我想學習標準毫升的新球衣,但我不明白如何迭代列表。如何迭代列表?
我想創建一個函數,它接受一個值和一個函數列表,並返回另一個字符串列表,如果當前函數在給定值時返回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