[Gauche-devel-jp] case-lambdaの挙動

Back to archive index
Shiro Kawai shiro****@gmail*****
2018年 11月 18日 (日) 21:54:52 JST


そのcase-lambdaフォームは不正ですが、Gaucheがエラーを出していないだけです。

1) (case-lambda ((<formals> <body> ...) ...))
で、<formals>に来ることができるのは、R7RSの(lambda <formals> <body> ..) の
<formals>と同じです。つまり

(<variable> ...)
(<variable> ...  . <varlable>)
<variable>

のいずれかの形式しか許されません。問題のcase-lambdaの最初の節では<formals>が((a))になっていて、これは許される形式ではありません。

2)
Gaucheは実行に差し支えない場合にエラー検出を省略することがよくあります。case-lambdaのコンパイルでは、各節の<formals>が受け取る引数の個数を数えてディスパッチテーブルを作るのですが、その時は単に数だけ数えていて引数の部分が実際に<variable>になっているかどうかをチェックしていません。なので((a))も(b)も「引数がひとつの場合」と解釈され、どちらか一方のみが有効になります(今回の場合は最初の節)。そして、その節内ではaはローカル変数とは認識されておらず、グローバルなaが参照されます。

なお、仕様としては、不正なプログラムを実行した場合の挙動は未定義です。なので元が不正なら何が起きても「想定どおり」です。

3) おそらく元のコードは、パターンマッチで (f 1) と (f '(1))
を区別したいという意図だったのではありませんか。RnRS内でそれを一発でやるフォームはありませんが、util.matchのmatch-lambda*を使えば可能です。

(use util.match)
(define f
  (match-lambda*
    [((a)) (print "a:" a)]
    [(b)  (print "b:" b)]))

gosh> (f 1)
b:1
#<undef>
gosh> (f '(1))
a:1
#<undef>







On Sun, Nov 18, 2018 at 2:32 AM akim muto <work.****@gmail*****>
wrote:

> メーリングリストの皆さんはじめまして、akimと名乗っております。
>
> (define a "global")
> (define f
>   (case-lambda
>    (((a)) (print a))
>    ((b) (print b))))
> と定義して実行すると
> (f "1")→global
> という結果になるのですが、これはたまたまそういう結果になっているのでしょうか。それとも想定通りの動作なのでしょうか。
> _______________________________________________
> Gauche-devel-jp mailing list
> Gauch****@lists*****
> https://lists.osdn.me/mailman/listinfo/gauche-devel-jp
-------------- next part --------------
HTMLの添付ファイルを保管しました...
URL: <https://lists.osdn.me/mailman/archives/gauche-devel-jp/attachments/20181118/4e0e9576/attachment.html>


Gauche-devel-jp メーリングリストの案内
Back to archive index