Эквивалент сращивания эквивалентен в Scheme Hygieni c Macros - PullRequest
1 голос
/ 15 апреля 2020

У меня есть реализация Scheme, и сейчас я тестирую макросы Hygieni c. У меня есть макрос -->, который работает так:

(--> document (querySelector "body"))

, который просто вызовет JavaScript

document.querySelector("body")

, и я хочу создать макрос, который будет создавать макрос, который будет вызывать методы на объектах. Поэтому, если я использую:

(define-method document querySelector)

, это создаст функцию:

(define-macro (querySelector . args)
  `(--> document (querySelector ,@args))

Это легко в макросах Lisp, потому что у меня есть @, чтобы склеить аргументы. Пример:

(define-macro (define-method object method)
   (let ((args (gensym)))
    `(define-macro (,method . ,args)
        `(--> ,',object (,',method ,@,args)))))

Это можно проверить с помощью my Scheme Interpreter на Codepen .

Ниже приведен простой макрос в CommonLisp, который генерирует макросы, отображающие текст (мой макрос тестирования в Clisp)

(define-macro (make-printer name)
  `(define-macro (,name)
      `(let ((,',name "xxx"))
          (write ,',name))))

это просто пример использования ,',, которое я тестировал. Это создает бесполезный макрос, который выдает «xxx».

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

(define-syntax define-method
   (syntax-rules ()
     ((_ obj method)
      (define-syntax method
          (syntax-rules ()
             ???)))))

Проблема в том, что я могу создать функцию потому что я не могу использовать apply для вызова метода объекта. Это должен быть вызов функции. Я также не могу изменить макрос -->, чтобы разрешить использование apply, потому что кто-то может захотеть вызвать метод apply для объекта, подобного

(--> fn (apply null '(1 2 3))

Рабочий пример:

(--> display (apply (current-environment) '#((1 2 3))))

он вызывает Function.prototype.apply со средой и массивом / вектором из одного элемента списка. То же самое, что и (display '(1 2 3))

Чтобы сделать это 100% -ной проблемой схемы, я могу подумать об этом случае, у меня есть макрос, который принимает переменное число аргументов, и я хочу создать макрос, который создаст оболочку для этого макроса.

Например: у меня есть макрос (foo name . args), и я хочу создать макрос make-foo, который будет создавать макросы, которые вызывают foo. (make-foo get-name) должен создать макрос (get-name . args), который расширится до (foo 'get-name . args). И foo может быть определено как:

(define-syntax foo
  (syntax-rules ()
    ((_ args ...)
      (display '(args ...)))))


(define-syntax make-foo
   (syntax-rules ()
     ((_ name)
      (define-syntax name
          (syntax-rules ()
             ((_ args ...)
              (foo name args ...)))))))

(make-foo hello)
(hello 1 2 3)

А что если я захочу создать макрос Scheme Hygieni c, где имя будет foo-hello, если я передам hello. Возможно ли что-то подобное с syntax-rules? Или мне нужно использовать макросы lisp или синтаксис-кейс. Я предпочитаю, если возможно, иметь код R5RS.

Я также пытался это сделать, чтобы иметь возможность создать функцию с переменным числом аргументов и создать макрос, который будет генерировать функцию с такими же аргументами:

(define (bar . args)
  (for-each display args))

(define-syntax caller
  (syntax-rules ()
    ((_ method)
       (define (method . args)
          (bar . args)))))

(caller foo)
(foo 1 2 3)

но это не работает, проверено в Кава и Гиль.

...