我是标准ML中的新手,对于知道如何用这种语言编码的人来说,我有一个很明显的问题。
我有一个原始功能如下:
fun getBlocked w =
case BlockingMgr.listBlockedSuccessors w
of nil => ""
| ws =>
concat (
List.map
(fn (r, w') => (
"v r1 w"
^
Int.toString (Node.getId w))
^ " w"
^ (Int.toString (Node.getId (w')))
^ "\n"
)
ws
)
这会给我一个完美的字符串,以便在我的程序中显示。
不幸的是,我还需要此字符串中'\ n'的数量。所以不是直接从字符串计算(这会很好),我想要制作另一个返回整数的函数:
fun getNbBlocked w =
let res = 0;
case BlockingMgr.listBlockedSuccessors w
of nil => res
| ws =>
List.map
(fn (r, w') => (
res = res+1
)
ws
但是我的大脑对程序/对象的思考太过分了,我不知道如何用函数式语言表达我想要的东西。
如果有人可以帮我调试这个功能,因为我真的不知道是什么问题:/(甚至更好,通过告诉我如何编写一个函数来计算'\ n'的数量来帮助我现有的字符串)
提前感谢您的帮助!
最诚挚的问候!
@molbdnilo你的解决方案似乎接近解决方案,但我没有设法使用它:/(不幸的是我是一个真正的初学者)。
我有这些功能(已经存在的功能和你的功能):
val res = 0
fun getBlocked w =
case BlockingMgr.listBlockedSuccessors w
of nil => ""
| ws =>
concat (
List.map
(fn (r, w') => (
"v r1 w"
^
Int.toString (Node.getId w))
^ " w"
^ (Int.toString (Node.getId (w')))
^ "\n"
)
ws
)
fun count c s = List.length (List.filter (fn x => x = c) (String.explode s));;
fun count_newlines s = count #"\n" s;;
fun af w = print(getBlocked w)
fun aff w = count_newlines(getBlocked w)
当我调用函数getBlocked()以显示创建的字符串
时我做的如下:
app af (Nodestore.listNodes ())
因为它正在调用print,所以它可以在任何地方调用。
但是对于你的函数,我需要使用它的返回值而我无法做到:/
我试着像:
res = (app aff Nodestore.listNodes())
(* We then, display the number of edges *)
print (Int.toString (res));
但遗憾的是,并不像我想的那么简单:/
我收到错误消息:
Error: src/output/modeloutput.sml 101.11.
Function applied to incorrect argument.
expects: _ -> [unit]
but got: _ -> [int]
in: app aff
Error: src/output/modeloutput.sml 101.11.
Function applied to incorrect argument.
expects: [Node.node list]
but got: [unit -> Node.node list]
in: (app aff) Nodestore.listNodes
Error: src/output/modeloutput.sml 101.11.
Function not of arrow type.
function: [unit]
in: ((app aff) Nodestore.listNodes) ()
pre codegen raised in 2.79 + 1.50 (35% GC)
pre codegen raised: Fail
Compile SML raised in 2.79 + 1.50 (35% GC)
Compile SML raised: Fail
答案 0 :(得分:2)
您的函数的主要问题是res = res + 1
是比较,而不是作业。
你需要忘记分配,甚至忘记存在这样的事情。
这是一种做你想做的事情的方法:
看起来像这样:
fun count c s = List.length (List.filter (fn x => x = c) (String.explode s))
fun count_newlines s = count #"\n" s
答案 1 :(得分:2)
也可以直接对字符串进行递归,而无需先将它们扩展到列表中:
fun countChar c "" = 0
| countChar c s = let val ch = String.sub (s,0) in
(if ch = c then 1 else 0) + countChar c (String.extract (s,1,NONE))
end;
String.sub (s,0)
对应于获取列表的头部,而String.extract (s,1,NONE)
对应于获取尾部。我怀疑这比使用explode
更有效,因为它不需要1次传递来构建列表然后另一次传递来处理列表,尽管这不太可能是显着的,甚至是显着的时间节省(除非你正在处理一些非常长的字符串)。
答案 2 :(得分:2)
我会在这里推荐John的解决方案,并可能将其扩展为尾递归:
fun countChar c s =
let val len = String.size s
fun cc i n = if i = len then n
else cc (i+1) (if String.sub (s, i) = c then n+1 else n)
in cc 0 0
end
答案 3 :(得分:0)
我不太清楚ML,但我相信你应该使用foldl,就像这样:
foldl op+ 0 f
其中op +是加号运算符,0是初始值,f是您的自定义,可能是匿名函数。