質問するログイン新規登録
LISP

LISPはプログラミング言語の一種であり、関数型言語に分類されています。 特徴として、括弧を多様する独特の構文を持ちます。

Common Lisp

Common Lispは、複数のLISP方言を統合した言語で、LISPの標準です。LISPの特徴を持ちつつ、他のプログラミングパラダイムも取り入れています。人工知能などの領域で多く用いられている言語です。

Q&A

1回答

457閲覧

関数を変数に束縛させる方法

tf2014

総合スコア75

LISP

LISPはプログラミング言語の一種であり、関数型言語に分類されています。 特徴として、括弧を多様する独特の構文を持ちます。

Common Lisp

Common Lispは、複数のLISP方言を統合した言語で、LISPの標準です。LISPの特徴を持ちつつ、他のプログラミングパラダイムも取り入れています。人工知能などの領域で多く用いられている言語です。

0グッド

0クリップ

投稿2022/12/29 20:15

編集2022/12/29 21:29

0

0

関数を他のシンボルに束縛することができますか?

例えば、SchemeのREPLに以下を入力すると期待通りが表示されます。

Scheme

1 (let ((x *)) 2 (x 2 2)) 34

同じことをSBCLで試すと、"illegal function call"というエラーになります。そこで、xinspectしてみると束縛されていないようです。

LISP

1CL-USER> (let ((x *)) 2 (inspect x)) 3 4The object is a SYMBOL. 50. Name: "NIL" 61. Package: #<PACKAGE "COMMON-LISP"> 72. Value: NIL 83. Function: "unbound" ;; <------ 束縛されていない 94. Plist: NIL 10>

グローバル変数でも同じ結果になります。

LISP

1CL-USER> (defparameter y *) 2Y 3CL-USER> (inspect 'y) 4 5The object is a SYMBOL. 60. Name: "NIL" 71. Package: #<PACKAGE "COMMON-LISP"> 82. Value: NIL 93. Function: "unbound" ;; <------ 束縛されていない 104. Plist: NIL 11> q 12; No values

Common Lispでは関数をシンボルに束縛することはできないのでしょうか? 

よろしく、お願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2022/12/30 01:32

(let ((x '*)) (funcall x 2 2)) か、 (let ((x '*)) (apply x '(2 2))) でしょう。
otn

2022/12/30 04:25

Common Lispの処理系が手元に無いですが、Emacs-Lispだと、letでは無理ですが、 (fset 'x '*) (x 2 2) => 4
tf2014

2022/12/31 00:53

melianさん、otnさん、 お返事ありがとうございます。'funcall`と`apply`をつかったら、出来ました。`fset`はcommon-lispでは"undefined function"になりました。`setf`で試してみましたができませんでした。 お2人の知恵を貸していただいて、ありがとうございます。
otn

2023/01/01 06:09

「関数」でなく「関数名(のシンボル)」をセットすれば良いのであれば、funcallで良いかと思います。
tf2014

2023/01/01 17:26

ありがとうございます。 (慣れないせいか、funcall の表記のほうが、見やすいです)
melian

2023/01/01 17:50

参考までに、setf の場合は、 (setf (fdefinition 'x) #'*) とします。
guest

回答1

0

Schemeのシンボルは言っちゃえば単なるトークンなんだけど、ANSI Common Lispのシンボルは、C言語で言う「構造体」みたいなモノで定義されたれっきとしたデータ型となる。

Python

1class Symbol(obj): 2 def __init__(self): 3 self.val = None 4 self.function = None 5 self.plist = None

上のPythonで書いたコードはANSI Common Lispでのシンボル実装のような疑似コードなんだけど、いずれにせよ、ANSI Common Lispではシンボルは「シンボル型」と言って良いようなデータ型で、最低でも変数用スロット、関数用スロット、あとは属性リスト用スロット、と言うスロット/フィールドを備えている。
結果、ANSI Common Lispでは一つのシンボルで最低でも3つの役割を果たす。言い換えると、ANSI Common Lispの名前空間は最低でも3つあり、これがANSI Common Lispの特徴の一つ、なんだ。
これをLisp-2な言語と呼ぶ。最低でも3つなのにLisp-2とは是如何に、なんだけど、名前空間が2つ以上設定されているプログラミング言語はすべてLisp-2だ。Lispじゃなくても通例、Lisp-2と呼ぶ。Lisp-2な言語には、他にはRubyがある。
一方、C言語やScheme、Python等、フツーの言語は名前空間が一つしかない。同名の変数と関数は同時に定義出来ない。このような名前空間が一つしかないプログラミング言語をLisp-1な言語と呼ぶ。これもLispじゃなくてもLisp-1だ。「C言語/JavaはLisp-1です」・・・・・・違和感があるけど、通例だとそう表現する。

さて、そうなると、だ。「変数用の名前空間」と「関数用の名前空間」が分かれている以上、同じキーワード(Lispだと「特殊形式」とか「マクロ」とか呼ぶが)で変数と関数は定義出来ない。
ここがLisp-1なSchemeとLisp-2なANSI Common Lispでは違う。
Schemeは変数名も関数名も同じ名前空間に属するので、同じキーワードletで関数も変数も束縛可能だ。と言うより、関数がファーストクラスオブジェクトである以上、変数と関数には機能的な差がないんだ。
何故なら、変数名に関数を束縛する、って事は変数に関数オブジェクトを束縛する、と言う意味になり、「関数オブジェクト」と言う「データ型」と言う存在は性質的には1, 2と言う整数とか"hoge!"と言う文字列と何ら変わらない。
よってそもそも理論的には、Lisp-1では関数がファーストクラスオブジェクトなら関数定義そのものが不必要だ、と言う結論になり、実際Schemeでは変数名と関数オブジェクトを結びつける事は出来るが他言語で言う関数定義が存在しない
Lisp-1であるC言語は、関数がファーストクラスオブジェクトじゃないんで関数定義構文が必要となる。
一方、同じくLisp-1であるPythonでは、関数がファーストクラスオブジェクトなので、理論的には関数定義構文(def)は要らないんだ。

ところが、Lisp-2であるANSI Common Lispだと事情が変わってくる。繰り返すが、変数用の名前空間と関数用の名前空間に分かれてるから、だ。
結果、Lisp-1と違い、関数がファーストクラスオブジェクトでも関数定義構文は変数定義構文と別に存在する必要が出てくる、んだ。
Schemeのletは局所変数定義用だけど、関数がファーストクラスオブジェクトな以上、関数も束縛可能だ。
一方、ANSI Common Lispではそうはいかない。
しかし、ANSI Common Lispのletでは「シンボルそのもの」を束縛は可能で(つまり「未評価の」...「クオートされた」シンボル)、その「シンボルそのもの」からどのスロットに収められた値を取り出すか、は自在に調整出来る。

Lisp

1CL-USER> (let ((x '*)) 2 (funcall x 2 2)) 34 4

これが故に、ANSI Common Lispユーザーはしばしば「Schemeにはシンボルがない」と言うんだ。明らかにANSI Common LispのシンボルはSchemeに比べると(不必要に)高機能だ。
(Schemeだとシンボルを一旦クオートすると「それを解除出来ない」・・・Schemeでもせめてsymbol-valueがあればいいのに、って思った事は数知れず、だ。)

Lisp

1The object is a SYMBOL. 20. Name: "*" 31. Package: #<PACKAGE "COMMON-LISP"> 42. Value: 4 53. Function: #<FUNCTION *> 64. Plist: NIL 7>

これはグローバル変数(と言うか、ANSI Common Lispでは動的変数)でも事情は変わらない。

Lisp

1CL-USER> (defparameter y '*) 2Y 3CL-USER> (inspect y) 4 5The object is a SYMBOL. 60. Name: "*" 71. Package: #<PACKAGE "COMMON-LISP"> 82. Value: Y 93. Function: #<FUNCTION *> ;; <------ 束縛されている 104. Plist: NIL 11>

投稿2025/07/21 12:18

編集2025/07/21 12:37
cametan

総合スコア104

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問