Генериране на клаузи за изискване с макроси на Racket

Добре, трябва да съм много глупав. Опитвам се да създам макрос (част от по-голямо начинание), който при дадена функция я обгръща в свой собствен подмодул, след което я requires, така че функциите, дефинирани по този начин, да не могат да се забъркват с околните термини, но останалата част от техния хост модулът може да ги използва както обикновено. Може би това не е добра идея, но ме усмихнете – не виждам защо е невъзможно.

Имам следния минимален примерен код в два файла.

tinylang.rkt:

(provide (all-defined-out))

(define-syntax (modularise stx)
  (syntax-case stx ()
[(_ func)
 (with-syntax ([mod (datum->syntax stx 'testmodule)]
               [nm  (datum->syntax stx 'working)]
               )
   #`(begin

       (print (list "Defining module " 'mod))(newline)

       (module mod racket
         (provide nm)
         (define  nm func)
       )

       (require (for-syntax (submod "." mod))) ;; at least kills a syntax error
       (require (for-template (submod "." mod))) ;; doesn't help
    ))]))

tinyimp.rkt:

#lang racket
(require "tinylang.rkt")
(modularise (lambda () (display "this works!")))
; the following line would make everything work!
;(require (submod "." testmodule))
(working)

Чувствам се виновен, че спамя този сайт с въпроси, които смятам, че трябва да са тривиални за мен, за да разреша с документацията, но все още не ми е ясно какво се случва на какъв етап. Ако някой знае добър ресурс (книга, лекция, доклад), ще се радвам да чуя за него. Знам за документацията на Racket, която е наистина обширна, но често пропускам важните подробности в обясненията там.


person RogerTheDragon    schedule 17.09.2013    source източник
comment
Въпреки че не знам дали ще го намерите за полезно, написах Страх от макроси.   -  person Greg Hendershott    schedule 17.09.2013
comment
Добре, моята интуиция за проблема е, че синтаксисът/идентификаторът nm се създава с лексикална информация, която го поставя извън новия модул mod, нещо като. Може би греша. Така или иначе нямам идея как да поправя това.   -  person RogerTheDragon    schedule 17.09.2013
comment
@GregHendershott, нали, попаднах на това – ще му обърна малко повече внимание. Благодаря за насоката, може би трябва да го разгледам обстойно.   -  person RogerTheDragon    schedule 17.09.2013
comment
Вашият въпрос ме озадачи. Тъй като е свързано с въпрос, който видях на [email protected] миналата седмица, аз публикува съобщение там току-що.   -  person Greg Hendershott    schedule 17.09.2013
comment
Споменах това в другата ви публикация, но неотдавнашният разговор на Матю Флат за Clojure/West обяснява много за макросите на Racket (макар че може би не точно този проблем): infoq.com/presentations/racket   -  person stchang    schedule 18.09.2013
comment
Всъщност вече гледах тази презентация два пъти, но не мисля, че разбирам 100% от подробностите. Всеки път става все по-добре :) Благодаря за насоките, @stchang и @Greg!   -  person RogerTheDragon    schedule 18.09.2013


Отговори (1)


Да, макрогенерираните изисквания и предоставяния са трудни. Техният ключ е лексикалния обхват на изискваната спецификация (т.е. (submod "." testmodule)).

От документи :

В изисква ... генераторът на изискващата спецификация определя обхвата на обвързванията.

С други думи, спецификацията на изискването и употребата на необходимите идентификатори трябва да имат еднакъв обхват.

Ето версия на tinylang.rkt, която ще работи:

#lang racket

(provide (all-defined-out))

(define-syntax (modularise stx)
  (syntax-case stx ()
    [(_ func)
     (with-syntax ([require-spec (datum->syntax stx '(submod "." testmodule))])
       #`(begin
           (module testmodule racket
             (provide working)
             (define working func))
           (require require-spec)))]))
person stchang    schedule 17.09.2013
comment
Вярно, наистина вече бях открил чрез проба-грешка, че позицията на require е от решаващо значение, така че предполагам, че следващата логична стъпка е това, което предлагате. Виждайки отговорите на този и предишния ми въпрос, предполагам, че начинът за свързване на код наистина е като този, който показвате, като използвате with-syntax. Както и да е, много ви благодаря, още веднъж! Имам чувството, че нямам RTFM, така че ще се опитам повече да разбера какво е написано. - person RogerTheDragon; 18.09.2013
comment
Мисля, че ученето според нуждите, както правите вие, е правилният начин и изглежда, че вече разбирате повечето от основите. Безцелното четене на документи без конкретна цел обикновено води до незапазване на нищо, поне за мен. - person stchang; 18.09.2013