From: shugo@... (MAEDA Shugo) Date: 1998-11-22T19:20:10+09:00 Subject: [ruby-dev:3627] Re: block local variable (Re: スコープの範囲) --Multipart_Sun_Nov_22_19:20:36_1998-1 Content-Type: text/plain; charset=ISO-2022-JP 前田です。 >>>>> In [ruby-dev:3626] >>>>> "前田" == MAEDA Shugo wrote: 前田> foo = 0 前田> iter { 前田> foo ::= 1 # ブロックローカルになる。演算子はSatherから借用:-) 前田> } 前田> p foo #=> 0 前田> っていうのはどうでしょう。 前田> これだと名前の衝突を避けられるので、ブロックローカル変数の 前田> メリットが増すと思います。 試しにちょっと実装してみました。 演算子は:=にしました。 # Rubyは代入が=なので。 --Multipart_Sun_Nov_22_19:20:36_1998-1 Content-Type: application/octet-stream; type=patch Content-Disposition: attachment; filename="parse.y.diff" Content-Transfer-Encoding: 7bit --- parse.y.orig Sun Nov 22 17:40:57 1998 +++ parse.y Sun Nov 22 18:47:26 1998 @@ -201,6 +201,7 @@ %token tCOLON2 /* :: */ %token tCOLON3 /* :: at EXPR_BEG */ %token tOP_ASGN /* +=, -= etc. */ +%token tDYNA_ASGN /* := */ %token tASSOC /* => */ %token tLPAREN /* ( */ %token tLBRACK /* [ */ @@ -217,7 +218,7 @@ %left kOR kAND %right kNOT %nonassoc kDEFINED -%right '=' tOP_ASGN +%right '=' tOP_ASGN tDYNA_ASGN %right '?' ':' %nonassoc tDOT2 tDOT3 %left tOROP @@ -619,6 +620,16 @@ } fixpos($$, $3); } + | tIDENTIFIER tDYNA_ASGN arg + { + if (!dyna_in_block()) + yyerror("Can't declare block local variable here"); + if (!dyna_var_defined($1)) { + dyna_var_asgn($1, TRUE); + } + $$ = assignable($1, $3); + fixpos($$, $3); + } | primary '[' aref_args ']' tOP_ASGN arg { NODE *args = NEW_LIST($6); @@ -2761,6 +2772,10 @@ } lex_state = EXPR_DOT; return tCOLON2; + } + else if (c == '=') { + lex_state = EXPR_BEG; + return tDYNA_ASGN; } pushback(c); if (lex_state == EXPR_END || ISSPACE(c)) { --Multipart_Sun_Nov_22_19:20:36_1998-1 Content-Type: text/plain; charset=ISO-2022-JP これで、 foo = 0 1.times { foo := 1 p foo #=> 1 } p foo #=> 0 となります。 :=ではなく=を使った場合の動作は従来通りです。 前田> 個人的にはfoo = 1とした時は、既にブロックローカルとしてfooが宣言されて 前田> ないかぎり、普通のローカル変数への代入とみなす方が便利な気もしますが。 こちらも実装は簡単そうですね。 問題はこの変更が望ましいかどうかですが。 -- 前田 修吾 (mailto:shugo@aianet.ne.jp) --Multipart_Sun_Nov_22_19:20:36_1998-1--