【问题标题】:Shorter way for tuple elements retargeting in SML在 SML 中重新定位元组元素的更短方法
【发布时间】:2019-09-02 12:10:51
【问题描述】:

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

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。

【问题讨论】:

    标签: sml smlnj


    【解决方案1】:
    (p, #1 (returnResult (p, q, s)),
        #2 (returnResult (p, q, s)),
        #3 (returnResult (p, q, s))) 
    

    这会 [...] 导致同一件事运行 3 次

    是的,没错。而且它也比你原来的提议更冗长。

    你也可以写例如

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

    作为 let-in-end 的替代品。

    您可以创建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 所做的一些计算可以拆分为多个函数,或者它们实际上是一回事,应该包装在一个通用数据类型中,或者也许是pq 和@987654335 @ 最好作为 reader/state monad 的隐式参数传递。我没有一个很好的例子来说明手头的 ML 中的最后一件事是怎样的,但我也不能说明情况是什么,因为代码是假设的。

    【讨论】:

    • 好吧,由于某些预先计算的结构确实存在并且在 ra、rb、rc 数据结构中,我正在考虑再次利用它们,而不是重新计算,因为它们实际上可以找到在另一个函数中进一步使用。
    【解决方案2】:

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

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

    【讨论】:

    • 不,它们不是一般的。我不要求任何具体问题,仅当 SML/NJ 存在一般性提案时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多