LINUX.ORG.RU

экспорт определений для 1-й фазы

 


0

1

такой способ:

#lang racket

(module proc-module racket
  (provide make-stx)

  (define (make-stx) #''i-am-syntax)
  
  )


(require (for-syntax 'proc-module))

(define-syntax (transformer stx) (make-stx))

(transformer)

возвращает ошибку
quote: unbound identifier;
 also, no #%app syntax transformer is bound
  at: quote
  in: (quote i-am-syntax)

такой

#lang racket


(module proc-module racket
  (provide (for-syntax make-stx))

  (define-for-syntax (make-stx) #''i-am-syntax)
  
  )


(require 'proc-module)

(define-syntax (transformer stx) (make-stx))

(transformer)
работает, но неудобен по некоторым причинам.

Почему не работает первый способ и работает второй?

Как сделать правильно в манере первого способа (без define-for-syntax)?


Должно быть

#lang racket

(module proc-module racket
  (provide make-stx)

  (define (make-stx) ''i-am-syntax)
  
  )


(require (for-syntax 'proc-module))

(define-syntax (transformer stx) 
  (datum->syntax stx (make-stx)))

(transformer)

Не надо таскать через границу модуля синтаксические объекты.

monk ★★★★★
()
Ответ на: комментарий от monk

Не надо таскать через границу модуля синтаксические объекты.

Почему? Они как-то с этим трансформером связываются?

В экспортирующем модуле много генераторов синтаксиса, наподобие

#lang racket

(module proc-module racket
  (provide make-stx)

  (define (make-stx)
    (with-syntax ([(expr ...) (make-exprs)])
      (syntax->datum #'(list expr ...))))

  
  (define (make-exprs)
    #'('expr1 'expr2))
  
  )


(require (for-syntax 'proc-module))

(define-syntax (transformer stx)
  (datum->syntax stx (make-stx)))

(transformer)

Придется много прописывать datum->syntax, syntax->datum, что сильно ухудшит читаемость. Можно как-нибудь сделать в таком духе:
#lang racket

(module proc-module racket
  (provide make-stx)

  (define (make-stx)
    (with-syntax ([(expr ...) (make-exprs)])
      #'(list expr ...)))

  
  (define (make-exprs)
    #'('expr1 'expr2))
  
  )

(require (for-syntax 'proc-module))

(define-syntax (transformer stx)
  (give-required-information (make-stx)))

(transformer)
?

qweqwe
() автор топика

Почему не работает первый способ и работает второй?

В первом способе (make-stx) возвращает биндинг quote для фазы 0, который в фазе 1 не определён.

Во втором — возвращает биндинг для фазы 1 — всё работает.

Ещё можно сделать так:

#lang racket

(module proc-module racket
  (provide make-stx)

  (define (make-stx) #'i-am-syntax))


(require (for-syntax 'proc-module))

(define-syntax (transformer stx)
  #`'#,(make-stx))

(transformer)
Тоже работает так как quote в результирующий синтаксис попадает из transformer (значит фаза 1).

monk ★★★★★
()
Ответ на: комментарий от qweqwe

Можно как-нибудь сделать в таком духе:

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

(module proc-module racket
  (provide make-stx)

  (define (make-stx list quote app)
    (with-syntax ([(expr ...) (make-exprs quote)]
                  [list list]
                  [#%app app])
      #'(#%app list expr ...)))
  
  (define (make-exprs quote)
    (with-syntax ([quote quote])
      #'('expr1 'expr2))))

(require (for-syntax 'proc-module))

(define-syntax (transformer stx)
  (make-stx #'list #'quote #'#%app))

(transformer)

monk ★★★★★
()
Ответ на: комментарий от qweqwe

В экспортирующем модуле много генераторов синтаксиса

А почему их не завернуть в begin-for-syntax? Ведь для фазы 0 они всё равно не несут смысла

monk ★★★★★
()
Ответ на: комментарий от monk

А почему их не завернуть в begin-for-syntax?

Я о нем не знал :). То что нужно, спасибо. И за объяснения тоже.

qweqwe
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.