【问题标题】:Scala no argument string function vs typed String parameterScala无参数字符串函数与类型化字符串参数
【发布时间】:2015-01-09 14:11:33
【问题描述】:

我遇到了一个看起来像这样的函数:

def doSomethingQuestionable(config: someConfig, value: String)(default: => String) : String

有趣的是作为第二个参数组传入的无参数函数。在代码库中,该方法只使用一个配置和两个字符串调用,后者是一些默认值,但作为一个字符串,而不是一个函数。在方法的代码主体中,默认值被传递给采用 3 个字符串参数的方法。所以函数“default”只解析为这个方法体中的一个字符串。

除了在我正在经历的代码库中这种方法不会发生的柯里化用法之外,以这种方式定义方法还有什么好处吗?为什么不在单个参数组中使用 3 个字符串参数来定义它?

我错过了什么?这里有一些编译器优势吗?请记住,我假设永远不会使用此方法进行柯里化,因为它是一个庞大的代码库,目前还没有使用此方法完成。

【问题讨论】:

标签: scala functional-programming


【解决方案1】:

关键是要有一个可能很昂贵的默​​认字符串,该字符串仅在您需要时创建。您编写代码就像创建要传入的字符串一样,但因为它是一个名称参数('=> String'),它实际上会变成一个函数,每当引用 default 时都会透明地调用它在doSomethingQuestionable 方法中。

将其分开的原因是如果您确实需要一大块代码来创建该字符串。如果你从不做,也永远不会做,那还不如

def doSomethingQuestionable(config: someConfig, value: String, default: => String): String

如果你这样做了,

def doSomethingQuestionable(cfg, v){
  // Oh boy, something went wrong
  // First we need to check if we have a database accessible
  ...
  // (Much pain ensues)
  result
}

比将代码块作为一个参数嵌入到多参数参数列表中要好得多。

【讨论】:

    【解决方案2】:

    这是一个返回String的无参数函数:

    () => String
    

    这不是你所拥有的。 这个

    => <WHATEVER>
    

    是按名称而不是按值传递的参数。例如:

    => String // A string being passed by-name
    => () => String // A parameterless function returning string being passed by-name
    

    这些模式的区别在于,按值,参数是求值,结果被传递,而按名称,参数是“按原样”传递,并在每次使用时进行评估。

    例如:

    var x = 0
    def printValue(y: Int) = println(s"I got $y. Repeating: $y.")
    def printName(y: => Int) = println(s"I got $y. Repeating: $y.")
    
    printValue { x += 1; x } // I got 1. Repeating: 1.
    printName { x += 1; x } // I got 2. Repeating: 3.
    

    现在,至于为什么该方法将其拆分为第二个参数,这只是句法上的愉悦。以方法foldLeft 为例,其定义类似。你可以这样写:

    (1 to 10).foldLeft(0) { (acc, x) =>
      println(s"Accumulator: $acc\tx: $x\tacc+x: ${acc+x}")
      acc+x
    }
    

    如果将foldLeft 定义为单个参数列表,则如下所示:

    (1 to 10).foldLeft(0, { (acc, x) =>
      println(s"Accumulator: $acc\tx: $x\tacc+x: ${acc+x}")
      acc+x
    })
    

    没有太大的不同,当然,但看起来更糟。我的意思是,你不会在下面写这个东西吧?

    if (x == y, { 
      println("Same thing") 
    }, { 
      println("Different thing" 
    })
    

    【讨论】:

      猜你喜欢
      • 2021-10-28
      • 2021-09-20
      • 2022-01-21
      • 2021-10-21
      • 2021-10-13
      • 2021-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多