我如何在 scala 中编写一个 isFunction 函数,这样才能工作:
def isFunction(x:Any) = /* SomeCode */
println(isFunction(isFunction _)) //true
println(isFunction("not a function")) //false
我如何在 scala 中编写一个 isFunction 函数,这样才能工作:
def isFunction(x:Any) = /* SomeCode */
println(isFunction(isFunction _)) //true
println(isFunction("not a function")) //false
很丑,但它有效:
def isFunction(x:Any) = x match {
case _: Function0[_] => true
case _: Function1[_, _] => true
case _: Function2[_, _, _] => true
...
case _: Function22[...] => true
case _: PartialFunction[_, _] => true
case _ => false
}
在 Scala 中,您可以将函数视为具有公共apply
方法的对象。我不熟悉新的 scala 2.10 反射 api,但您始终可以使用传统的 java 方式:
def isFunction(x:Any) = x.getClass.getMethods.map(_.getName).exists{name =>
name == "apply" || name.startsWith("apply$")
}
val set = Set(1, 2)
val str = "abc"
val func = { _:Int=> 1 }
val map = Map(1 -> 2)
val tuple = 1->2
val obj = new { def apply = 1 }
val obj2 = new { private def apply = 2 }
assert(isFunction(set))
assert(!isFunction(str))
assert(isFunction(func))
assert(isFunction(map))
assert(!isFunction(tuple))
assert(isFunction(obj))
assert(!isFunction(obj2))
我不是您解决方案的特别粉丝,我同意 Daniel Sobral 的评论。如果我必须实现它,我会通过隐式转换以一种类型安全的方式来实现它
trait IsFunctionable {
def isFunction : Boolean
}
object IsFunctionable {
object IsFunction extends IsFunctionable {
def isFunction = true
}
object IsNotFunction extends IsFunctionable {
def isFunction = false
}
implicit def function0ToIsFunctionable[A<:Function0[_]](a:A):IsFunctionable = IsFunction
implicit def function1ToIsFunctionable[A<:Function1[_,_]](a:A):IsFunctionable = IsFunction
implicit def function2ToIsFunctionable[A<:Function2[_,_,_]](a:A):IsFunctionable = IsFunction
// and so on
implicit def anyToIsFunctionable[A](a:A):IsFunctionable = IsNotFunction
}
现在您可以愉快地在 repl 中进行测试:
scala> import IsFunctionable._
import IsFunctionable._
scala> val a: Int => Int = _ * 2
a: Int => Int = <function1>
scala> val b: (Int,Int) => Int = (_*_)
b: (Int, Int) => Int = <function2>
scala> a(3)
res0: Int = 6
scala> b(2,4)
res3: Int = 8
scala> a.isFunction
res4: Boolean = true
scala> b.isFunction
res5: Boolean = true
scala> "Hello".isFunction
res6: Boolean = false