我一直在编写Common Lisp宏,所以Scheme的R5Rs宏对我来说有点不自然.我想我有了这个想法,除了我不明白如何在语法规则中使用矢量模式:
(define-syntax mac
(syntax-rules ()
((mac #(a b c d))
(let ()
(display a)
(newline)
(display d)
(newline)))))
(expand '(mac #(1 2 3 4))) ;; Chicken's expand-full extension shows macroexpansion
=> (let746 () (display747 1) (newline748) (display747 4) (newline748))
Run Code Online (Sandbox Code Playgroud)
我不知道我是如何使用一个需要将其参数写成向量的宏:
(mac #(1 2 3 4))
=>
1
4
Run Code Online (Sandbox Code Playgroud)
是否有某种技术使用这些模式?
谢谢!
使用define-syntax或define-syntax-rule在Racket中定义捕获宏的最简单方法是什么?
作为一个具体的例子,这里aif是CL风格的宏系统中的微不足道的.
(defmacro aif (test if-true &optional if-false)
`(let ((it ,test))
(if it ,if-true ,if-false)))
Run Code Online (Sandbox Code Playgroud)
这个想法是,it将被绑定到的结果test在if-true和if-false条款.天真的音译(减去可选的替代方案)是
(define-syntax-rule (aif test if-true if-false)
(let ((it test))
(if it if-true if-false)))
Run Code Online (Sandbox Code Playgroud)
在没有投诉的情况下进行评估,但如果您尝试it在子句中使用则会出错:
> (aif "Something" (displayln it) (displayln "Nope")))
reference to undefined identifier: it
Run Code Online (Sandbox Code Playgroud)
该anaphora蛋实现aif为
(define-syntax aif
(ir-macro-transformer
(lambda (form inject compare?)
(let ((it (inject 'it)))
(let ((test (cadr form))
(consequent (caddr …Run Code Online (Sandbox Code Playgroud) 是否可以在Scheme中编写一个宏(define-syntax例如),它将采用这样的表达式:
(op a b c d e f g h i j)
Run Code Online (Sandbox Code Playgroud)
并将这样的表达式作为输出?
(op (op (op (op (op (op (op (op (op a b) c) d) e) f) g) h) i) j)
Run Code Online (Sandbox Code Playgroud)
当然,任意长度.考虑到这样的一些模板,我想不出办法来做到这一点:
(define-syntax op
(syntax-rules ()
[(_) 'base-case]
[(v1 v2 ...) 'nested-case??]))
Run Code Online (Sandbox Code Playgroud) R5RS为库语法形式提供了建议的宏定义:
http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-ZH-10.html#%_sec_7.3
其中也以一种非常复杂的方式定义了letrec,当然不是我如何定义它,我会简单地使用:
(define-syntax letrec2
(syntax-rules ()
((letrec2 ((name val) ...) body bodies ...)
((lambda ()
(define name val) ...
body bodies ...)))))
Run Code Online (Sandbox Code Playgroud)
据我所知,letrec的语义,我经常使用它作为命名let.它的工作原理这样,但是我有我与谁认为他们可以否定了狭义相对论或建立语音理论哲学家争论的公平份额,我知道,当你认为你有一个简单的解决一个复杂的问题,它可能错误.必须要有一点,这个宏不能满足letrec的语义,否则他们可能已经使用过了.
在这个定义中,定义是letrec主体的局部定义,它们可以相互引用相互递归,我不太确定是什么(如果有的话)是错误的.
我正在为SICP工作,并希望尝试一些诡计的例子.我正在尝试流示例,并想要一个cons-stream的实现,我从这个StackOverflow问题得到了.然而当我把它打成诡计时,我得到:
guile> (define-syntax cons-stream
(syntax-rules ()
[(cons-stream x y) (cons x (delay y))]))
ERROR: invalid syntax ()
ABORT: (misc-error)
Run Code Online (Sandbox Code Playgroud)
我不知道这有什么问题 - 我尝试用'()替换(),删除[],但它仍然不起作用,即使它似乎是有效的R5RS.我目前正在使用guile 1.8.7,我看不到GNU文档提到的v2.0.1的包,这可能就是为什么它不能为我工作?
我被告知"call/cc"可用于实现任意控制流构造,所以我试图使用"call/cc"来实现所有这样的构造,但是我遇到了麻烦.假设我没有"if",我将如何使用"define-syntax"和"call/cc"来实现它?有可能或者我被误导了吗?我知道如何使用"call/cc"实现无条件跳转,但在机器级别使用分支指令执行条件执行,分支指令的执行取决于处理器的状态位.如果没有这种类型的结构,我看不出它是如何完成的.
scheme functional-programming callcc define-syntax control-flow
我正在学习Scheme 中的宏系统,我认为实现柯里化函数将是一个好的开始。这是我煮的:
(define-syntax function
(syntax-rules ()
((_ () body ...) (lambda () body ...))
((_ (param) body ...) (lambda (param) body ...))
((_ (param_1 param_2 params ...) body ...) (lambda (param_1 . rest)
(let ((k (function (param_2 params ...) body ...)))
(if (null? rest) k (apply k rest)))))
((_ name params body ...) (define name (function params body ...)))))
Run Code Online (Sandbox Code Playgroud)
这段代码按预期工作。例如我可以定义一个add函数如下:
(function add (x y) (+ x y))
Run Code Online (Sandbox Code Playgroud)
然后我就可以正常调用它了:
(add 2 3) ; => 5
Run Code Online (Sandbox Code Playgroud)
此外,我可以轻松地部分应用它:
(map (add 10) …Run Code Online (Sandbox Code Playgroud) 举个简单的例子:
(define-macro-variable _iota 0) ; define-macro-variable does not really exist
(define-syntax (iota stx)
(syntax-case stx ()
((iota)
(let ((i _iota))
(set! _iota (+ i 1))
#`#,i))))
Run Code Online (Sandbox Code Playgroud)
这样给出:
(define zero (iota))
(define one-two-three (list (iota) (iota) (iota)))
(define (four) (iota))
Run Code Online (Sandbox Code Playgroud)
以下都应评估为#t:
(equal? zero 0)
(equal? one-two-three '(1 2 3)) ; possibly in a different order
(equal? (four) 4)
(equal? (four) 4)
(equal? (four) 4)
Run Code Online (Sandbox Code Playgroud)
是否有任何真正的球拍功能define-macro-variable可以完成上述示例中应该执行的操作?
编辑:
我找到了解决办法:
(define-syntaxes (macro-names ...)
(let (macro-vars-and-vals ...)
(values macro-bodies-that-nead-the-macro-vars ...)))
Run Code Online (Sandbox Code Playgroud)
但我更喜欢一种解决方案,它不需要使用宏变量的所有宏都在一个表达式中.
我发现自己使用相同的定义来定义语法参数,除了它们的名称,所以我决定编写一个宏来使这更简单:
(define-syntax (test-case-parameter stx)
(syntax-parse stx
[(_ parameter:id)
#'(define-syntax-parameter parameter
(lambda (stx)
(raise-syntax-error stx "Can only be used inside test-case.")))]))
(test-case-parameter a)
(test-case-parameter b)
(test-case-parameter c)
Run Code Online (Sandbox Code Playgroud)
然而,我不想重复宏名称,我希望能够写:
(test-case-parameter a b c)
Run Code Online (Sandbox Code Playgroud)
但是我没有看到如何使用普通的省略号语法来实现这一点,因为我需要将所有内容包装在一个begin可以创建新范围的内容中,并且我希望所有的语法参数就好像我已经为每个顶部写了一样水平.什么是正确的方法来实现这一目标?
define-syntax ×10
macros ×9
scheme ×9
lisp ×3
racket ×3
syntax-rules ×2
callcc ×1
control-flow ×1
currying ×1
guile ×1
nested ×1
toplevel ×1
variadic ×1