Как я пишу макрос схемы, который определяет переменную и также получает название той переменной как строка?

Это - главным образом продолжение этого вопроса. Я решил просто иметь в виду 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)))

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

1
задан Community 23 May 2017 в 11:48
поделиться

3 ответа

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

(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
ответ дан 3 September 2019 в 00:15
поделиться

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

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

, а затем запустить get-cpyfunc (символ-> имя строки) ?

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

1
ответ дан 3 September 2019 в 00:15
поделиться

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

> (define-syntax (my-syntax stx)
  (syntax-case stx ()
  [(_ id)
  #'(define-values (id) (values (symbol->string (quote id))))]))
> (my-syntax y)
> y
"y"
0
ответ дан 3 September 2019 в 00:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: