2016-03-22 16 views
2

私は最近CLを学び始めました。関数の名前空間のシンボルに値を設定できるかどうかを調べようとしています。関数名前空間の関数を値で定義できますか?

機能の構成や単に既存の機能(たとえば、おもちゃ "Hello、World!"レベルのプロジェクトでidentityを2回書き直すだけで)を定義したいと考えています。名前空間の分離を壊す可能性があるかどうかは確かではありません。私もmacroexpandに何を試しましたかdefun実際にはします。それは初心者として私にはあまりにもわかりにくいですが、それの中核部分が組み込まれているようです(私はSBCLを使用しています)。

代わりに言っての:

(defun myfn (x) x) 

私はむしろちょうど言うと思います:

(def..? myfn identity) 

私はそれを行うことができない場合、どのように私はコードの重複のこのクラスを避けることができますか? (同義語を作成するだけではなく、機能構成によって作成された機能を含みます)。現在の環境で、シンボルにバインドされた機能のために可能です

+0

ちょっと考えてみましょう。(defun myfun(&rest args)(identity argsを適用)) 'に展開するマクロを追加することができます。もちろん、Lisp-1では 'myfn identityを定義する 'ことができます。 – Cactus

+2

複製からリンクされている機能の一部を確認してください。周囲に浮かぶ有益な情報がたくさんあります。 ** defunが(setq )と同じではないというタイトルのものは、いくつかの良い議論があります。 –

+1

また、明確にするために、 '# ''表記を使ってシンボルの関数値を得ることができます。つまり、(let((id(lambda(x)x)))(compose id ...)) 'を実行する必要はありません。あなたは '(let((id# 'identity))(compose id ...))'や '(compose#' identity ...)'を実行できます。 –

答えて

5

:そこもほとんど同じことを(setf FDEFINTION)ですが、またsetfの機能をサポートしています

(setf (symbol-function 'myfn) #'identity) 

レキシカルバインドされた関数(FLETLABELS)では、それを行うことはできません。それは現在の環境でそれを行うこと(setf fdefinition)

CL-USER 11 > (setf (fdefinition 'myfn) #'identity) 
#<Function IDENTITY 410003F974> 

CL-USER 12 > (myfn 10) 
10 

さらに発言

注意を使用してシンボルの機能を設定する方法

例。関数はコンパイル時にいつものように知られているであろう。したがって

(defun myfn (x) x) 

(eval-when (:compile-toplevel :load-toplevel :execute) 
    (setf (fdefinition 'myfn) #'identity)) 

ターの利点のようなものに置き換えられるかもしれません。心に留めておくべき事柄の

ワン:

シンボルオブジェクトはいくつかの情報を運ぶことができます。 1があった場合たとえば、元の関数名、:

CL-USER 13 > #'identity 
#<Function IDENTITY 410003F974> 

は、シンボルの関数セルを設定するには、それを変更しません:

CL-USER 14 > #'myfn 
#<Function IDENTITY 410003F974> 

それは、元の内部名と同じ関数オブジェクトです。一つは、その名前にアクセスすることができるかもしれませんが、一つは、それを変更することはできません。

CL-USER 18 > (nth-value 2 (function-lambda-expression #'identity)) 
IDENTITY 

自己再帰関数での問題もあります:

CL-USER 19 > (defun foo (n) 
       (if (zerop n) 
        1 
       (* n (foo (1- n))))) ; here foo calls the function foo 
FOO 

は今、私たちは機能を使用するようにBARを設定するにはここでFOO

CL-USER 20 > (setf (symbol-function 'bar) #'foo) 
#<interpreted function FOO 4060004084> 


CL-USER 21 > (bar 10) 
3628800 

我々はFOOを再定義:

CL-USER 22 > (defun foo (n) 
       (if (zerop n) 
        1 
       (+ n (foo (1- n))))) 
FOO 

BARは、古いFOOを引き続き使用します。これは、新しいFOOを呼び出す場合としない場合があります。

CL-USER 23 > (bar 10) 
460 

OOPS! FOOを変更しましたが、BARには奇妙な影響があります。最初の繰り返しは古いFOOであり、次の再帰呼び出しは新しいFOOです。

BARおよびFOOは、同じ機能の2つの異なるバージョンです。しかし、両方とも関数FOOを呼び出します。これは、コードをどのように解釈したりコンパイルするかによって、古い関数または新しい関数である可能性があります。

CL-USER 24 > #'foo 
#<interpreted function FOO 40600041F4> 

CL-USER 25 > #'bar 
#<interpreted function FOO 4060004084> 
関連する問題