如何在整个 SML 程序中将元素保留在列表中?
How to keep elements in list through out the program in SML?
假设我必须在每次调用函数时更新列表,以便保留列表的前一个元素。
这是我的尝试:
local
val all_list = [];
in
fun insert (x:int) : string = int2string (list_len( ((all_list@[x])) ) )
end;
问题是每次调用insert时,得到的输出都是“1”,表示list又被初始化到[]
但是我期望第一次调用插入时输出 "1"
,第二次调用输出 "2"
,等等
我无法提供解决方法。应该怎么做?
值在 SML 中是不可变的。 insert
是在 all_list
的值为 []
的上下文中定义的,您的代码不会更改该值。
all_list@[x]
不会改变值 all_list
-- 它 returns 一个全新的列表,您的代码会立即丢弃它(在获取其长度后)。
使用引用类型(SML 的不纯特性之一)可以完成您似乎想要做的事情,但生成的代码不会是惯用的 SML。它会破坏引用透明性(函数式编程语言的理想特性,其中使用相同输入调用的函数会产生相同的输出)。
您需要使用 side-effects。
大多数时候函数式程序员更喜欢使用 pure functions,它没有副作用。您的实现是一个纯函数,因此对于相同的输入,它总是 return 相同的值(在您的情况下,它 return 对于任何输入都是相同的值)。
您可以使用 参考资料 来解决这个问题。
标准 ML 参考速成班:
- 使用
ref
创建一个新的引用,ref
的类型是'a -> 'a ref
,所以它把任意值打包到一个引用单元格中,你可以稍后修改;
!
用于解包引用:(!) : 'a ref -> 'a
,在大多数命令式语言中,此操作是隐式的,但在 SML 或 OCaml 中不是;
(:=) : 'a ref * 'a -> unit
是一个用于修改引用的中缀运算符,下面是如何递增整数引用的内容:r := !r + 1
.
上面给出了以下代码(我将 x
s 添加到列表中,而不是附加它们):
local
val rxs = ref []
in
fun insert (x:int) : string =
(rxs := x :: !rxs;
Int.toString (length (!rxs)))
end
假设我必须在每次调用函数时更新列表,以便保留列表的前一个元素。
这是我的尝试:
local
val all_list = [];
in
fun insert (x:int) : string = int2string (list_len( ((all_list@[x])) ) )
end;
问题是每次调用insert时,得到的输出都是“1”,表示list又被初始化到[]
但是我期望第一次调用插入时输出 "1"
,第二次调用输出 "2"
,等等
我无法提供解决方法。应该怎么做?
值在 SML 中是不可变的。 insert
是在 all_list
的值为 []
的上下文中定义的,您的代码不会更改该值。
all_list@[x]
不会改变值 all_list
-- 它 returns 一个全新的列表,您的代码会立即丢弃它(在获取其长度后)。
使用引用类型(SML 的不纯特性之一)可以完成您似乎想要做的事情,但生成的代码不会是惯用的 SML。它会破坏引用透明性(函数式编程语言的理想特性,其中使用相同输入调用的函数会产生相同的输出)。
您需要使用 side-effects。 大多数时候函数式程序员更喜欢使用 pure functions,它没有副作用。您的实现是一个纯函数,因此对于相同的输入,它总是 return 相同的值(在您的情况下,它 return 对于任何输入都是相同的值)。
您可以使用 参考资料 来解决这个问题。
标准 ML 参考速成班:
- 使用
ref
创建一个新的引用,ref
的类型是'a -> 'a ref
,所以它把任意值打包到一个引用单元格中,你可以稍后修改; !
用于解包引用:(!) : 'a ref -> 'a
,在大多数命令式语言中,此操作是隐式的,但在 SML 或 OCaml 中不是;(:=) : 'a ref * 'a -> unit
是一个用于修改引用的中缀运算符,下面是如何递增整数引用的内容:r := !r + 1
.
上面给出了以下代码(我将 x
s 添加到列表中,而不是附加它们):
local
val rxs = ref []
in
fun insert (x:int) : string =
(rxs := x :: !rxs;
Int.toString (length (!rxs)))
end