背景

とあるネット記事のGaucheのコードを読んでいて ^ _ ( 何か処理 ) というのがあってこれは何だと思って調べたメモです。

^ 自体は知っていたのですが、 ^ _ という別の記法もあるのかなと不思議に思ったので。

無名関数

公式ドキュメント: 4.3 手続きを作る

Gaucheの無名関数は lambda で書きます。

gosh> ( lambda ( a b ) ( + a b )) #<closure ( #f a b ) > gosh> (( lambda ( a b ) ( + a b )) 1 2 ) 3

lambda は ^ という略記もあります。

Special Form: ^ formals body … ^はlambdaの短い別名です。これはGauche独自の拡張です。

gosh> ( ^ ( a b ) ( + a b ) 1 2 ) #<closure ( #f a b ) > gosh> (( ^ ( a b ) ( + a b )) 1 2 ) 3 gosh>

lambda もしくは ^ は引数部分を (a) ではなく a にすると可変長引数を受け取ります。

variable : 手続きは不定個の引数を取ります。 実引数は新しいリストに集められて、そのリストがvaribleに束縛されます。 ((lambda a a) 1 2 3) ⇒ (1 2 3)

gosh> ( ^ ( x ) x ) #<closure ( #f x ) > gosh> (( ^ ( x ) x ) 10 ) 10 gosh> ( ^ x x ) #<closure ( #f . x ) > gosh> (( ^ x x ) 10 ) ( 10 ) gosh> (( ^ x x ) 10 20 ) ( 10 20 ) gosh> (( ^ ( x ) x ) 10 20 ) *** ERROR: wrong number of arguments: #f requires 1, but got 2 While compiling "(standard input)" at line 8: (( ^ ( x ) x ) 10 20 ) gosh>

冒頭の ^ _ はこれを意図した書き方だったのかもしれません。

他の言語でもイディオムとして良くあるように、引数を使わないことを意味するため _ にしていたのだと思います。実際使っていなかったので。

またこれらとは別に、 ^c というのもあります。

Macro: ^c body … (lambda (c) body …)の短縮表記です。 cには#[_a-z]に含まれる任意の一文字が使えます。 (map (^x (* x x)) ‘(1 2 3 4 5)) ⇒ (1 4 9 16 25)

gosh> (( ^x ( + 1 2 ))) 3 gosh> (( ^_ ( + 1 2 ))) 3

スペースがあると前述の (#f . x) になるので注意が必要です。最初この違いに気付けず、スペース付きのまま試して期待通りにいかず悩みました。

gosh> ( ^x ( + 1 2 )) #<closure ( #f x ) > gosh> ( ^ x ( + 1 2 )) #<closure ( #f . x ) >

ちなみに部分適用に向いた cut というのもあります。

Macro: cut expr-or-slot expr-or-slot2 … [SRFI-26] 手続きを簡潔に書ける便利なマクロです。 いわゆる部分適用を実現するために使えます。

gosh> ( cut + 1 2 ) #<closure ( #f ) > gosh> (( cut + 1 2 )) 3 gosh> ( cut + <> <> ) #<closure ( #f #<identifier srfi-26##<identifier srfi-26#x.126a9c0>.1293ee0> #<identifier srfi-26##<identifier srfi-26#x.126a9c0>.1293e00> ) > gosh> (( cut + <> <> ) 1 2 ) 3

本来はmapとかfor-eachとかそういうやつで使うべきな気がします。

gosh> ( map ( ^a ( + a 1 )) '( 1 2 3 )) ( 2 3 4 ) gosh> ( map ( cut + <> 1 ) '( 1 2 3 )) ( 2 3 4 )

余談: 調べ方

今回のような記号( ^ )に関するリファレンスを調べる場合でも apropos と info で簡単に辿り着けるのがとても良いです。

gosh> ( apropos ' ^ ) ^ ( gauche ) ^-generator ( gauche ) ^_ ( gauche ) ^a ( gauche ) ^b ( gauche ) ^c ( gauche ) ^d ( gauche ) ^e ( gauche ) ^f ( gauche ) ^g ( gauche ) ^h ( gauche ) ^i ( gauche ) ^j ( gauche ) ^k ( gauche ) ^l ( gauche ) ^m ( gauche ) ^n ( gauche ) ^o ( gauche ) ^p ( gauche ) ^q ( gauche ) ^r ( gauche ) ^s ( gauche ) ^t ( gauche ) ^u ( gauche ) ^v ( gauche ) ^w ( gauche ) ^x ( gauche ) ^y ( gauche ) ^z ( gauche ) define-^x ( gauche ) gosh> ( info ' ^ )

余談

公開前にプレビューで推敲したらlambdaに著作権発生してた。