我可以将任意函数传递给Scala中的另一个函数吗?

| 我是Scala的新手,能够将函数传递给其他函数非常巧妙-但是我可以将任意函数引用传递给另一个函数吗?所述功能参数的Arity将是固定的(也就是说,我也很好奇您是否也可以通过任意Arity传递函数)。我一直被类型错误绊倒。我尝试使用
Any
,但似乎无济于事。 例如,我有以下代码:
class CodeRunner(val user_defined: (Int) => Unit) {
  def run(input: Int) = {
    user_defined(input)
  }
}

def arbitrary_code(input: Int) = { println(\"Running with input \" + input) }

val d1 = new CodeRunner(arbitrary_code)

d1.run(4)
我得到:
Running with input 4
现在,假设我要传递以下函数:
def arbitrary_code(input: String) = { println(\"Running with input \" + input) }
如何更改我的
CodeRunner
班级以同时处理这两个类?     
已邀请:
        泛型类型允许您使用占位符类型定义一个类,该类在实例化对象时得到指定。编译器很高兴,因为它可以确保所有类型都是安全的,而您很高兴,因为您可以实例化该对象并为该值传递任意类型。 要在类中使用泛型类型,可以这样修改它:
class CodeRunner[T] (val user_defined: (T) => Unit) {
  def run(input: T) = {
    user_defined(input)
  }
}
\“ Class CodeRunner \”之后的[T]是重要的部分,它定义了将在类定义中使用的泛型T(可以用另一个大写字母替换T,等等)。 因此,如果您定义一个方法:
def arbitrary_code(input: String) = { println(\"Running with input \" + input) }
然后将其传递给:
val d1 = new CodeRunner(arbitrary_code)
...然后,编译器说“啊哈,对于此CodeRunner实例,泛型T是字符串”。如果您调用
d1.run(\"string\")
编译器会很高兴,但不会让您传入d1.run(4)。     
           如何更改我的
CodeRunner
班级以同时处理这两个类? 您可以使任意类型成为类的参数:
class CodeRunner[T](val user_defined: (T) => Unit) {
  def run(input: T) = {
    user_defined(input)
  }
}

def arbitrary_code(input: Int) = { println(\"Running with input \" + input) }

val d1 = new CodeRunner(arbitrary_code)

d1.run(4)

def arbitrary_code2(input: String) = { println(\"Running with input \" + input) }

val d2 = new CodeRunner(arbitrary_code2)

d2.run(\"hello\")
注意,
d2
的类型是
CodeRunner[String]
,不能分配给
d1
CodeRunner[Int]
。     
        要传递任意函数,您当然可以使用泛型:
def run[T,U](f: T => U) = println(f)
对于任意Arity,这是不可能的,因为类型T => U的函数是Function1 [U,T]的实例,类型(T,U)=> V的函数是Function2 [T,U, V]。 (此外,我找不到任何有用的用例)。 但是,有一个聪明的概念叫做“ currying”。它包含转换一个带有多个参数的函数,并在一个带有单个参数并返回另一个函数的函数中返回一个值。 这是一个例子:
def nonCurriedAdd(x: Int, y: Int) = x + y
// nonCurriedAdd(4,6)
def curriedAdd(x: Int) = (y: Int) => x + y
// we can use some syntax sugar
def curriedAdd(x: Int)(y: Int) = x + y
// curriedAdd(4)(6)
因此,您现在可以执行d1.run(curriedAdd)。 您还可以使用\“ curried \”方法将非咖喱函数转换为咖喱函数:
d1.run(nonCurriedAdd.curried)
    
           如何将任意函数引用传递给另一个函数?所述功能参数的固定性将是固定的 与往常一样,记下您正在开发的函数的类型,一切都变得清晰。 您的“任意”一词表明函数参数可以在任何类型下使用。也就是说,它们是多态函数(或某些语言中的泛型函数)。 以下内容应相当清晰地转换为Scala:
== The type of an \"arbitrary\" function of fixed arity
f :: a -> b -> c -> d

-- The type of a function that accepts such a
-- function as an argument, and does something with it:
g :: (a -> b -> c -> d) -> a -> b -> c -> d

-- And a function that implements something of that type
g f a b c = f a b c
您也许可以提出一些其他这样的高阶函数,它们采用固定Arity但任意(即多态)类型的函数并对其进行运算。 经典的高阶函数例如
map :: (a -> b) -> [a] -> [b]

fold :: (a -> b -> b) -> b -> [a] -> b
还有很多很多。     
        
scala> object codeRunner {
     |    def run[InputType, OutputType](code: InputType => OutputType) = (input: InputType) => code(input)
     | }
defined module codeRunner

scala> def someCode(x: Int) {
     |    println(\"This code uses \" + x)
     | }
someCode: (x: Int)Unit

scala> def otherCode(y: String) {
     |    println(\"This code uses \" + y)
     | }
otherCode: (y: String)Unit

scala> codeRunner.run(someCode)(10)
This code uses 10

scala> codeRunner.run(otherCode)(\"hello\")
This code uses \"hello\"
    

要回复问题请先登录注册