LoginSignup
0
1

More than 5 years have passed since last update.

fish関数定義の--no-scope-shadowingオプションで遊ぶ

Last updated at Posted at 2017-04-20

--no-scope-shadowingオプションって?

fish shellで関数定義する際,function--no-scope-shadowing(-S)オプションを付けると外側のスコープの変数を参照できるようになります.

色々なことができそうなオプションですけれど,具体的にどんな使い途があるか考えてみました.

使ってみる

インクリメント演算子もどき

++.fish
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)って書かないといけませんからね...
ちなみにデクリメント演算子--は関数名として認められていないため再現不可です.

変数名と値を表示

p.fish
function p --no-scope-shadowing
    for arg in $argv
        echo "$arg: $$arg"
    end
end
set a "Hello, fish!"
p a #=> a: Hello, fish!

変数の名前から値を調べられるのを利用.副作用は伴いません.デバッグに役立ちそう?

スワップ

swap.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個受け取ってその共通項を返します.

intersect.fish
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に直しました.


  1. fish-shellビルトイン関数縛りでseqが封印されている場合とかですね! 

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1