Scheme racketswitch语句宏
我试图在Racket中创建一个switch语句宏。我很难明白该怎么做。我希望能够使用如下所示的功能Scheme racketswitch语句宏,scheme,racket,Scheme,Racket,我试图在Racket中创建一个switch语句宏。我很难明白该怎么做。我希望能够使用如下所示的功能 (define x 99) (switch x [3 (displayln "x is 3")] [4 (displayln "x is 4")] [5 (displayln "x is 5")] ['default (displayln "none of the above")]) 我已经尝试过将模式匹配与语法大小写结合使用,但我不确定这是正确的方法。这里的任
(define x 99)
(switch x
[3 (displayln "x is 3")]
[4 (displayln "x is 4")]
[5 (displayln "x is 5")]
['default (displayln "none of the above")])
我已经尝试过将模式匹配与语法大小写结合使用,但我不确定这是正确的方法。这里的任何球拍专家都能给我一个正确的方向吗?对于
开关
我建议制作一个打开值的辅助宏-这避免了在(开关expr子句…
中多次评估expr
的问题
下面我使用标识符else
来表示默认子句
请注意,语法分析
一次尝试一种模式。如果输入错误,例如(开关)
模式中的初始标识符前缀为。
,以避免递归宏中出现任何问题
请注意,使用的基本重写规则是:
(switch-value v
[expr result]
clause ...)
==>
(if (equal? v expr)
result
(switch-value v clause ...))
使宏递归比编写一个同时处理所有子句的大型宏更容易
#lang racket
(require (for-syntax syntax/parse))
(define-syntax (switch stx)
(syntax-parse stx
[(_switch)
#'(raise-syntax-error 'switch "value expression and at least one clause expected" stx)]
[(_switch expr clause ...)
#'(let ([v expr])
(switch-value v clause ...))]))
(define-syntax (switch-value stx)
(syntax-parse stx
#:literals (else)
[(_switch-value v)
#'(raise-syntax-error 'switch "at least one clause is expected" _switch-value)]
[(_switch-value v [else expr])
#'expr]
[(_switch-value v [expr1 expr2] clause ...)
#'(if (equal? v expr1)
expr2
(switch-value v clause ...))]))
(define x 4)
(switch x
[3 "x is 3"]
[4 "x is 4"]
[5 "x is 5"]
[else (displayln "none of the above")])
我相信不要重新发明完美的轮子,因此这里有一个宏用于将您的
开关
转换为等效的案例
,只需稍作更改即可使用默认值
,而不是默认值
。(我向soegaard道歉,因为我还不知道如何使用语法解析
,所以我将只使用传统的语法大小写
。-)
与使用大小写
相反,使用此开关
宏的缺点是,您无法区分使用默认值
匹配符号与使用“一网打尽”符号。因此,使用case
更好。:-)
我喜欢其他两个答案,但我觉得我们还应该提到现有的
匹配
表单,它(afaict)已经完全满足了您的需求:
#lang racket
(define x 99)
(match x
[3 (displayln "x is 3")]
[4 (displayln "x is 4")]
[5 (displayln "x is 5")]
[default (displayln "none of the above")])
唯一的变化是:我写match
而不是switch
,并且我使用模式default
而不是引用的'default
。事实上,任何标识符都可以在这里工作;标识符只是给一个值命名
事实上,match可以做的远不止这些,但这是它的一大用途
如果您只是想练习编写宏,那么您可以忽略以下答案:)。(语法大小写(默认)stx子句)
和(语法解析stx::文字(默认)子句…
的意思是相同的(假设您没有使用任何防护措施。就是这么简单!
(case x
((3) (displayln "x is 3"))
((4) (displayln "x is 4"))
((5) (displayln "x is 5"))
(else (displayln "none of the above")))
#lang racket
(define x 99)
(match x
[3 (displayln "x is 3")]
[4 (displayln "x is 4")]
[5 (displayln "x is 5")]
[default (displayln "none of the above")])