Enhancing Numeric#step

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:42305] Re: Introducing
“rb_scan_keyword_args()” (was Re: Re: Enhancing Numeric#step)”
on Wed, 29 Sep 2010 11:21:09 +0900, “Akinori MUSHA”
[email protected] writes:

|e$B!!$b$&$@$$$V7P$D$N$G8e$[$IF~$l$h$&$H;W$$$^$9!#0J2<$N$h$&$Je(BAPIe$B$G$9!#e(B

e$B$$$l$k$3$H$=$N$b$N$K$OH?BP$G$O$J$$$s$G$9$,!"e(B

|num-of-mandatory-args := DIGIT ; The number of mandatory
| ; keywords
|
|sym-for-capture := “*” ; Indicates that all the
| ; keywords that are not on the
| ; list should be captured as a
| ; ruby hash.
|sym-for-raise := “!” ; Indicates that an
| ; ArgumentError should be
| ; raised if any keyword that
| ; are not on the list is given.
|sym-for-warning := “” ; Indicates that a soft warning
| ; should be emitted raised if
| ; any keyword that are not on
| ; the list is given.

e$B$3$NJU$NJ8K!$O9%$_$G$O$"$j$^$;$s!#e(B

e$B0z?t$r%7%s%%k$K$7$?$N$G$3$N$h$&$K$J$C$F$$$k$N$@$H;W$$$^$9$,!"e(B
e$B8D?ME*$K$Oe(B

  • e$B%7%s%%k$G$J$/J8;zNse(B
  • e$BJ8;zNsKvHx$Ke(B:e$B$,$D$$$F$$$?$ie(Boptional
    e$B$^$?$OJ8;zNsKvHx$Ke(B!e$B$,$D$$$F$$$?$ie(Bmandatory
  • “*” e$B$,$"$l$P;D$j$,%O%C%7%e$H$7$FEO$ke(B
  • “*” e$B$,;XDj$5$l$F$$$J$1$l$PNc30e(B
  • soft warninge$B$O$J$7e(B

e$B$r9M$($F$$$^$7$?!#$"$H4X?tL>$Oe(Brb_scan_keyword_argse$B$8$c$J$/$F!“e(B
rb_keyword_argse$B$,$$$$$+$J$”!#e(B

| /*
| * The keywords and are mandatory, and is optional;
| * If any other keyword arguments are given, an ArgumentError is raised.
| */
| rb_scan_keyword_args(opt, “2!”,
| rb_intern(“x”), &x, rb_intern(“y”), &y,
| rb_intern(“color”), &color, NULL);

e$B$Oe(B

rb_scan_keyword_args(opt,
“x”, &x, “y”, &y,
“color:”, &color, NULL);

e$B$H$J$j!"e(B

| /*
| * The keywords and are mandatory, and is optional;
| * If other keyword arguments are given, they are packed into a hash
| * and assigned to the variable rest.
| /
| rb_scan_keyword_args(opt, "2
",
| rb_intern(“x”), &x, rb_intern(“y”), &y,
| rb_intern(“color”), &color, NULL, &rest);

rb_scan_keyword_args(opt,
“x”, &x, “y”, &y,
“color:”, &color, “*”, &rest, NULL);

| /* Unknown parameters can just be dropped by passing a NULL. /
| rb_scan_keyword_args(opt, "2
",
| rb_intern(“x”), &x, rb_intern(“y”), &y,
| rb_intern(“color”), &color, NULL, NULL);

rb_scan_keyword_args(opt,
“x”, &x, “y”, &y,
“color:”, &color, “*”, NULL, NULL);

| /*
| * The keywords , , and are all optional;
| * If any other keyword arguments are given, a soft warning (only
| * reported in verbose mode) is emitted.
| */
| rb_scan_keyword_args(opt, “0”,
| rb_intern(“x”), &x, rb_intern(“y”), &y,
| rb_intern(“color”), &color, NULL);
|

rb_scan_keyword_args(opt,
“x:”, &x, “y:”, &y,
“color:”, &color, NULL);

e$B$H$$$&$N$r9M$($F$$$^$7$?!#e(B

                            e$B$^$D$b$He(B e$B$f$-$R$me(B /:|)

At Wed, 29 Sep 2010 16:10:27 +0900,
matz wrote:

この辺の文法は好みではありません。

引数をシンボルにしたのでこのようになっているのだと思いますが、
個人的には

  • シンボルでなく文字列

 メソッド呼び出しごとの rb_intern() のコストはどう考えますか?
現状の手書き処理ではほぼ漏れなくIDまたはSymbolを事前生成している
実態に即してIDを取れるようにしたのですが。

  • 文字列末尾に:がついていたらoptional
    または文字列末尾に!がついていたらmandatory
  • “*” があれば残りがハッシュとして渡る
  • “*” が指定されていなければ例外

 これも、呼び出しごとに切り出しとコピーを含む文字列処理が必要に
なるのが気になります。

 逆に動的生成のキーワード群を扱いたいシーンでも、自前でアロケート
&コピーする手間が生じて煩わしいのではないでしょうか。

 提案中の仕様は、所与のkeywordã‚’åŠ å·¥ã›ãšã«æ¸¡ã›ã‚‹åˆ©ç‚¹ãŒã‚ã‚Šã¾ã™ã€‚

å¿…é ˆå¼•æ•°:
rb_scan_keyword_args(opt, “1*”, rb_intern(keyword), &val, NULL,
&opt);

省略可能引数:
rb_scan_keyword_args(opt, “*”, rb_intern(keyword), &val, NULL,
&opt);

 なお、わざわざ * を渡さないと残り受け取れない仕様にしてあるのは
æ‹¡å¼µæ€§ãŒå¿µé ­ã«ã‚ã‚Šã¾ã™ã€‚è¿”ã‚Šå€¤ãŒãªã„ã®ã‚‚ãã†ã§ã™ãŒã€ä¸Šã®ä¾‹ã‚’è¦‹ã‚‹ã¨
キャプチャーした数を返すのが妥当な気がしてきました。

  • soft warningはなし

 確かになくてもいいのかも。

を考えていました。あと関数名はrb_scan_keyword_argsじゃなくて、
rb_keyword_argsがいいかなあ。

 動詞なしはちょっと…。rb_scan_kwargsくらいに縮めればいいですか?

At Wed, 29 Sep 2010 23:43:47 +0900,
matz wrote:

個人的には

  • シンボルでなく文字列
  • 文字列末尾に:がついていたらoptional
    または文字列末尾に!がついていたらmandatory

ã€€æœ«å°¾ã§ãªãå…ˆé ­ã®æ–¹ãŒæœ›ã¾ã—ãã†ã§ã™ã€‚è­˜åˆ¥å­ã®æœ«å°¾ã«ã‚‚!が置ける
ので(「method(x!:1)」も文法的に有効)曖昧さが生じます。

  • “*” があれば残りがハッシュとして渡る
  • “*” が指定されていなければ例外
  • soft warningはなし

 これはRubyで書くときも自力なのでそれでいいでしょうね。

At Wed, 29 Sep 2010 23:43:47 +0900,
matz wrote:

元々はrb_scan_keywordsでしたね。予約語と混同しそうなのでargs
ã‚’è¿½åŠ ã—ãŸã®ã§ã—ã‚‡ã†ã‹ã€‚ãŸã¨ãˆã°ã€ç§ã®ææ¡ˆã—ãŸä»•æ§˜ã®ã‚‚ã®ã‚’

rb_scan_kwargs()

とし、武者さんの仕様のものを

rb_scan_keyword_args()

として両方提供するというのはどうでしょう?

 ちなみに、私が最初に考えていた記法は次のようなもので、動的生成の
便宜や rb_intern() のコストを考えないならこちらの方が書きやすく、
わかりやすそうに思えます。

/* セミコロンはmandatoryとoptionalの区切り */
rb_scan_keywords(&opt, "x,y;color,size,*", &x, &y, &color, &size, 

&rest)

もしかしてまつもとさんにはこれならacceptableだったりしますか?

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:42308] Re: Introducing
“rb_scan_keyword_args()” (was Re: Re: Enhancing Numeric#step)”
on Wed, 29 Sep 2010 16:45:38 +0900, “Akinori MUSHA”
[email protected] writes:

|> * e$B%7%s%%k$G$J$/J8;zNse(B
|
|e$B!!%a%=%C%I8F$S=P$7$4$H$Ne(B rb_intern() e$B$N%3%9%H$O$I$&9M$($^$9$+!)e(B
|e$B8=>u$N<j=q$-=hM}$G$O$[$\O3$l$J$/e(BIDe$B$^$?$Oe(BSymbole$B$r;vA0@8@.$7$F$$$ke(B
|e$B<BBV$KB($7$Fe(BIDe$B$r<h$l$k$h$&$K$7$?$N$G$9$,!#e(B

e$B$b$A$m$sM}M3$OJ,$+$j$^$9!#$,!"@5D>e(BCe$B%3!<%I$r=q$/?H$H$7$F$O!"Khe(B
e$B2se(Binterne$B$r=q$/$N$,%$%d$G$9!#e(B

|e$B!!$3$l$b!"8F$S=P$7$4$H$K@Z$j=P$7$H%3%T!<$r4^$`J8;zNs=hM}$,I,MW$Ke(B
|e$B$J$k$N$,5$$K$J$j$^$9!#e(B

e$B$3$l$b!“%3%9%H$H=q$-$d$9$5$N%H%l!<%I%*%U$G$9$M!#;d$O=q$-$d$9e(B
e$B$5$rM%@h$9$k798~$,$”$j$^$9!#N>J}MQ0U$9$k$N$,$h$$$N$+$b$7$l$^e(B
e$B$;$s!#e(B

|e$B!!5U$KF0E*@8@.$N%-!<%o!<%I72$r07$$$?$$%7!<%s$G$b!“<+A0$G%”%m%1!<%He(B
|e$B!u%3%T!<$9$k<j4V$,@8$8$FHQ$o$7$$$N$G$O$J$$$G$7$g$&$+!#e(B
|
|e$B!!Ds0FCf$N;EMM$O!“=jM?$Ne(Bkeyworde$B$r2C9)$;$:$KEO$;$kMxE@$,$”$j$^$9!#e(B
|
|e$BI,?\0z?te(B:
| rb_scan_keyword_args(opt, “1*”, rb_intern(keyword), &val, NULL, &opt);
|
|e$B>JN,2DG=0z?te(B:
| rb_scan_keyword_args(opt, “*”, rb_intern(keyword), &val, NULL, &opt);

e$B3N$+$K$=$&$G$9$,!“F0E*@8@.$N%-!<%o!<%I$r;H$$$?$$6ILL$,$A$g$Ce(B
e$B$H;W$$$D$+$J$$$N$G!”$3$l$K$D$$$F$O@Q6KE*$K;?@.$7$^$;$s!#e(B

|e$B!!$J$*!“$o$6$o$6e(B * e$B$rEO$5$J$$$H;D$j<u$1<h$l$J$$;EMM$K$7$F$”$k$N$Oe(B
|e$B3HD%@-$,G0F,$K$“$j$^$9!#JV$jCM$,$J$$$N$b$=$&$G$9$,!”>e$NNc$r8+$k$He(B
|e$B%-%c%W%A%c!<$7$??t$rJV$9$N$,BEEv$J5$$,$7$F$-$^$7$?!#e(B

e$B!Ve(B* e$B$rEO$5$J$$$H;D$j<u$1<h$l$J$$;EMM!W$K$O;?@.$7$^$9!#e(B

|> e$B$r9M$($F$$$^$7$?!#$"$H4X?tL>$Oe(Brb_scan_keyword_argse$B$8$c$J$/$F!“e(B
|> rb_keyword_argse$B$,$$$$$+$J$”!#e(B
|
|e$B!!F0;l$J$7$O$A$g$C$H!D!#e(Brb_scan_kwargse$B$/$i$$$K=L$a$l$P$$$$$G$9$+!)e(B

e$B85!9$Oe(Brb_scan_keywordse$B$G$7$?$M!#M=Ls8l$H:.F1$7$=$&$J$N$Ge(Bargs
e$B$rDI2C$7$?$N$G$7$g$&$+!#$?$H$($P!";d$NDs0F$7$?;EMM$N$b$N$re(B

rb_scan_kwargs()

e$B$H$7!"Ip<T$5$s$N;EMM$N$b$N$re(B

rb_scan_keyword_args()

e$B$H$7$FN>J}Ds6!$9$k$H$$$&$N$O$I$&$G$7$g$&!)e(B

                            e$B$^$D$b$He(B e$B$f$-$R$me(B /:|)

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:42318] Re: Introducing
“rb_scan_keyword_args()” (was Re: Re: Enhancing Numeric#step)”
on Thu, 30 Sep 2010 13:47:57 +0900, “Akinori MUSHA”
[email protected] writes:

|> * e$B%7%s%%k$G$J$/J8;zNse(B
|> * e$BJ8;zNsKvHx$Ke(B:e$B$,$D$$$F$$$?$ie(Boptional
|> e$B$^$?$OJ8;zNsKvHx$Ke(B!e$B$,$D$$$F$$$?$ie(Bmandatory
|
|e$B!!KvHx$G$J$/@hF,$NJ}$,K>$^$7$=$&$G$9!#<1JL;R$NKvHx$K$be(B!e$B$,CV$1$ke(B
|e$B$N$G!J!Ve(Bmethod(x!:1)e$B!W$bJ8K!E*$KM-8z!K[#Kf$5$,@8$8$^$9!#e(B

e$B5-K!E*$K$O8e$m$K=q$$$?J}$,5$J,$,$h$$$N$G$9$,!"@hF,$KCV$/$N$Ge(B
e$B$bBE6($G$-$^$9!#$C$F$$$&$+!“e(BRubye$B%l%Y%k$G$Oe(Bmandatorye$B$J%-!<%o!<e(B
e$B%I0z?t$r;XDj$9$k9=J8$r9M$($F$$$J$$$s$G$9$,!”$=$l$C$F$3$H$O!"e(B
e$B$D$^$je(Brb_scan_keyword_argse$B$G$bBP1~ITMW$C$F$3$H$J$N$G$O$J$$$+e(B
e$B$H:#$5$i$J$,$i;W$$$^$7$?!#e(B

|e$B!!$A$J$$K!";d$,:G=i$K9M$($F$$$?5-K!$O<!$N$h$&$J$b$N$G!"F0E*@8@.$Ne(B
|e$BJX59$de(B rb_intern() e$B$N%3%9%H$r9M$($J$$$J$i$3$A$i$NJ}$,=q$-$d$9$/!"e(B
|e$B$o$+$j$d$9$=$&$K;W$($^$9!#e(B
|
| /* e$B%;%
%3%m%s$Oe(Bmandatorye$B$He(Boptionale$B$N6h@Z$je(B /
| rb_scan_keywords(&opt, "x,y;color,size,
", &x, &y, &color, &size, &rest)
|
|e$B$b$7$+$7$F$^$D$b$H$5$s$K$O$3$l$J$ie(Bacceptablee$B$@$C$?$j$7$^$9$+!)e(B

e$B$J$<e(Bopte$B$G$O$J$/e(B&opte$B$J$N$+$H$+!“5?Ld$O$”$C$?$j$7$^$9$,!"$3$A$ie(B
e$B$NJ}$,e(B([ruby-dev:42305]e$B0F$h$j$Oe(B)e$B$o$+$j$d$9$+$m$&$H$O;W$$$^$9!#e(B
e$B$?$@$7!"5-K!$H$7$F$O;d$N$b$Ne(B[ruby-dev:42307]e$B$NJ}$,9%$_$G$9!#e(B
e$B$J$<$+$H9M$($?;~$K!"e(B"x,y;color,size,*"e$B$H;XDj$9$k$3$H$K$h$kJ,e(B
e$B$+$j$d$9$5$N8~>e$HJ8;zNs$r$r9=J82r@O$9$k%3%9%H$,8+9g$C$F$$$Je(B
e$B$$$h$&$K46$8$k$+$i$N$h$&$K;W$($^$9!#e(B

                            e$B$^$D$b$He(B e$B$f$-$R$me(B /:|)

At Thu, 30 Sep 2010 23:45:05 +0900,
matz wrote:

|ã€€æœ«å°¾ã§ãªãå…ˆé ­ã®æ–¹ãŒæœ›ã¾ã—ãã†ã§ã™ã€‚è­˜åˆ¥å­ã®æœ«å°¾ã«ã‚‚!が置ける
|ので(「method(x!:1)」も文法的に有効)曖昧さが生じます。

è¨˜æ³•çš„ã«ã¯å¾Œã‚ã«æ›¸ã„ãŸæ–¹ãŒæ°—åˆ†ãŒã‚ˆã„ã®ã§ã™ãŒã€å…ˆé ­ã«ç½®ãã®ã§
も妥協できます。っていうか、Rubyレベルではmandatoryなキーワー
ド引数を指定する構文を考えていないんですが、それってことは、
つまりrb_scan_keyword_argsでも対応不要ってことなのではないか
と今さらながら思いました。

ã€€ç§ã®æƒ³å®šã¯ã™ã§ã«æç¤ºã—ã¦ã„ã¾ã™ãŒã€é †åºå¼•æ•°ã¨åŒã˜ã§ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå€¤ã‚’
æŒ‡å®šã—ãªã‹ã£ãŸã‚‰å¿…é ˆã§ã„ã„ã®ã§ã¯ãªã„ã§ã—ã‚‡ã†ã‹ã€‚

| ちなみに、私が最初に考えていた記法は次のようなもので、動的生成の
|便宜や rb_intern() のコストを考えないならこちらの方が書きやすく、
|わかりやすそうに思えます。
|
| /* セミコロンはmandatoryとoptionalの区切り /
| rb_scan_keywords(&opt, "x,y;color,size,
", &x, &y, &color, &size, &rest)
|
|もしかしてまつもとさんにはこれならacceptableだったりしますか?

なぜoptではなく&optなのかとか、疑問はあったりしますが、こちら

 誤記でした。

の方が([ruby-dev:42305]案よりは)わかりやすかろうとは思います。
ただし、記法としては私のもの[ruby-dev:42307]の方が好みです。
なぜかと考えた時に、"x,y;color,size,*"と指定することによる分
かりやすさの向上と文字列をを構文解析するコストが見合っていな
いように感じるからのように思えます。

 このコスト感をどうも私は共有できないんですよね…。末尾に ! を
ç½®ãã¨å¿…é ˆå¼•æ•°ã¨ã™ã‚‹ã¨ã„ã†ä»•æ§˜ã‚‚ã‚„ã¯ã‚Šæ–‡å­—èµ°æŸ»ã¨åˆ‡ã‚Šå‡ºã—ãŒå‰æ
なので、コスト面での差はあまりないと思うのです。