Как написать макрос схемы, который определяет переменную, а также получает имя этой переменной в виде строки? - PullRequest
1 голос
/ 28 мая 2010

Это в основном продолжение этого вопроса . Я решил просто помнить о YAGNI и создал глобальную переменную (libpython). Сначала я установил #f, затем set!, когда вызывается init. Я добавил функцию, которая должна обрабатывать проверку, было ли инициализировано это значение:

  (define (get-cpyfunc name type)
    (lambda args
      (if libpython
        (apply (get-ffi-obj name libpython type) args)
        (error "Call init before using any Python C functions"))))

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

(define-cpyfunc Py_Initialize (_fun -> _void))

И преобразовать это в это:

(define Py_Initialize (get-cpyfunc "Py_Initialize" (_fun -> _void)))

Я читал документацию по макросам, чтобы попытаться выяснить это, но я не могу найти способ заставить его работать. Может ли кто-нибудь помочь мне с этим (или хотя бы дать общее представление о том, как будет выглядеть макрос)? Или есть способ сделать это без макросов?

Ответы [ 3 ]

1 голос
/ 28 мая 2010

Я ответил на большую часть этого вопроса в другом (я не видел этот). Хорошо использовать функцию, которая вытягивает привязки, подобные этой, но одна из возможных проблем здесь заключается в том, что, поскольку вы генерируете привязку только при вызове результирующей функции, эта привязка воссоздается при каждом вызове. Простой способ быстро решить эту проблему - использовать обещания, что-то вроде этого:

(require scheme/promise)
(define (get-cpyfunc name type)
  (define the-function
    (delay (if libpython
             (get-ffi-obj name libpython type)
             (error "Call init before using any Python C functions"))))
  (lambda args (apply (force the-function) args)))

Но это, по сути, почти то же самое, что код, который я разместил в вашем предыдущем вопросе.

Больше случайных нот:

  • get-ffi-obj примет символ в качестве имени для привязки - это сделано специально, чтобы упростить такие макросы (как в последнем вопросе).

  • Использование (symbol->string 'name) в макросе - это нормально. Как я отметил выше в своем комментарии в ответ на комментарий Натана, это означает, что он вызывается во время выполнения, но mzscheme должен быть в состоянии оптимизировать это в любом случае, поэтому нет необходимости пытаться написать какой-то сложный макрос, который выполняет эту работу во время компиляции.

  • Загляните в каталог PLT - вы найдете коллекцию под названием ffi. Это коллекция примеров привязок с различными стилями. Макросы, которые создают привязки, очень распространены в этих примерах.

1 голос
/ 28 мая 2010

Почему бы вам не изменить сгенерированный код на

(define Py_Initialize (get-cpyfunc 'Py_Initialize (_fun -> _void)))

и затем get-cpyfunc запустить (symbol->string name)?

Конечно, есть способ сделать это с syntax-case (хотя я никогда не могу вспомнить его синтаксис ), и определенно, если вы используете Scheme с CL-esque define-macro.

0 голосов
/ 28 мая 2010

Это не полный ответ, но я придумал макрос, который удовлетворяет обоим требованиям (определяет переменную и строку с именем этой переменной):

> (define-syntax (my-syntax stx)
  (syntax-case stx ()
  [(_ id)
  #'(define-values (id) (values (symbol->string (quote id))))]))
> (my-syntax y)
> y
"y"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...