Sml 在标准ml中定义嵌套函数

Sml 在标准ml中定义嵌套函数,sml,smlnj,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

我是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
有趣的数字(a:int):int= 让 乐趣大小(a)=如果a<0,则为零 else x=Int.toString x然后数字s=size(x) 有趣的插入(num,nil)=[num] |插入(num,xs)=x::插入() 乐趣转换(a,s)=如果s<0则为零 其他插入(a/(10*(s-1)),xs) 然后转换(a-(10*(s-1),s-1) 在里面 结束 或者,如果函数不是相互递归的,则定义需要事先调用的函数。如果函数是相互递归的,则可以查找关键字

fun F2 ...
fun F3 ...
fun aFunctionCallingF2F3 = <make use of F2 F3 directly>
请注意,您不能这样做

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

square
需要在areaCircle之前定义。

嵌套函数只是将工作负载分成多个更小部分的一种方法。另一种选择是非嵌套库函数。主要区别在于,非嵌套函数不会继承其父函数的变量范围,因此它们只能使用自己的输入,嵌套的函数在其他任何地方都不可用,无法重复使用。假设您正在尝试解决此问题:

fun digit_meh n = if n < 10 then [n] else n mod 10 :: digit_meh (n div 10)
  • 您可以先删除最重要的数字,但计算并不像
    nmod 10
    那样简单,因为它取决于位数

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

    fun digit n = rev (digit_meh n)
    
    但是函数
    digit_meh
    在该函数之外并不特别有用,因此可以使用local in end或let in 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
    
    当输入REPL时,只有相关功能在模块外可用:

    > structure Digit : {val digit : int -> int list}
      signature DIGIT = {val digit : int -> int list}
    - Digit.digit 1234;
    > val it = [1, 2, 3, 4] : int list
    

    关于你的第二个问题:是的。你需要输入结束。你指的是如何使用你在“输入结束”中定义的
    insert
    convert
    等函数吗?是的,我提到了你给出的链接。我在建议5中发现了这一点,但我不明白我应该在“输入”上键入什么,我想可能会遗漏“输入”行并执行数字函数,对吗?你应该尝试使用你之前在中的
    和'end'之间定义的函数。我写了一些东西。希望这会有帮助。我认为首先集中精力编写正确的非嵌套函数是一个好主意–这些都是胡说八道。我有点喜欢
    有趣的areaCircle r=square r*3.14square x=x*x
    。它可以让你把重要的函数放在最上面,就像你在Haskell做的那样,顶级函数顺序无关紧要,你有postfix
    where…
    @SimonShine,这太有效了lol。我实际上有时候更喜欢拆分函数。最近,我在一个类型检查项目中编写了长函数我真的很想分割函数…但不能这样做,因为野兽是相互递归的。。。
    - digit_meh 1234;
    > val it = [4, 3, 2, 1] : int list
    
    fun digit n = rev (digit_meh n)
    
    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
    
    fun rev L =
        let fun rev_stack [] result = result
              | rev_stack (x::xs) result = rev_stack xs (x::result)
        in rev_stack L [] end
    
    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
    
    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
    
    > structure Digit : {val digit : int -> int list}
      signature DIGIT = {val digit : int -> int list}
    - Digit.digit 1234;
    > val it = [1, 2, 3, 4] : int list