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

时间:2019-04-11 19:07:39

标签: sml smlnj

目前,我在其中一个函数中使用了类似的方法:(所有变量都与更复杂的函数一起使用,但是对于我要问的问题来说,这无关紧要,并且我会简化)

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))),但是(可能)在某些情况下,这会使同一件事运行3次,即returnResult。

2 个答案:

答案 0 :(得分:1)

在不了解您的实际问题的情况下很难说出任何常规的东西,但是您可以将元组的最后三个元素组合在一起(看起来像是一个单元),例如

fun RecursiveCall p (q, r, s) = RecursiveCall p (returnResult (p, q, s))

答案 1 :(得分:0)

(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 curried函数并使用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)因此成为接受三元组的函数,这是returnResult p q s的精确结果。

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

但是我认为这是returnResult返回太多东西的征兆。

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

也许returnResult所做的某些计算可以分解为多个函数,或者也许它们确实是一回事,应该包装在一个通用的数据类型中,或者也许p,{{ 1}}和q最好作为阅读器/状态单子的隐式参数传递。对于当前的ML,我没有一个很好的例子,但是由于代码是假设的,因此我也无法说清情况是什么。