Emm*_*ery 2 pattern-matching racket
我正在阅读《球拍领域》一书,第 175 页,我实际上看到了以下代码:
(struct dice-world (src board gt))
(struct game (board player moves))
(define (no-more-moves-in-world? w)
(define tree (dice-world-gt w))
(define board (dice-world-board w))
(define player (game-player tree))
player)
Run Code Online (Sandbox Code Playgroud)
书中的函数不会返回播放器,但直到该行的所有内容都与书中一样。对我来说,这尖叫着需要模式匹配!
事实上,这很好用,对我来说可读性更强,更明确:
(define (no-more-moves+? w)
(match w
[(dice-world _ board (game _ player _)) player]))
Run Code Online (Sandbox Code Playgroud)
然而,在这里我们仍然w毫无理由地命名变量。我希望能够直接在函数参数上进行模式匹配,如下所示(无效语法):
(define (no-more-moves2? (dice-world _ board (game _ player _)))
player)
Run Code Online (Sandbox Code Playgroud)
从我到目前为止的谷歌搜索来看,这似乎不可能?这对我来说听起来难以置信吗?我猜这可能是通过一些宏技巧实现的,但我真的很惊讶这不是从书中编写代码的标准方法?作为初学者的书,我想也许稍后会介绍模式匹配,但我在索引中根本没有找到它?
另外,如果答案是不可能/不习惯,我想知道其他 lisps 是否也一样?
您可以从 Racket match-plus 包中define/match*获得您想要的表格,名称为。免责声明:这是我的包裹。使用该模块,以下代码应该可以正常工作:
(require match-plus)
(define/match* (no-more-moves2? (dice-world _ board (game _ player _)))
player)
Run Code Online (Sandbox Code Playgroud)
要安装包,请使用 DrRacket 的包管理器 GUI,或运行以下命令:
raco pkg install match-plus
Run Code Online (Sandbox Code Playgroud)
我认为这不包含在 Racket 本身的基本原理正如 John Clements 提到的:使用这种形式,如果模式匹配失败,该函数只会抛出异常。尽管如此,这对于您的用例还是非常有用的,特别是如果您在函数上签订了合同。正如文档所指出的:
...只能指定一个匹配子句,因为匹配模式与形式定义内联。这意味着如果模式匹配失败将引发错误,但如果函数已经以保证成功模式匹配的方式收缩,则是理想的。
(强调我的。)