miniKanren:如何定义#s和#u?
Posted
技术标签:
【中文标题】miniKanren:如何定义#s和#u?【英文标题】:miniKanren: How to define #s and #u? 【发布时间】:2019-11-29 17:01:40 【问题描述】:在miniKanren中,succeed
可以定义为(define succeed (== #t #t))
,fail
可以定义为(define fail (=== #t #f))
。但是#s
和#u
是succeed
和fail
的缩写形式,它们出现在The Reasoned Schemer 中呢?
(define #s succeed)
在 Racket 中产生错误:
Welcome to Racket v7.2.
> (require Racket-miniKanren/miniKanren/mk)
> (define #s succeed)
; readline-input:2:8: read-syntax: expected `(`, `[`, or `` after `#s` [,bt
; for context]
#<procedure:...iniKanren/mk.rkt:337:4>
; readline-input:2:18: read-syntax: unexpected `)` [,bt for context]
我感觉这与阅读器宏有关。
如何在 Scheme 和 Racket 中为 succeed
定义 #s
和为 fail
定义 #u
?
我正在使用canonical miniKanren implementation for Scheme 和canonical miniKanren implementation for Racket。
【问题讨论】:
简短的回答可能是,没关系,因为它可能太难实现而没有太大的收获。 :) 【参考方案1】:Racket 中的标识符不能以#
开头。绑定标识符s
和u
很简单。重新定义#s
和#u
的含义并不那么简单,因为它需要发生在读者身上。通常#something
会向读者发出信号,表示要阅读一些特别的东西。
输入(foo bar)
将被读取为列表,#(foo bar)
将被读取为向量,#s(foo bar)
将被读取为结构体。您可以在此处阅读有关标准语法的信息:
https://docs.racket-lang.org/reference/reader.html?q=%23s#%28mod-path._reader%29
现在如果你想改变#s
和#u
的含义,你需要查看readtables。
每次读者看到#
时,它都会查阅一个可读表以了解如何处理以下字符。由于读取发生在解析/扩展和评估之前,您不能简单地通过调用程序中的函数来更改读取器。您将需要使用
#reader
扩展机制或创建您自己的语言。
有关 readtable 的更多信息:https://docs.racket-lang.org/reference/readtables.html?q=reader-macro
指南中有一个如何使用阅读器扩展的示例: https://docs.racket-lang.org/guide/hash-reader.html
【讨论】:
【参考方案2】:我用
解决了所有的书(define succeed
(lambda (s)
`(,s)))
(define SUCC succeed)
(define fail
(lambda (s)
'()))
另一方面,您应该咨询 Friedman & Byrd 提供的the source code。我使用 mit-scheme 解决了这个问题——没有使用球拍的特定功能,R6RS 就足够了。
【讨论】:
【参考方案3】:对于 Racket,#s
和 #u
可以这样定义(参考:Using Racket for The Reasoned Schemer):
;; #s for succeed.
(current-readtable
(make-readtable (current-readtable)
#\s
'dispatch-macro
(lambda (ch port src line col pos) succeed)))
;; #u for fail.
(current-readtable
(make-readtable (current-readtable)
#\u
'dispatch-macro
(lambda (ch port src line col pos) fail)))
请注意,这只适用于 REPL。
这通过修改readtable 来定义#s
和#u
。
对于Scheme,添加读取语法在SRFI-10 sharp-comma external form 中定义,但生成的#,()
形式对于大多数人来说可能很尴尬。对于 Scheme,最好只定义 s
和 u
,因为目前没有可移植的方式来定义 #s
和 #u
。
【讨论】:
以上是关于miniKanren:如何定义#s和#u?的主要内容,如果未能解决你的问题,请参考以下文章
如何阅读 nm 命令:nm 选项 -T 和 -U(未定义)是啥意思?
为啥 miniKanren 中的“disj”在 Scheme 中有效,而在 Racket 中无效?