在标准ml中定义嵌套函数

时间:2018-03-15 05:50:55

标签: sml smlnj

我是sml的新人。我试图将int转换为int list。例如,假设存在输入1234,则输出是类似[1,2,3,4]的列表。我的问题是,如何在sml中键入嵌套函数?让我们结束?有我的代码。

 fun digit (a : int): int =

    let
            fun size (a) = if a < 0 then nil
                    else x = Int.toString x then digit s = size(x)

            fun insert (num, nil) = [num]
                    |       insert (num,xs) = x :: insert ()

            fun convert (a, s) = if s < 0 then nil
                            else insert (a / (10*(s - 1)), xs)
                                    then convert(a - (10*(s - 1), s - 1)

    in

    end

2 个答案:

答案 0 :(得分:2)

fun areaCirle r:real = 
   let fun square x:real = x*x
       val pi = 3.14
   in 
      pi * square r
   end

例如,

and

或者,如果它们不是相互递归的,则预先定义需要事先调用的函数。如果它们是相互递归的,您可以查找关键字fun F2 ... fun F3 ... fun aFunctionCallingF2F3 = <make use of F2 F3 directly>

fun square x:real = x * x
fun areaCircle r = square r * 3.14

例如,

fun areaCircle r = square r * 3.14
fun square x:real = x * x

请注意,您无法执行

square
需要在areaCircle之前定义

UInt32

答案 1 :(得分:1)

嵌套函数只是将工作负载分成多个较小部分的一种方法。另一种选择是非嵌套库函数。主要区别在于没有嵌套的函数不会继承其父变量范围,因此它们只能使用自己的输入,并且嵌套的函数不能在任何地方使用别的,不能重复使用。让我们说你是第一次尝试这个问题:

fun digit_meh n = if n < 10 then [n] else n mod 10 :: digit_meh (n div 10)

你意识到它并没有完全符合你的要求:

- digit_meh 1234;
> val it = [4, 3, 2, 1] : int list
  • 您可以先移除最重要的数字,但计算并不像n mod 10那么简单,因为它取决于数字位数。

  • 您可以生成此列表,然后将其反转:

    fun digit n = rev (digit_meh n)
    

    但是函数digit_meh在此函数之外并不是特别有用,因此可以使用 local-in-end let-in-end隐藏它

    local
      fun digit_meh n = if n < 10 then [n] else n mod 10 :: digit_meh (n div 10)
    in
      val digit = rev o digit_meh
    end
    
    fun digit n =
        let fun meh n = if n < 10 then [n] else n mod 10 :: meh (n div 10)
        in rev (meh n) end
    

    请注意功能meh的{​​{1}}影子n digit副本的副本。

    为清楚起见,您还可以区别对变量命名。

  • 或者你可以看看n如何做它的事情并做到这一点。它基本上将其输入视为一个堆栈,并将顶部元素递归地放入一个新的堆栈中,以便顶部成为底部,就像StackOverflow的徽标看起来像是跳出来并倒置像{{3 }}:

    rev

    因为结果是在一个额外的参数中累积的,并且fun rev L = let fun rev_stack [] result = result | rev_stack (x::xs) result = rev_stack xs (x::result) in rev_stack L [] end 应该只接受一个参数,所以使用额外的累积参数嵌套一个函数是一个非常有用的技巧。

    你也可以模仿这种行为:

    rev

    这样,我们首先继续处理最不重要的数字,但我们将它放在堆栈fun digit N = let fun digit_stack n result = if n < 10 then n::result else digit_stack (n div 10) (n mod 10::result) in f N [] end 中,这意味着它最终位于底部/末尾。因此,我们不需要调用result并保存列表的迭代。

在实践中,您不必使用 local-in-end let-in-end 隐藏辅助功能;虽然在 let-in-end 的情况下继承父函数的范围很有用,但是一旦开始使用{{3}的模块,就没有必要隐藏你的函数。 (rev运算符):

:>

将其输入REPL时,只有相关功能可在模块外部使用:

signature DIGIT =
sig
  val digit : int -> int list
end

structure Digit :> DIGIT =
struct
  fun digit_stack n result =
      if n < 10
      then n::result
      else digit_stack (n div 10) (n mod 10::result)

  fun digit n = digit_stack n []
end