--no-scope-shadowingオプションって?
fish shellで関数定義する際,function
に--no-scope-shadowing(-S)
オプションを付けると外側のスコープの変数を参照できるようになります.
色々なことができそうなオプションですけれど,具体的にどんな使い途があるか考えてみました.
使ってみる
インクリメント演算子もどき
function ++ --no-scope-shadowing
if set -q "$argv[1]"
set $argv[1] (math $$argv[1] + 1)
end
end
set a 1
++ a
echo $a #=> 2
外側の変数に触れる,ということですぐに思いついたのがこちら.やんごとない理由1によりforループでなくwhileループを書かなければいけないときに役立つかもしれません.fish
はインクリメントするだけでもset a (math $a + 1)
って書かないといけませんからね...
ちなみにデクリメント演算子--
は関数名として認められていないため再現不可です.
変数名と値を表示
function p --no-scope-shadowing
for arg in $argv
echo "$arg: $$arg"
end
end
set a "Hello, fish!"
p a #=> a: Hello, fish!
変数の名前から値を調べられるのを利用.副作用は伴いません.デバッグに役立ちそう?
スワップ
function swap --no-scope-shadowing
if begin; set -q "$argv[1]"; and set -q "$argv[2]"; end
set -l tmp $$argv[1]
set $argv[1] $$argv[2]
set $argv[2] $tmp
end
end
set a 1
set b 2
p a b #=> a: 1 b: 2
swap a b
p a b #=> a: 2 b: 1
ふたつの変数の値を交換.$argv[i]
で変数の名前を,$$argv[i]
で変数の値を取得しています.こういう$
が連続する記法,他のシェルでもできるんですかね?
ふたつの配列を引数に取る
配列を2個受け取ってその共通項を返します.
function intersect --no-scope-shadowing
if begin; set -q "$argv[1]"; and set -q "$argv[2]"; end
for i in $$argv[1]
if contains $i $$argv[2]
echo $i
end
end
end
end
set a 1 2 3 4 5
set b 3 4 5 6 7
intersect a b #=> 3 4 5
配列を展開せずに関数に渡せるのがミソです.
fishは引数がargv
という一つの配列に格納されるので,--no-scope-shadowing
を使わずにintersect $a $b
と呼び出すような実装にするとargv
のどこまでが一つ目の配列に由来するのかが分からなくなります.
おわりに
もっと色々なことができそうな気がするのですが,思いつきませんでした.何かアイデアがあればコメント等で教えていただけると幸いです.
訂正
記事タイトルが--no-scope-shading
になっていたのを,--no-scope-shadowing
に直しました.
-
fish-shellビルトイン関数縛りで
seq
が封印されている場合とかですね! ↩