поиск альтернативы для привязки let для определения-синтаксиса

Я пытаюсь обновить старый код guile 1.8 до guile 3.x. Я изо всех сил пытаюсь найти хорошую замену той или иной конструкции.

Вот пример, представляющий старый код 1.8:

(define h (make-hash-table 31))

(define (def-node name-args types)
  (let ((name (car name-args))
        (args (cdr name-args)))
    (hashq-set! h name
                (list name args types))))

(define define-node
  (defmacro:syntax-transformer
    (lambda arg-list
      (apply def-node arg-list)
      #f)))

(define (make-nodes)
  (let ((def define-node))
    (def (a b . c) (BT . CT))
    (def (d e . f) (ET . FT))))

(make-nodes)

(display (hashq-ref h 'a))
(newline)
(display (hashq-ref h 'd))
(newline)

Я надеюсь обновить define-node и / или def-node, оставив make-nodes без изменений. Пока что я переписал define-node вот так:

(define-syntax define-node
  (lambda (x)
    (syntax-case x ()
      [(_ name-args arg-types)
       #'(def-node 'name-args 'arg-types)])))

Это кажется разумной заменой define-node, но он не работает с текущим make-nodes, let в make-nodes недействителен. Я должен заменить make-nodes на это:

(define (make-nodes)
    (define-node (a b . c) (BT . CT))
    (define-node (d e . f) (ET . FT)))

Это нормально, но мне интересно, можно ли найти решение, при котором мне не нужно изменять make-nodes?


person Andrew    schedule 29.01.2021    source источник


Ответы (1)


Вам нужно будет изменить make-nodes. Если вы думаете о таком выражении, как

(let ((def define-node))
  (def (a b . c) (BT . CT))
  (def (d e . f) (ET . FT))))

Это то же самое, что и

((λ (def)
   (def (a b . c) (BT . CT))
   (def (d e . f) (ET . FT)))
 define-node)

Затем оценка (def (a b . c) (BT . CT)) включает в себя сначала оценку аргументов ... которая завершится ошибкой.

Мне не ясно, как это могло работать с нормальной версией let.

Поэтому вам нужно будет использовать что-то вроде let-syntax для создания локального макроса. Не знаю, есть ли это у Гайла, но если нет, то должно.


Я думаю, что следующее будет работать в схеме R5RS, если вы добавите make-hasheqv и hash-set!. Я тестировал это на самом деле с помощью Racket, но используя язык модуля R5RS с подходящим #%require для получения битов хеширования:

(define h (make-hasheqv))

(define (def-node name-args types)
  (let ((name (car name-args))
        (args (cdr name-args)))
    (hash-set! h name
                (list name args types))))

(define (make-nodes)
  (let-syntax ((def (syntax-rules ()
                      ((_ name-args types)
                       (def-node 'name-args 'types)))))
    (def (a b . c) (BT . CT))
    (def (d e . f) (ET . FT))))
person Community    schedule 30.01.2021