Ryo.Fの日記: なんでやねん>PowerShellのスコープ 4
いや、なんでかは解らんではないんだが…
まあ、論よりコード。
PS C:\> function f{ $a; $a=$a+1; $a}
PS C:\> $a=9; $a; f; $a
9
9
10
9
PS C:\>
関数定義で、等号の左側と最後の$aはローカル変数、それ以外はグローバル変数だ。
つまり、こう動いている。
PS C:\> function f{ $global:a; $local:a=$global:a+1; $local:a}
PS C:\> $a=9; $a; f; $a
9
9
10
9
PS C:\>
つまりこういうことか?
右辺値としては、ローカルスコープを越えてグローバルスコープまで探索する。
一方左辺値としては、ローカルスコープのみを探索し、未定義ならば、ローカル変数として定義する。
やってることは理解できるが、バグの温床だろ。
もう一つ。
PS C:\> function f{$a; $a.x = 5; $a}
PS C:\> $a = [PSObject] @{x=3}; $a; f; $a;
Name Value
---- -----
x 3
x 3
x 5
x 5
PS C:\>
まあ、こうなるだろうな、とは思うが。
ちなみに、同じようなコードをRubyでは:
irb(main):001:0> def f; puts a; a=a+1; puts a; end
=> nil
irb(main):002:0> a=9; puts a; f; puts a
9
NameError: undefined local variable or method `a' for main:Object
from (irb):1:in `f'
from (irb):2
from /usr/bin/irb:12:in `<main>'
irb(main):003:0>
関数定義の最初のputs aでエラーになる。
( ゚д゚)ポカーン (スコア:0)
なにわけのわからんこと言ってんのこの人…。
そもそもPowerShellって、既にもう名前にShellと入ってるのになに言ってんの?
まさかと思うけど、仮にshで書いたとして。
shでは、local指定もしてないのに、いきなりローカル変数ができるとでも思ってんの?
無知って次元じゃないだろもう…。
更に「Rubyで書いた同じようなコード」とか称するクソコードが、どう見ても同じようなコードじゃない件について。
自分でここまで「ローカルスコープとグローバルスコープがどうたら」という駄文を書いてきた癖して、
「Rubyで書いた同じようなコード」とか称する、読むのも苦痛なクソコードにはグローバル変数が定義されてないとかね。(笑)
何から何まで支離滅裂だろ。
自分がどれだけおかしな主張繰り広げてるかわからないの?
Re:( ゚д゚)ポカーン (スコア:1)
そもそもPowerShellって、既にもう名前にShellと入ってるのになに言ってんの?
いわゆる普通のシェルと、PowerShellの動きが同じなら、君の指摘は正しい。
でも、実際には違うんだよ。
shでは、local指定もしてないのに、いきなりローカル変数ができるとでも思ってんの?
そんなことは知ってるよ。
つまり、君はこういうことを言っているわけだろ?
君の言うように、いきなりローカル変数ができたりはしない。
特に指定しない限り、すべてグローバル変数として扱われる。
一方、PowerShellではそうではない。
PowerShellでは、いきなりローカル変数ができる。
出力結果を見れば違いは明らかなんだが、どうかね?
無知って次元じゃないだろもう…。
君がな(失笑)。
いや、君は無知と言うよりは、粗忽かな(笑)。
多少は知識があるようだからね。
更に「Rubyで書いた同じようなコード」とか称するクソコードが、どう見ても同じようなコードじゃない件について。
君は、最初の勘違いが激しすぎて、私の意図も誤解しちゃたんだね。
私は、Rubyでは関数の外のスコープが勝手に参照されたりしない、と言うことを示した。
外のスコープを参照したければ、明示的に指定する必要がある。
一方、PowerShellは、外のスコープが勝手に参照されるのに、代入ではローカル変数が外のスコープは参照されず、勝手に変数が作られてしまう。
粗忽な君にもそろそろ違いが解ってきただろ?
自分がどれだけおかしな主張繰り広げてるかわからないの?
解らない。
君に指摘がおかしいのは、よく解るよ(笑)。
ダイナミックスコープ (スコア:0)
PowerShellの変数スコープは、今時珍しいダイナミックスコープなんですよ。
(しかしよく気がつきましたね。)
$a = $a + 1
を処理する時は、左辺に手をつける前、ローカルの$aが生成・処理される前に、右辺を処理するので
その時点で検索すれば、$a は既に存在するグローバルなものが見つかる。
大昔の素朴なLispインタープリタは、ダイナミックスコープでしたが、今時のLispも、Rubyも
レキシカルスコープです。実装が楽なのでしょうが、確かにこれは、バグの元になりますねえ。
Re:ダイナミックスコープ (スコア:1)
しかしよく気がつきましたね。
ちょっとした規模のプログラムを今PowerShellで書いてて気づきました。
副作用のある関数を書いたのですが、$script:などのスコープ修飾子を書かなければいけないところと、そうでないところがあることから、ちょっと調べてみた、というわけです。
確かにこれは、バグの元になりますねえ。
コーディング規約として、ローカルスコープ以外の変数には必ずスコープ修飾子を付けよ、とすべきなんですかね。
Set-StrictModeあたりで強制できるといいんじゃないかと思うんですが。