开发者

Traversing Scheme function as a list

Isn't it possible to treat functions in Scheme as any other list?

Basically, what开发者_开发知识库 I want do to is something like this:

(define (foo) "hello")

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

I've found a similar discussion about this, and I feel a bit disappointed if this is not possible with Scheme. If so, why is this impossible? Is it possible in other lisps?

EDIT: Changed (cdr 'foo) to (cdr foo) -- it was misleading. I'm asking, why can't I access a function as a list?


I have often wanted to be able to do the same thing csl. Below is a quick example of how you could go about doing this in 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)

Outputs:

((args) args)
lambda
('blah)
(testfunc2 test)
(2 3 4 5 6 'a)
1
>


Your define form is not a function but a function definition. In fact, it is a shorthand for

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

Lambda can be thought of as a "compiler invocation". In this case, it produces a function which returns that string. Define then binds this function to the symbol 'foo.

Compare this to

(define foo "hello")

which binds just the string to the symbol 'foo. What would (cdr foo) return?

Now, it is imaginable that some Scheme implementation actually saves or has the option to save the lambda form when binding a function to a symbol. You will have to check the documentation, but the kind of pure interpretation this implies surely would have an impact on performance.

If you manage to get this, though, it will return the lambda form, not the define form.


MIT Scheme has the ability to do this. (If you really want, comment on this and I'll give you the code. I had to find some undocumented functions to make it happen.)

However, it's not in the Scheme language definition, so implementations don't have to allow it. The reason for this is that in order to make functions faster, a good Scheme implementation will modify the functions. This means both rewriting them in a different language (either machine code or something fairly low-level) and taking out any bits you don't need - for instance, the + function must in general check whether its arguments are numbers, and if so, what sort of numbers, but if your function is a loop which calls +, you can just check once at the beginning, and make the function a lot faster.

Of course, you could still keep the lists around without too much trouble, even with all of these things. But if you tried to modify the lists, how would it work?

(Again, you could make it work. It would just be more work for implementers, and since it's not usually used in programs, most people probably just don't want to bother.)


In guile,

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


'foo evaluates to a symbol, you can't take the CDR of a symbol.

What you may want to do is (cdr foo), but this does not work. The value of a FOO is a procedure, not a list.


You might be able to access the function as a list using pp or pretty-print. That said, you might also need to run your code in debug mode. This is very implementation dependent however. I know it can work in Gambit-C.


(define (foo) ...) produces a compiled object, and it's a value - a procedure.
You cannot iterate over it because it is not an s-expression.

Like what other suggested, you should check out your programming environment and see
if it has any facilities for such tasks.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜