Scala没有参数字符串函数vs typed String参数

时间:2015-01-08 19:04:09

标签: scala functional-programming

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

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

有趣的是作为第二个参数组传入的无参数函数。在代码库中,该方法仅使用config和两个字符串调用,后者是一些默认值,但是作为String而不是函数。在方法的代码体内,default被传递给一个带有3个字符串参数的方法。所以功能"默认"只能解析为此方法体内的字符串。

除了在我正在经历的代码库中使用此方法不会发生的currying使用时,是否有任何好处,以这种方式定义方法?为什么不在一个参数组中用3个字符串参数定义它?

我错过了什么?这里有一些编译优势?请记住,我假设不会对此进行任何干扰,因为它是一个很大的代码库,并且目前还没有使用此方法。

2 个答案:

答案 0 :(得分:2)

关键是要有一个可能很昂贵的默​​认字符串,只有在需要时才会创建。你编写代码就像创建要传入的字符串一样,但是因为它是一个名字参数('=> 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
}

比在多参数参数列表中嵌入代码块作为一个参数更好。

答案 1 :(得分:1)

这是一个无参数函数,返回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" 
})