【问题标题】:Traversing Scheme function as a list遍历 Scheme 函数作为列表
【发布时间】:2011-01-24 12:14:48
【问题描述】:

难道不能把 Scheme 中的函数和其他列表一样对待吗?

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

(define (foo) "hello")

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

我找到了a similar discussion 关于这个,如果这在Scheme 中是不可能的,我会感到有点失望。如果是这样,为什么这是不可能的?其他lisps有可能吗?

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

【问题讨论】:

标签: reflection lisp scheme metaprogramming homoiconicity


【解决方案1】:

在诡计中,

诡计>(定义(foo bar)'baz)
诡计>(程序源 foo)
(lambda (bar) (quote baz))
诡计> (cdr (procedure-source foo))
((bar) (quote baz))
诡计>

【讨论】:

    【解决方案2】:

    我经常希望能够做同样的事情 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
    >
    

    【讨论】:

    • 有人知道如何在其他方案实现中做到这一点吗?
    • 根据实现,我认为您可以使用 defmacro 或 Syntatic 闭包做类似的事情。我想要(define blah (lambda ...))(define blah (lambda (...) new code (blah ...))) 的宏等价物,但我还没有找到允许的方案实现一种直接的方式来做到这一点。
    【解决方案3】:

    MIT 计划有能力做到这一点。 (如果你真的想要,请对此发表评论,我会给你代码。我必须找到一些未记录的函数来实现它。)

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

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

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

    【讨论】:

    • 当然,我很乐意获得代码。也许在网上发布(gist/pastebin)?
    • 很抱歉 - 我以为我拥有它,但我只是看了看并找不到它。我基本上是通过下载 mit-scheme 源代码,找到它们如何表示解释程序,并使用该文件中的一些函数来实现的,这些函数恰好在 REPL 中可用,尽管它们可能不应该存在。跨度>
    【解决方案4】:

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

    像其他建议一样,您应该检查您的编程环境并查看
    如果它有任何设施来完成这些任务。

    【讨论】:

      【解决方案5】:

      您的define 表单不是函数,而是函数定义。其实它是一种简写形式

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

      Lambda 可以被认为是“编译器调用”。在这种情况下,它会生成一个返回该字符串的函数。 Define 然后将此函数绑定到符号'foo

      比较一下

      (define foo "hello")
      

      仅将字符串绑定到符号'foo(cdr foo) 会返回什么?

      现在,可以想象,在将函数绑定到符号时,某些 Scheme 实现实际上会保存或可以选择保存 lambda 表单。您将不得不检查文档,但是这意味着这种纯粹的解释肯定会对性能产生影响。

      如果你设法得到这个,但是,它将返回 lambda 表单,而不是 define 表单。

      【讨论】:

      • 很好的解释!难道不能创建我自己的定义表单,既编译代码(通过 eval)又保留源代码?那会很有帮助。
      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

        • 是的;我在问为什么我不能 cdr 程序。
        • 因为程序不是列表。您只能 cdr 列表。该过程可能是一堆机器指令。
        • 这不是一个非常令人满意的答案——你可以对列表说同样的话,因为你并不真正知道列表在内存中是如何表示的。
        • @csl:CDR 是为 conses 和 list 定义的。而已。所以 CDR 适用于列表。由于程序不是列表,因此它不起作用。过程是另一回事。
        猜你喜欢
        • 2014-05-03
        • 1970-01-01
        • 1970-01-01
        • 2020-07-18
        • 2019-11-25
        • 2021-12-31
        • 1970-01-01
        • 2011-02-26
        • 1970-01-01
        相关资源
        最近更新 更多