8

是否可以将 Scheme 中的函数视为任何其他列表?

基本上,我想做的是这样的:

(define (foo) "hello")

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

我发现了一个类似的讨论,如果这在 Scheme 中是不可能的,我会感到有点失望。如果是这样,为什么这是不可能的?其他lisps有可能吗?

编辑:将 (cdr 'foo) 更改为 (cdr foo) - 它具有误导性。我在问,为什么我不能以列表的形式访问函数?

4

7 回答 7

3

我经常希望能够做同样的事情 csl。下面是一个快速示例,说明如何在 mzscheme 中执行此操作。

博士计划 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 语言定义中,因此实现不必允许它。这样做的原因是为了让函数更快,一个好的Scheme实现会修改函数。这意味着用不同的语言(机器代码或相当低级的东西)重写它们并取出你不需要的任何位 - 例如,+函数通常必须检查它的参数是否是数字,如果是,什么样的数字,但如果你的函数是一个调用 的循环+,你可以在开始时检查一次,并使函数更快。

当然,即使有所有这些东西,您仍然可以保留列表而不会带来太多麻烦。但是,如果您尝试修改列表,它将如何工作?

(同样,你可以让它工作。这对实现者来说只是更多的工作,而且由于它通常不用于程序,大多数人可能只是不想打扰。)

于 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

'foo 计算为符号,您不能获取符号的 CDR。

您可能想要做的是 (cdr foo),但这不起作用。FOO 的值是一个过程,而不是一个列表。

于 2010-03-06T18:14:50.727 回答
1

也许可以使用pp或以列表形式访问该函数pretty-print。也就是说,您可能还需要在调试模式下运行代码。然而,这非常依赖于实现。我知道它可以在 Gambit-C 中工作。

于 2010-03-06T18:35:25.807 回答
1

(define (foo) ...)产生一个编译的对象,它是一个- 一个过程
您不能对其进行迭代,因为它不是s-expression

就像其他人建议的那样,您应该检查您的编程环境,看看
它是否有任何用于此类任务的设施。

于 2010-03-06T18:47:47.883 回答