在 SML 中重新定位元组元素的较短方法



目前,我在我的一个函数中使用了这样的东西:(所有变量都与更复杂的函数一起使用,但对于我要问的问题,这并不重要,我简化了)

fun RecursiveCall (p, q, r, s) =
let
val (ra, rb, rc) = returnResult (p, q, s)
in
RecursiveCall (p, ra, rb, rc)
end

我怎样才能用更短、(也许)更好的方式写这个?这意味着,如何提取从函数返回的元组元素并将其作为另一个元组的参数传递?

注意:也可以简单地写RecursiveCall (p, #1 (returnResult (p, q, s)) , #2 (returnResult (p, q, s)), #3 (returnResult (p, q, s)))但(可能)在某些情况下,这会导致同样的事情运行三次,即 returnResult。

如果不了解您的实际问题,很难说任何笼统的话,但是您可以将元组的最后三个元素组合在一起(看起来它们是一个单元),例如

fun RecursiveCall p (q, r, s) = RecursiveCall p (returnResult (p, q, s))
(p, #1 (returnResult (p, q, s)),
#2 (returnResult (p, q, s)),
#3 (returnResult (p, q, s))) 

这将导致同样的事情运行三次

是的,没错。而且它也比你最初的提案更冗长。

你也可以写例如

case returnResult (p, q, s) of
(ra, rb, rc) => recursiveCall (p, ra, rb, rc)

作为让结束的替代方案。

您可以制作returnResultrecursiveCall柯里函数并使用uncurry3

fun curry3 f x y z = f (x, y, z)
fun uncurry3 f (x, y, z) = f x y z
fun returnResult p q s = (p + 1, q + 2, s + 3)
fun recursiveCall p q r s =
uncurry3 (recursiveCall p) (returnResult p q s)

在这里,recursiveCall p部分应用于其四个参数之一,使其成为接受三个柯里参数的函数。 因此,uncurry3 (recursiveCall p)成为一个接受 3 元组的函数,这是returnResult p q s的精确结果。

此方法依赖于方便组合在一起的参数顺序。

但我认为这是returnResult退回太多东西的症状。

理想情况下,函数返回其名称表明它计算的一件事。

也许returnResult所做的一些计算可以拆分为多个函数,或者它们真的是一回事,应该包装在一个通用的数据类型中,或者也许pqs最好作为读者/状态monad的隐式参数传递。我没有一个很好的例子来说明最后一件事在 ML 中的外观,但我也不能说情况需要什么,因为代码是假设的。

相关内容

最新更新