Функция обхода схемы в виде списка

Разве нельзя трактовать функции в Scheme как любой другой список?

По сути, я хочу сделать что-то вроде этого:

(define (foo) "hello")

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

Я нашел подобное обсуждение по этому поводу, и я чувствую себя немного разочарованным, если это невозможно с Схемой. Если так, то почему это невозможно? Возможно ли это на других губах?

РЕДАКТИРОВАТЬ: изменено (cdr 'foo) на (cdr foo) - это вводило в заблуждение. Я спрашиваю, почему я не могу получить доступ к функции в виде списка?

7 ответов

Решение

Я часто хотел быть в состоянии сделать то же самое 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
>

В коварстве,

guile> (define (foo bar) 'baz)
guile> (процедура-источник foo)
(лямбда (бар) (цитата баз))
guile> (cdr (процедура-источник foo))
((бар) (цитата баз))
лукавства>

Ваш define Форма это не функция, а определение функции. На самом деле, это сокращение для

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

Lambda можно рассматривать как "вызов компилятора". В этом случае он создает функцию, которая возвращает эту строку. Define затем связывает эту функцию с символом 'foo,

Сравните это с

(define foo "hello")

которая связывает только строку с символом 'foo, Что бы (cdr foo) вернуть?

Теперь можно себе представить, что некоторая реализация Scheme на самом деле сохраняет или имеет возможность сохранить lambda Форма при привязке функции к символу. Вы должны будете проверить документацию, но вид чистой интерпретации, который это подразумевает, несомненно, повлияет на производительность.

Если вам удастся получить это, он вернет lambda форма, а не define форма.

Схема MIT имеет возможность сделать это. (Если вы действительно хотите, прокомментируйте это, и я дам вам код. Мне нужно было найти некоторые недокументированные функции, чтобы это произошло.)

Однако это не входит в определение языка Scheme, поэтому реализации не должны позволять это. Причина этого заключается в том, что для того, чтобы сделать функции быстрее, хорошая реализация Схемы будет модифицировать функции. Это означает как переписать их на другом языке (либо машинный код, либо что-то довольно низкоуровневое), так и удалить любые ненужные биты, например, + В общем случае функция должна проверять, являются ли ее аргументы числами, и если да, то какого рода числами, но если ваша функция является циклом, который вызывает +, вы можете просто проверить один раз в начале, и сделать функцию намного быстрее.

Конечно, вы все еще можете хранить списки без особых проблем, даже со всеми этими вещами. Но если бы вы попытались изменить списки, как бы это работало?

(Опять же, вы могли бы заставить это работать. Это просто было бы больше работы для разработчиков, и поскольку это обычно не используется в программах, большинство людей, вероятно, просто не хотят беспокоиться.)

Вы можете получить доступ к функции в виде списка, используя pp или же pretty-print, Тем не менее, вам также может понадобиться запустить ваш код в режиме отладки. Однако это очень зависит от реализации. Я знаю, что это может работать в Gambit-C.

(define (foo) ...) производит скомпилированный объект, а это значение - процедура.
Вы не можете перебрать его, потому что это не s-выражение.

Как и то, что другие предложили, вы должны проверить свою среду программирования и увидеть
если у него есть какие-либо возможности для таких задач.

'foo оценивает символ, вы не можете взять CDR символа.

Вы можете захотеть сделать это (cdr foo), но это не работает. Значение FOO - это процедура, а не список.

Другие вопросы по тегам