scala贷款模式,可选功能参数

时间:2011-09-07 21:56:05

标签: scala

我有一个贷款模式,它应用一个函数n次,其中'i'是递增变量。 “偶尔”,我希望传入的函数可以访问'i'....但我不想要求传入的所有函数都要求定义一个param来接受'i'。以下示例......

def withLoaner = (n:Int) => (op:(Int) => String) => {
  val result = for(i <- 1 to n) yield op(i)
  result.mkString("\n")
}

def bob = (x:Int) => "bob" // don't need access to i. is there a way use () => "bob" instead?
def nums = (x:Int) => x.toString // needs access to i, define i as an input param

println(withLoaner(3)(bob))

println(withLoaner(3)(nums))

1 个答案:

答案 0 :(得分:11)

def withLoaner(n: Int) = new {
  def apply(op: Int => String) : String = (1 to n).map(op).mkString("\n")
  def apply(op: () => String) : String = apply{i: Int => op()}
}

(不确定它与贷款模式的关系)

修改评论中要求的解释很少。

不确定你知道什么,也不知道scala以及你在该代码中没有找到的东西。很抱歉,如果我只是显而易见的话。

首先,scala程序由traits / classes(也是单例对象)和方法组成。所做的一切都是通过方法完成的(将构造函数放在一边)。函数(与方法相对)是各种FunctionN特征(的子类型)的实例(N个参数的数量)。它们中的每一个都具有作为实际实施的应用方法。 如果你写

val inc = {i: Int => i + 1}

它是卑鄙的

val inc = new Function1[Int, Int] {def apply(i: Int) = i + 1}

(定义一个扩展Function1的匿名类,使用给定的apply方法并创建一个实例)

因此,编写函数比简单方法更重要。此外,您不能重载(具有相同名称的多个方法,不同于签名,正如我上面所做的那样),也不能使用命名参数或参数的默认值。

另一方面,函数是第一个类值(它们可以作为参数传递,作为结果返回)而方法不是。它们会在需要时自动转换为函数,但在执行此操作时可能会出现一些边缘情况。如果方法仅用作函数值,而不是作为方法调用,则编写函数可能更好。

使用f方法调用函数apply时使用f(x)而不是f.apply(x)(也可以调用),因为scala在函数上使用函数调用符号(值后跟括号和0或更多args)调用方法applyf(x)f.apply(x)的语法糖。这适用于f的任何类型,它不需要是FunctionN之一。

在withLoaner中所做的是返回一个对象(匿名类型,但是可以单独定义一个类并返回它的实例)。该对象有两个apply方法,一个接受Int => String,另一个接受() => String。当您withLoaner(n)(f)时,它意味着withLoaner(n).apply(f)。如果f具有其中一个的正确类型,则选择适当的apply方法,否则编译错误。

万一你想知道withLoaner(n)并不意味着withLoaner.apply(n)(或者它永远不会停止,那也可能意味着withLoaner.apply.apply(n)),因为withLoaner是一个方法,而不是一个值。