我想学习标准毫升的新球衣,但我不明白如何迭代列表。如何迭代列表?
我想创建一个函数,它接受一个值和一个函数列表,并返回另一个字符串列表,如果当前函数在给定值时返回true。
功能就像这样('a -> bool) * string
,即一对函数和它的名字串。
该函数是一个curried函数,因此它的定义类似于“fun it x xs”。
我想非递归地做到这一点。
任何人都可以帮助我开始吗?
我想学习标准毫升的新球衣,但我不明白如何迭代列表。如何迭代列表?
我想创建一个函数,它接受一个值和一个函数列表,并返回另一个字符串列表,如果当前函数在给定值时返回true。
功能就像这样('a -> bool) * string
,即一对函数和它的名字串。
该函数是一个curried函数,因此它的定义类似于“fun it x xs”。
我想非递归地做到这一点。
任何人都可以帮助我开始吗?
一个自然而直接的函数可以很容易地用递归写出来。
fun itr x fs =
case fs
of [] => []
| (f, s) :: fs' => if f x
then s :: itr x fs'
else itr x fs'
或者,如果你不想在你的函数明确递归,您可以使用foldr
。
fun itr x fs =
List.foldr (fn ((f, s), ss) =>
if f x
then s :: ss
else ss) [] fs
而且,itr
是不是一个非常翔实的名字,所以你可能想选择一个不同的,更好地描述了什么是你正在尝试做的。
所以,如果我理解正确的话,你希望能够调用你的函数是这样的:
itr
3
[ ((fn i => i > 3), "greaterThanThree"),
((fn i => i mod 2 = 1), "odd"),
((fn i => 12 mod i = 0), "dividesTwelve")
]
和得到的结果一样["odd", "dividesTwelve"]
(因为odd
和dividesTwelve
是两个功能使用时就返回true
到3
)。
我有这个权利吗?
因此,我们可以通过书写开始:
(* Given a value and a list of named Boolean functions, returns a list of the names of the
* functions that return true for value.
*)
fun itr value namedFunctions =
...
既然你说你想“做这个非递归”,我认为你的意思是,你要使用的列表功能标准ML基础库,允许您通过提供独立处理列表元素的函数来处理列表;这些函数当然是使用递归实现的,但是如果itr
只是代表它们,那么itr
本身不需要递归。
鉴于这些要求,我看到两种方法。
一种方法是通过使用List.filter
(see List.filter
documentation here)得到的只是关于value
调用时返回true
的的namedFunctions
元素开始。要做到这一点,我们需要一个函数,命名函数(一('a -> bool) * string
,其中'a
是value
类型),并返回true
如果命名的函数返回true
;那就是:
(* A function that, given a named Boolean function, returns whether it returns true for
* value.
*)
fn (f, _) => f value
来让我们叫List.filter
像这样:
(* A list of the elements of namedFunctions that return true for value. *)
List.filter (fn (f, _) => f value) namedFunctions
一旦我们有了这一点,我们需要使用List.map
(see List.map
documentation here),以获得每个功能的只是名字:
(* A list of the names in namedFunctions that return true for value. *)
List.map #2 (List.filter (fn (f, _) => f value) namedFunctions)
(其中#2
是提取元组或记录的组件2
的函数;在命名为f联合,#2 namedFunction
是名称)。
将其组合在一起:
(* Given a value and a list of named Boolean functions, returns a list of the names of the
* functions that return true for value.
*)
fun itr value namedFunctions =
List.map #2 (List.filter (fn (f, _) => f value) namedFunctions)
另一种方法是既过滤和映射组合到单个步骤中,通过使用List.mapPartial
(见List.mapPartial
documentation here)。相反,正是我们想要的元素用一个函数,命名函数,并返回一个布尔值,然后将它们转换成我们希望通过使用一个函数,命名函数,并返回其名称形式的第一选择,我们可以结合步骤通过使用带有命名函数的函数,并且仅当我们需要时返回其名称。
标准ML,当我们想要的,我们用option
来表示的值并不总是存在的;例如,string option
手段“是一个字符串,有或全无”(see Option.option
documentation here;值得注意的是,虽然它的记录为Option.option
,它也可作为刚刚option
)。所以,这里的,需要一个命名函数返回只有当它为value
返回true其名称的功能:
(* A function that, given a named Boolean function, returns its name if it returns true
* for value, and nothing if it returns false.
*)
fn (f, name) => if f value then SOME name else NONE
这种功能被称为“部分功能” —它只是的一部分返回一个值其领域—,我们可以使用List.mapPartial
检索其结果只有那些地方都返回一个情况:
(* Given a value and a list of named Boolean functions, returns a list of the names of the
* functions that return true for value.
*)
fun itr value namedFunctions =
List.mapPartial (fn (f, name) => if f value then SOME name else NONE) namedFunctions
一般来说,要应用到List.map
的结果的任何时间或反之亦然,您可以使用List.mapPartial
将两个步骤组合在一起。 (在任何给定的情况下,但是,它可能是也可能不是一个好主意,这样做。我推荐哪一个更清晰。)
为什么你想这样做,非递归? ML的列表结构自然是递归的。 – voithos 2013-02-10 23:21:40
我很确定在SML中没有“非递归”的东西。没有循环控制流程结构。如下所述,你可以使用foldr,但这只是一个使用递归的高阶函数。 – dbmikus 2013-06-14 14:25:25
你可以在标准ML中编写命令式的代码,但并不漂亮。既有'while'又有'ref',例如'val x = ref 0; val_ = while!x <10 do x:=!x + 1'。 – 2013-08-06 11:27:28