Действительно ли возрастающее Макроопределение возможно?

Я часто нахожу следующий тип возрастающего определения полезным:

(define (foo) (display "bar"))
(foo)
;prints bar
(define foo (let ((bar foo))
              (lambda ()
                (display "foo")
                (bar))))

(foo)
;prints foobar

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

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

Править:

Наивно я хотел бы сделать следующее:

(define-syntax foo
  (syntax-rules ()
    ((_) (display "bar"))))

(define-syntax foo
  (let-syntax ((old-foo (syntax-rules () ((_) (foo)))))
    (syntax-rules ()
      ((_) (begin
             (display "foo")
             (old-foo))))))

Перевод наивных макросов к работе plt макросы схемы:

(require-for-syntax scheme/base) 
(define-syntax foo
  (syntax-rules ()
    [(foo) (display "bar")]))
(define-syntax foo
  (let ([old (syntax-local-value #'foo)])
    (lambda (stx)
      #`(begin #,((syntax-rules ()
               [(_) (begin (display "foo"))]) stx)
             #,(old #'(_))))))
(foo)

Если я пропускаю лучший сообщенный мне метод.

6
задан Davorak 4 May 2010 в 08:39
поделиться

5 ответов

FWIW (и это определенно не много, так как это в значительной степени упражнение по тренировке мишеней ногами), вот как вы бы сделали это в схеме PLT с помощью только макросов гигиенических синтаксических правил :

(define-syntax foo
  (syntax-rules ()
    [(foo x) (list 'x '= x)]))
(define-syntax foo
  (let ([old (syntax-local-value #'foo)])
    (compose (syntax-rules ()
               [(_ x ...) (list 'begin x ... 'end)])
             old)))
(printf ">>> ~s\n" (foo (+ 1 2)))

Это не будет работать внутри модуля, только на REPL - и это хорошо . Можно сделать что-то подобное и в модулях, но если вы собираетесь это сделать, вы также можете использовать процедурные макросы (также известные как макрос синтаксиса syntax-case ) с идентификатором, привязанным к уровень синтаксиса и `set! '- указав его значение, чтобы расширить его. Все еще не лучшая идея и все еще может привести к кровотечению из глаз, но некоторым людям нравится причинять себе вред ...

(О, и кстати - даже это все еще совершенно не связано с тем, являются ли рассматриваемые макросы гигиеничными или нет.)

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

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

Изменить: в Common Lisp это возможно. Я не могу вспомнить, чтобы когда-нибудь видел, чтобы это использовалось в исходном коде.

Добавление поведения к функциям или макросам часто называется «советом» или «советом» в сообществе Common Lisp. Некоторые инструменты «советовать» также могут давать советы по макросам.

3
ответ дан 10 December 2019 в 02:44
поделиться

Как насчет let * ?

(define foobar
    (let* ((foo (lambda () (display "foo")))
           (bar (lambda () (foo) (display "bar"))) )
            bar))
0
ответ дан 10 December 2019 в 02:44
поделиться

Я думаю, вы могли бы добиться этого, используя негигиеничные макросы, которые, как я полагаю, поддерживает PLT Scheme. Тогда вы будете использовать точно такие же механизмы, как и при работе с обычными функциями, поскольку макросы будут обычными функциями, которые работают с S-выражениями.

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

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

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

Обратите внимание, что макросы - это не просто некоторые функции с дополнительной магией ! Макросы - это совсем другое дело.

Возможно, вы ищете что-то вроде комбинаций методов в Common Lisp?

3
ответ дан 10 December 2019 в 02:44
поделиться