Пересечение Схемы функционирует как список

Разве не возможно рассматривать функции в Схеме как какой-либо другой список?

В основном, что я хочу, делают к, что-то вроде этого:

(define (foo) "hello")

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

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

Править: Измененный (CDR 'нечто) к (нечто CDR) - это вводило в заблуждение. Я спрашиваю, почему я не могу получить доступ к функции как к списку?

8
задан csl 6 March 2010 в 18:22
поделиться

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
>
3
ответ дан 5 December 2019 в 14:02
поделиться

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

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

. Лямбда может рассматриваться как «вызов компилятора». В этом случае он создает функцию, которая возвращает эту строку. Определите , затем привяжите эту функцию к символу 'foo .

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

(define foo "hello")

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

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

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

2
ответ дан 5 December 2019 в 14:02
поделиться

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

1
ответ дан 5 December 2019 в 14:02
поделиться

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

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

1
ответ дан 5 December 2019 в 14:02
поделиться

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

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

1
ответ дан 5 December 2019 в 14:02
поделиться

В guile,

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

2
ответ дан 5 December 2019 в 14:02
поделиться

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

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

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

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

.
2
ответ дан 5 December 2019 в 14:02
поделиться