Есть ли в Racket функция, которая возвращает лямбда-выражение процедуры? - PullRequest
5 голосов
/ 01 февраля 2020

В одном варианте Common Lisp (я думаю, что это был CMUCL, но я могу ошибаться - я больше не могу его найти) была функция, которая (я думаю) называлась function-lambda-expression. Если бы он получил процедуру, он распечатал лямбда-выражение, которое его сгенерировало. Пример:

(let ((my-thunk (lambda () (+ 1 2))))
    (write my-thunk)
    (write (function-lambda-expression my-thunk)))

Это напечатало бы что-то вроде:

#<PROCEDURE>
(LAMBDA () (+ 1 2))

Это было ужасно полезно для отладки и изучения языка.

Я ищу функционировать, как это в Racket. Я просмотрел документацию Racket , но не могу найти ничего подобного. (Однако я бы не удивился, если бы не заметил этого.) Есть ли эквивалент в Racket?

1 Ответ

8 голосов
/ 01 февраля 2020

Нет. lambda Racket создает замыкание, которое не запоминает его S-выражение (или объект синтаксиса). Обычно он запоминает свое имя (или его сокращенное исходное местоположение, если никакое имя не может быть выведено), и этого достаточно, чтобы помочь с отладкой. (См. object-name.)

Вы можете создать свой собственный вариант lambda, который имеет эту функцию, используя соответствующие структуры Racket и простой макрос. Вот базовый c пример:

#lang racket

(struct exp-closure (f exp)
  #:property prop:procedure (struct-field-index f))

(define-syntax-rule (exp-lambda formals . body)
  (exp-closure (lambda formals . body)
               (quote (exp-lambda formals . body))))

(let ([my-thunk (exp-lambda () (+ 1 2))])
  (printf "fun is ~v\n" my-thunk)
  (printf "exp is ~v\n" (exp-closure-exp my-thunk))
  (printf "result is ~v\n" (my-thunk)))

Это производит

fun is #<procedure:...tmp/lambda.rkt:11:19>
exp is '(exp-lambda () (+ 1 2))
result is 3

Лучшая версия этого макроса может распространить исходное местоположение макроса на выражение lambda, которое оно создает, или предполагаемое имя (см. syntax-local-infer-name), или оба.

...