在标准 ml 中定义嵌套函数
Define nested functions in standard ml
我是sml新手。我试图将 int 转换为 int 列表。例如,假设有一个输入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
fun aFunctionCallingF2F3 someVariables =
let
<define some functions and local variables here>
fun F2 ...
fun F3 ...
val v1 ...
val v2 ...
in
<Make use of the functions/variables you defined above and `someVariables`>
end
例如,
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之前定义。
嵌套函数只是将工作量分成多个较小部分的一种方法。另一种选择是 non-nested 库函数。主要区别是非嵌套函数不继承其父变量范围,因此它们只能使用自己的输入,而嵌套函数在其他任何地方都不可用,不能 re-used.假设您要先解决这个问题:
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
的 n
副本遮蔽了 digit
的 n
副本。
为清楚起见,您还可以为变量命名。
或者您可以看看 rev
是如何做的,然后就去做。它基本上将其输入视为堆栈并递归地将顶部元素放入新堆栈中,以便顶部成为底部,很像 Whosebug 的徽标如果它跳出并像 slinky spring 一样颠倒着陆时的样子:
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
,这意味着它最终位于底部/末尾。所以我们不需要调用 rev
并保存列表的迭代。
实际上,您不必使用 local-in-end 或 let-in-end 来隐藏辅助函数;虽然在 let-in-end 的情况下继承父函数的范围很有用,但一旦开始使用带有 opaque signatures 的模块就没有必要隐藏你的函数(:>
运算符):
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
由于这是进入 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
我是sml新手。我试图将 int 转换为 int 列表。例如,假设有一个输入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
fun aFunctionCallingF2F3 someVariables =
let
<define some functions and local variables here>
fun F2 ...
fun F3 ...
val v1 ...
val v2 ...
in
<Make use of the functions/variables you defined above and `someVariables`>
end
例如,
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之前定义。
嵌套函数只是将工作量分成多个较小部分的一种方法。另一种选择是 non-nested 库函数。主要区别是非嵌套函数不继承其父变量范围,因此它们只能使用自己的输入,而嵌套函数在其他任何地方都不可用,不能 re-used.假设您要先解决这个问题:
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
的n
副本遮蔽了digit
的n
副本。为清楚起见,您还可以为变量命名。
或者您可以看看
rev
是如何做的,然后就去做。它基本上将其输入视为堆栈并递归地将顶部元素放入新堆栈中,以便顶部成为底部,很像 Whosebug 的徽标如果它跳出并像 slinky spring 一样颠倒着陆时的样子: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
,这意味着它最终位于底部/末尾。所以我们不需要调用rev
并保存列表的迭代。
实际上,您不必使用 local-in-end 或 let-in-end 来隐藏辅助函数;虽然在 let-in-end 的情况下继承父函数的范围很有用,但一旦开始使用带有 opaque signatures 的模块就没有必要隐藏你的函数(:>
运算符):
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
由于这是进入 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