带有递归函数参数的Scala函数

时间:2016-01-27 16:59:03

标签: scala

我很好奇是否可以实现类似于这个Javascript函数的Scala函数。显然,我可以通过内部函数轻松完成。

知道Scala必须预先声明参数类型和arity,我只是想知道是否有任何我可以用来实现这个JS函数的东西。感谢。

.method public static 
    void validateAndPrint (
        int32 i
    ) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 57 (0x39)
    .maxstack 6
    .locals init (
        [0] class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, class [FSharp.Core]Microsoft.FSharp.Core.Unit>>,
        [1] class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, class [FSharp.Core]Microsoft.FSharp.Core.Unit>>, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>,
        [2] bool
    )

    IL_0000: ldstr "%i Greater than 100: %s"
    IL_0005: newobj instance void class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`5<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, class [FSharp.Core]Microsoft.FSharp.Core.Unit>>, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [mscorlib]System.Tuple`2<int32, string>>::.ctor(string)
    IL_000a: stloc.1
    IL_000b: call class [mscorlib]System.IO.TextWriter [mscorlib]System.Console::get_Out()
    IL_0010: ldloc.1
    IL_0011: call !!0 [FSharp.Core]Microsoft.FSharp.Core.PrintfModule::PrintFormatLineToTextWriter<class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, class [FSharp.Core]Microsoft.FSharp.Core.Unit>>>(class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.PrintfFormat`4<!!0, class [mscorlib]System.IO.TextWriter, class [FSharp.Core]Microsoft.FSharp.Core.Unit, class [FSharp.Core]Microsoft.FSharp.Core.Unit>)
    IL_0016: stloc.0
    IL_0017: nop
    IL_0018: ldloc.0
    IL_0019: newobj instance void FSSO.Test2/'validateAndPrint@14-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<string, class [FSharp.Core]Microsoft.FSharp.Core.Unit>>)
    IL_001e: ldarg.0
    IL_001f: ldarg.0
    IL_0020: ldc.i4.s 100
    IL_0022: cgt
    IL_0024: stloc.2
    IL_0025: ldloca.s 2
    IL_0027: constrained. [mscorlib]System.Boolean
    IL_002d: callvirt instance string [mscorlib]System.Object::ToString()
    IL_0032: call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32, string>::InvokeFast<class [FSharp.Core]Microsoft.FSharp.Core.Unit>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<!0, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<!1, !!0>>, !0, !1)
    IL_0037: pop
    IL_0038: ret
} // end of method Test2::validateAndPrint

1 个答案:

答案 0 :(得分:6)

如果我已正确理解你的问题,你的确可以做到这一点,而最着名的方法是使用所谓的Y-combinator。简而言之,Y-combinator将函数作为参数并继续应用它。 Y-combinator不了解所涉及的参数类型

rosetta code

右侧复制示例Y-combinator
def Y[A,B](f: (A=>B)=>(A=>B)) = {
  case class W(wf: W=>A=>B) {
    def apply(w: W) = wf(w)
  }
  val g: W=>A=>B = w => f(w(w))(_)
  g(W(g))
}

定义你的组合子。然后,您可以将其递归函数传递给它

val fac = Y[Int, Int](f => i => if (i <= 0) 1 else f(i - 1) * i)
fac: Int => Int = <function1>

然后给予评估的东西

scala> fac(6)
res0: Int = 720