Как превратить эту функцию в макрос? - PullRequest
1 голос
/ 20 августа 2011

У меня трудности с пониманием новой макросистемы Схемы.Где-то вдоль пути я начал сначала писать свой «макрос» как функцию, а затем применить его как макрос.

Поэтому моя миссия состоит в том, чтобы перевернуть следующую структуру:

;; highlight-rules: rule id, color and the regexp matches
(define highlight-rules
  `((important   ,(with-esc "[1;33m") ("foo"
                                       "bob"))
    (unimportant ,(with-esc "[1;30m") ("case of unimport"))
    (urgent      ,(with-esc "[1;31m") ("urgents"))))

В этот вид cond рядов с совпадающими строками, скомпилированными в регулярные выражения:

;; just an example. `line` is an argument bound by the function application
(cond
  ((string-match (regexp ".*sudo:session.*") line)
     (with-color *important* line))
  (else line))

Я написал функцию, которая, кажется, работает:

;; (cdar highlight-rules) -> (colorstring   list-of-rules)
(define (parse-highlight-rules rules)
  ;; aux function to do one 'class' of patterns
  (define (class-of-rules colorstr rulelist)
    (map (lambda (rule)
        `((string-match ,(regexp rule)) (with-color ,colorstr line)))
        rulelist))
  (define (do-loop accumulator rules)
    (let* ((highlight-group (cdar rules))
           (colorstr        (car highlight-group))
           (grouprules      (cadr highlight-group))
           (acc*            (append (class-of-rules colorstr grouprules) accumulator))
           (rest            (cdr rules)))
    (if (null? rest)
        acc*
        (do-loop acc* rest))))
  ; wrap the list in cond.
  `(apply cond ,(do-loop '() rules)))

С учетом highlight-rules функция возвращает правильно выглядящий список (кроме применения apply - в clojure можно использовать сплайсинг):

CSI> (parse-highlight-rules highlight-rules)
(apply cond (((string-match #<regexp>) (with-color "\x1b[1;31m" line))
            ((string-match #<regexp>) (with-color "\x1b[1;30m" line))
            ((string-match #<regexp>) (with-color #0="\x1b[1;33m" line))
            ((string-match #<regexp>) (with-color #0# line))))

Но как поступить с этим?Я застрял с этим некоторое время.Цыпленок Схема мой диалект.

1 Ответ

1 голос
/ 20 августа 2011

Самый простой способ трансформировать вашу функцию в макрос - это использовать макрос Chicken явное переименование , который работает аналогично defmacro Clojure (за исключением того, что макрос с явным переименованием принимает некоторые дополнительные аргументы, которые может использоваться для сохранения гигиены).

Сплайсинг работает в основном так же, как в Clojure. Синтаксис ,@. Поэтому должно работать следующее:

(define-for-syntax (parse-highlight-rules rules)
  ;; ... insert missing code here ...
  `(cond ,@(do-loop '() rules)))

(define-syntax highlight
  (er-macro-transformer
    (lambda (form rename compare)
      (parse-highlight-rules (cdr form)))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...