球拍中的c(a | d)+ r宏 [英] c(a|d)+r macro in Racket

查看:112
本文介绍了球拍中的c(a | d)+ r宏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有可能在Racket中编写一个宏来转换每种形状的形状(c(a | d)+ r xs),其中c(a | d)+ r是与car,cdr匹配的正则表达式,caar,cadr等 相应的第一"和休息"的组成.

I wonder if it's possible to write a macro in Racket that would translate every form of shape (c(a|d)+r xs), where c(a|d)+r is a regular expression matching car, cdr, caar, cadr, ... etc, into the corresponding composition of first and rest.

例如,此宏应采用(caadr'(1 2 3 4 5))并将其转换为(first(first(rest'(1 2 3 4 5)))).

For example, this macro should take (caadr '(1 2 3 4 5)) and transform that to (first (first (rest '(1 2 3 4 5)))).

沉(Mark Tarver的新编程语言)中的代码如下: https://groups.google.com/group/qilang/browse_thread/thread/131eda1cf60d9094?hl=zh_CN

Something like this in Shen (Mark Tarver's new programming language): https://groups.google.com/group/qilang/browse_thread/thread/131eda1cf60d9094?hl=en

推荐答案

完全有可能在Racket中做到这一点,并且比上述方法要短得多.涉及两个技巧(不是真的):

It is very possible to do exactly that in Racket, and in a much shorter way than done above. There are two (not-really) tricks involved:

  1. 使用Racket的

  1. Using Racket's #%top macro makes it possible to create such bindings-out-of-thin-air. This macro is getting used implicitly around any variable reference that is unbound ("top" because these things are references to toplevel variables).

如果使宏执行必要的最小操作,并将其余部分留给函数,宏就会变得简单得多.

Macros become much simpler if you make them do the necessary minimum, and leave the rest to a function.

这是带有注释和测试的完整代码(实际代码很小,大约10行).

Here's the complete code with comments and tests (the actual code is tiny, ~10 lines).

#lang racket

;; we're going to define our own #%top, so make the real one available
(require (only-in racket [#%top real-top]))
;; in case you want to use this thing as a library for other code
(provide #%top)

;; non-trick#1: doing the real work in a function is almost trivial
(define (c...r path)
  (apply compose (map (λ(x) (case x [(#\a) car] [(#\d) cdr])) path)))

;; non-trick#2: define our own #%top, which expands to the above in
;; case of a `c[ad]*r', or to the real `#%top' otherwise.
(define-syntax (#%top stx)
  (syntax-case stx ()
    [(_ . id)
     (let ([m (regexp-match #rx"^c([ad]*)r$"
                            (symbol->string (syntax-e #'id)))])
       (if m
         #`(c...r '#,(string->list (cadr m)))
         #'(real-top . id)))]))

;; Tests, to see that it works:
(caadadr '(1 (2 (3 4)) 5 6))
(let ([f caadadr]) (f '(1 (2 (3 4)) 5 6))) ; works even as a value
(cr 'bleh)
(cadr '(1 2 3))    ; uses the actual `cadr' since it's bound,
;; (cadr '(1))     ; to see this, note this error message
;; (caddddr '(1))  ; versus the error in this case
(let ([cr list]) (cr 'bleh)) ; lexical scope is still respected

这篇关于球拍中的c(a | d)+ r宏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆