8

Scheme の関数を他のリストと同じように扱うことはできませんか?

基本的に、私がやりたいことは次のようなものです:

(define (foo) "hello")

(cdr foo)  ; or similar, should return the list ((foo) "hello")

これに関する同様の議論を見つけました。Scheme でこれができないとしたら、少しがっかりします。もしそうなら、なぜこれが不可能なのですか?他のLispでは可能ですか?

編集: (cdr 'foo) を (cdr foo) に変更 -- 誤解を招くものでした。関数にリストとしてアクセスできない のはなぜですか?

4

7 に答える 7

3

私はしばしば同じことを csl できるようにしたいと思っていました。以下は、mzscheme でこれを行う方法の簡単な例です。

DrScheme 4.2

(module qdefine mzscheme
  (provide ;(all-from-except mzscheme let)
   (rename define olddefine)
   (rename quote-define define)
   (rename quote-cdr cdr)
   (rename quote-car car))

  (define define-list '())
  (define define-list-add 
    (lambda (key value)
      (set! define-list (cons `(,key ,value) define-list))))

  (define-syntax quote-define
    (syntax-rules ()
      ((_ (pro-name args ...) body ...) 
       (begin
         (define (pro-name args ...) body ...)
         (define-list-add pro-name  '((pro-name args ...) body ...))))
      ((_ pro-name pro) (begin
                          (define pro-name pro)
                          (define-list-add pro-name 'pro)))

      ))

  (define quote-cdr (lambda (lst)
                      (if (procedure? lst)
                          (cdr (cadr (assoc lst define-list)))
                          (cdr lst))))

  (define quote-car (lambda (lst)
                      (if (procedure? lst)
                          (car (cadr (assoc lst define-list)))
                          (car lst))))
  )
(require 'qdefine)

(define testfunc (lambda (args) args))
(cdr testfunc)
(car testfunc)

(define (testfunc2 test) 'blah)
(cdr testfunc2)
(car testfunc2)

(define testlist '(1 2 3 4 5 6 'a))
(cdr testlist)
(car testlist)

出力:

((args) args)
lambda
('blah)
(testfunc2 test)
(2 3 4 5 6 'a)
1
>
于 2010-03-06T23:09:05.590 に答える
2

フォームdefineは関数ではなく、関数定義です。実際、それはの省略形です

(define foo
  (lambda ()
    "hello"))

Lambda「コンパイラ呼び出し」と考えることができます。この場合、その文字列を返す関数を生成します。 Define次に、この関数をシンボルにバインドします'foo

これと比較して

(define foo "hello")

これは、文字列だけをシンボルにバインドします'foo。何を(cdr foo)返しますか?

lambdaさて、関数をシンボルにバインドするときに、Scheme 実装が実際にフォームを保存するか、フォームを保存するオプションを持っていることが想像できます。ドキュメントを確認する必要がありますが、これが意味する純粋な解釈の種類は、パフォーマンスに確実に影響を与えます。

ただし、これを取得できた場合lambdaは、フォームではなくフォームが返されdefineます。

于 2010-03-06T18:42:49.140 に答える
2

MIT スキームには、これを行う機能があります。(本当に必要な場合は、これについてコメントしてください。コードを提供します。それを実現するために、文書化されていない関数をいくつか見つけなければなりませんでした。)

ただし、Scheme 言語の定義には含まれていないため、実装で許可する必要はありません。この理由は、関数を高速化するために、優れた Scheme 実装が関数を変更するためです。これは、それらを別の言語 (マシンコードまたはかなり低レベルのもの) で書き直すことと、必要のないビットを取り除くことの両方を意味します+。関数が を呼び出すループの場合は+、最初に 1 回チェックするだけで、関数を大幅に高速化できます。

もちろん、これらすべてを使用しても、それほど問題なくリストを保持できます。しかし、リストを変更しようとすると、どのように機能するでしょうか?

(繰り返しますが、それを機能させることはできます。実装者にとっては、より多くの作業が必要になるだけです。通常、プログラムでは使用されないため、ほとんどの人はおそらく気にしたくないでしょう。)

于 2010-03-06T18:56:58.167 に答える
2

ガイルで、

guile> (define (foo bar) 'baz)
guile> (procedure-source foo)
(lambda (bar) (quote baz))
guile> (cdr (procedure-source foo))
((bar) (quote baz))
guile >

于 2010-03-12T01:16:45.713 に答える
1

またはを使用して、リストとして関数にアクセスできる場合があります。とはいえ、コードをデバッグ モードで実行する必要がある場合もあります。ただし、これは実装に大きく依存します。Gambit-C で動作することはわかっています。pppretty-print

于 2010-03-06T18:35:25.807 に答える
1

(define (foo) ...)コンパイルされたオブジェクトを生成し、それは-プロシージャーです。これはs-expression
ではないため、反復できません。

他の人が提案したように、プログラミング環境を調べて、
そのようなタスクのための機能があるかどうかを確認する必要があります.

于 2010-03-06T18:47:47.883 に答える
1

'foo はシンボルに評価されます。シンボルの CDR を取得することはできません。

やりたいことは (cdr foo) ですが、これはうまくいきません。FOO の値は手続きであり、リストではありません。

于 2010-03-06T18:14:50.727 に答える