SML,递归数据类型数组
SML, recursing a datatype array
我有这个数据类型
datatype json =
Num of real
| String of string
| False
| True
| Null
| Array of json list
| Object of (string * json) list
和此代码
fun mymatch (jobj,str) =
case jobj of
Array [] => NONE
| Array(Object oh::[]) => mymatch (Object oh, str)
| Array (Object oh::ot) =>
if isSome (assoc(str, oh)) then assoc(str, oh) else mymatch (Array ot, str)
| Object xs => assoc (str, xs)
| _ => NONE
有了这个辅助函数
fun assoc (k, ls) =
case ls of
[] => NONE
| (a,b)::[] => if k = a then SOME b else NONE
| (a,b)::xs => if k = a then SOME b else assoc (k,xs)
这应该是这样的
mymatch (Array [Object [("n", Num (4.0)),("b", True)],Object [("last", Num (4.0)),("foo", True)]],"foo")
和 return 在 string
"foo" 上匹配,在 Array
中搜索每个 Object
。正如您在代码中看到的那样,我实际上只处理 json
中符合匹配条件的两件事,即包含 Objects
的 Array
,然后发送 Object
s 待检查。这段代码有效,但它肯定来自粗野主义的编程学派,也就是说,它感觉像是一种拼凑。为什么?由于 mymatch
中的情况,我需要通过 Array
向下递归
...
| Array (Object oh::ot) =>
if isSome (assoc(str, oh)) then assoc(str, oh) else mymatch (Array ot, str)
...
到现在为止,我只处理了列表上的递归,您在其中检查汽车,然后在 cdr 上递归。同样,此代码有效,但我能感觉到我遗漏了一些东西。我需要检查 Array
的头部 Object
并在匹配时终止;否则,继续递归 - 全部在 option
return 世界中。有更优雅的方法吗?
写一个函数来匹配数组的"innards":
fun match_array (str, Object ob :: obs) = (case assoc (str, ob) of
NONE => match_array (str, obs)
| something => something)
| match_array _ = NONE;
然后重写mymatch
:
fun mymatch (str, Array a) = match_array (str, a)
| mymatch (str, Object ob) = assoc (str, ob)
| mymatch _ = NONE;
你也可以稍微简化一下assoc
:
fun assoc (k, []) = NONE
| assoc (k, (a,b)::xs) = if k = a then SOME b else assoc (k,xs);
我有这个数据类型
datatype json =
Num of real
| String of string
| False
| True
| Null
| Array of json list
| Object of (string * json) list
和此代码
fun mymatch (jobj,str) =
case jobj of
Array [] => NONE
| Array(Object oh::[]) => mymatch (Object oh, str)
| Array (Object oh::ot) =>
if isSome (assoc(str, oh)) then assoc(str, oh) else mymatch (Array ot, str)
| Object xs => assoc (str, xs)
| _ => NONE
有了这个辅助函数
fun assoc (k, ls) =
case ls of
[] => NONE
| (a,b)::[] => if k = a then SOME b else NONE
| (a,b)::xs => if k = a then SOME b else assoc (k,xs)
这应该是这样的
mymatch (Array [Object [("n", Num (4.0)),("b", True)],Object [("last", Num (4.0)),("foo", True)]],"foo")
和 return 在 string
"foo" 上匹配,在 Array
中搜索每个 Object
。正如您在代码中看到的那样,我实际上只处理 json
中符合匹配条件的两件事,即包含 Objects
的 Array
,然后发送 Object
s 待检查。这段代码有效,但它肯定来自粗野主义的编程学派,也就是说,它感觉像是一种拼凑。为什么?由于 mymatch
中的情况,我需要通过 Array
...
| Array (Object oh::ot) =>
if isSome (assoc(str, oh)) then assoc(str, oh) else mymatch (Array ot, str)
...
到现在为止,我只处理了列表上的递归,您在其中检查汽车,然后在 cdr 上递归。同样,此代码有效,但我能感觉到我遗漏了一些东西。我需要检查 Array
的头部 Object
并在匹配时终止;否则,继续递归 - 全部在 option
return 世界中。有更优雅的方法吗?
写一个函数来匹配数组的"innards":
fun match_array (str, Object ob :: obs) = (case assoc (str, ob) of
NONE => match_array (str, obs)
| something => something)
| match_array _ = NONE;
然后重写mymatch
:
fun mymatch (str, Array a) = match_array (str, a)
| mymatch (str, Object ob) = assoc (str, ob)
| mymatch _ = NONE;
你也可以稍微简化一下assoc
:
fun assoc (k, []) = NONE
| assoc (k, (a,b)::xs) = if k = a then SOME b else assoc (k,xs);