pattern-matching - 在 ML 中使用 let 解构元组
问题描述
在 sml 中,我可以在 a 中使用元组let
吗?如果是这样,语法是什么?我可以要求这是同心模式匹配,但似乎应该有一个更少的样板方式。在let
下面,我想将v1
和绑定v2
到从调用返回的元组的两个值interpExp
。然后我想interpExp
用其中一个值调用以获得另外两个值。
fun performOp (e1,op,e2,table) =
let val (v1,t1) = interpExp(e1,table) (* interpExp returns 2-tuple, bind v1 and t2 to those two values *)
and val (v2,t2) = interpExp(e1,t1) (* use t1 which was bound on previous line *)
and val v3 = (case op of
Plus => v1 + v2
| Minus => v1 - v2
| Times => v1 * v2
| Div => v1 / v2)
in (v3,t2)
end
在进一步的试验和错误中,似乎第二个和第三个val
是不必要的,此后似乎v1
andv2
不在下一个子句的范围内。
fun performOp (e1,op,e2,table) =
let val (v1,t1) = interpExp(e1,table)
and (v2,t2) = interpExp(e1,t1) (* oops t1, not in scope *)
and v3 = (case op of
Plus => v1 + v2
| Minus => v1 - v2
| Times => v1 * v2
| Div => v1 / v2)
in (v3,t2)
end
在进一步的实验中,我发现了另一种语法,但我不确定有什么区别,即使用val
而不是and
在let
.
fun performOp (e1,op,e2,table) =
let val (v1,t1) = interpExp(e1,table)
val (v2,t2) = interpExp(e1,t1) (* oops t1, not in scope *)
val v3 = (case op of
Plus => v1 + v2
| Minus => v1 - v2
| Times => v1 * v2
| Div => v1 / v2)
in (v3,t2)
end
解决方案
一般来说,and
关键字在 SML 中用于引入多个相互递归的函数或数据类型。例如,我们可以将无端低效的奇偶校验定义为
fun isEven 0 = true
| isEven 1 = false
| isEven n = isOdd (n - 1)
and isOdd 0 = false
| isOdd 0 = true
| isOdd n = isEven (n - 1)
还有一个数据类型的例子:
datatype 'a exposed = Exposed of 'a * 'a stream
and 'a stream = Stream of unit -> 'a exposed
但是,and
在其他一些上下文中也支持(我假设是为了一致性?),其中它仅具有引入同时捆绑在一起的所有绑定的效果。例如,在
val x = 7
and y = 8
两者x
和y
立即介绍。现在直接解决您的直接示例:
- 您提出的第一个将遇到语法错误,因为它应该是
and
而不是val and
- 您提出的第二个同时介绍了所有这些绑定,因此您不能
t1
在第二个中依赖它——它还没有被引入。 - 最后一个关于使用是正确的
val
然而,所有这些也存在语法错误,因为op
它也是一个保留字(它主要用于允许将中缀函数视为前缀函数,如 in val sum = foldr op+ 0
)。如果你改变这个,给你留下类似的东西
fun performOp (e1, binop, e2, table) =
let val (v1, t1) = interpExp (e1, table)
val (v2, t2) = interpExp (e1, t1)
val v3 = (case binop of
Plus => v1 + v2
| Minus => v1 - v2
| Times => v1 * v2
| Div => v1 / v2)
in (v3,t2)
end
那么它应该按预期工作。我还应该注意,/
它用于real
s 上的除法,所以如果你打算使用int
s 代替,它应该是div
(也是中缀)。
推荐阅读
- php - Symfony 5 - 同一页面上的多个表单
- sql - 如何在delphi中接收光标并显示详细信息
- node.js - 使用 puppeteer 抓取网页
- express - 我可以使用 Promise 作为中间件来处理这样的错误吗?
- logstash - 在 logstash.conf 中搜索文件的通配符
- python - 将多级 xml 连同节点的绝对路径作为列名提取到 pandas 数据框中
- python - 编写 Python 时在 VSCode 中使用制表符而不是空格?
- python - 无法为形状为 (129213603, 28) 且数据类型为 int8 的数组分配 3.37 GiB
- visual-studio - Visual Code Windows环境变量路径,如何更正?
- python - 如何从后台进程运行 Python?