タイトルどおりだとしたら、高橋さんに一票。
Matzにっき(2007-02-05)高橋(Maki)さんによる:=オペレータへの反対意見。思っているよりもずっとずっと人生は短い。
「:=」をどういうときに使えばいいか説明するのが難しそう(特に初心者に)
また、Rubyのローカル変数のスコープの点に気がついた彼[引用者註:Larry Wall]はやっぱりとても鋭い人だと思います
私にとっても、Rubyのスコープルールは一番違和感があるところでして。
例えば、以下のコードは、
foo = 1 loop do puts foo foo = 2 puts foo break end puts foo
1,2,2と出力しますが、以下のPerl Codeは1,2,1です。
$\="\n"; # so print does puts our $foo = 1; { print $foo; my $foo = 2; print $foo; } print $foo;
JavaScriptはまた特殊でして、var宣言された変数はlexical scopeの内側からは見えません。
// double-click to execute var foo = 1; (function(){ alert(foo); // undefined var foo = 2; alert(foo); // 2 })(); alert(foo); // 1
よって厳密にはfunction localといいます。
話をRubyに戻します。それだけならまだいいのですが、Perlで$scalar
,@array
,%hash
,&subroutine
,*typeglob
と型の違いを示すのに使っている記号(Perl語でsigil)が、local
,$global
,@instance
,@class
とスコープの違いに使われているところも面食らうところです。もっともPerl 6では、twigilといって、$*ARGS
, &?BLOCK
, という具合に、二番目の記号で特殊変数を区別するようになっているのでちょっとRuby的になっていますが、それでも$.instance
のように、用途が直感的にわかる記号の選び方をしています。まあ後だしじゃんけんゆえ当然なのですが。
で、:=
です。Matz案では
foo = 1 loop do puts foo foo := 2 puts foo break end puts foo
とすると1,2,1と出力される、すなわち:=
で代入した変数は、Perlのmy変数と同じ扱いになる、ということを想定しているのでしょうか?会話の流れからするとどうもそのようなのですが。以下、そうだとして話を進めます。
これ、混迷をさらに深める事になると思います。スコープを記号で切り替えるのでもすでに違和感大きいのに、今度は演算子となると...PerlからmyをパクるなりJavaScriptからvarをパクるなりした方が RSL (Ruby as Second Language) のユーザーにやさしいと思います。
さらに、Perl 6で:=
がbinding operatorとして使われていることもあります。要は変数の別名を作る演算子で、例えば以下のコードは1,2と出力します。
my $a = 1; my $b := $a; say $b; $a = 2; say $b;
まあそれを言ったらPascalでは:=
が代入ですし、別の言語だし演算子に別の意味があってもいいですし、グラスの底に顔があったって芸術は爆発しているからいいのですが(なんのこっちゃ)、the principle of least surpriseから行くと、too surprisingなのではないでしょうか。
....待てよ、
|foo| = 1
というのはいかがでしょう?これだと絶対確実にblock localなiterator variableとの整合性も取れますし。foo := 1
よりはRubyishに見えます。|foo|
というのは一番rubyらしいconstructですし。キーストロークが増えるという意見もありますが、
|foo, bar, baz| = 1, 2, 3
とやればそれも気にならないでしょう。
Dan the Broken Ruby Speaker
foo <- 1
local({
cat(foo,"\n")
foo <- 2
cat(foo,"\n")
})
cat(foo,"\n")
なら 121
foo <-1
repeat{
cat(foo,"\n")
foo <- 2
cat(foo,"\n")
break
}
cat(foo,"\n")
なら 122
localやfunctionは無名環境を作ります
ブロック内のスコープは貴方次第。
昔のインタプリタの名残?で":="の残骸があって、
":=" <- function (x, value)
{
assign(deparse(substitute(x)), value, envir = parent.env(environment()))
}
hoge := runif(100) * 1000
も出来るとか。
任意の演算子を作る場合は %で挟んで
> "%(^_^)%"<-function(x,value){x+value}
> 1 %(^_^)% 2
[1] 3
等と何でもあり...