我对SNL / NJ很新,并且想知道如何完成以下任务:
foo(stuff,counter)
{
while(counter > 0)
{
bar(stuff);
counter-1;
}
return;
}
这样的东西,但我该怎么减少?:
foo(stuff,counter) =
while counter > 0 do bar(stuff) ??? // how do I decrement counter here?
答案 0 :(得分:7)
我同意其他贡献者的意见,你通常应该使用递归而不是循环和变异来用功能语言来做这件事。
如果您真的想使用变异和循环,则需要使用称为引用的数据结构,这是一种“可变单元”。您使用ref
函数分配引用,并将初始内容传递给它。您可以使用!
运算符访问内容。然后使用:=
运算符设置新内容。因此,上面代码的字面翻译将如下所示。正如您所看到的,语法非常难看,这也是人们避免使用它的另一个原因。
fun foo (stuff, counter_start) =
let
val counter = ref counter_start
in
while !counter > 0 do (
bar stuff;
counter := !counter - 1
)
end;
答案 1 :(得分:6)
在一个功能程序中,一个可变变量变成一个参数,通常是一个嵌套的辅助函数。
因为在你的例子中,被变异的东西是aleady参数,所以不需要辅助函数。您的代码变为
fun foo stuff counter =
if counter > 0 then
( bar stuff
; foo stuff (counter-1)
)
else
()
当然这段代码仍然非常命令式......调用bar stuff
纯粹是为了副作用而执行的。不是ML-ish。
答案 2 :(得分:5)
简短回答:你没有。在函数式编程中,通常不会修改变量,这意味着循环是不可能的。相反,您可以使用递归实现相同的功能。同样,由于你没有,一般来说,有副作用,函数调用只有在返回数据时才有意义。所以吧(东西)可能不是很有用。它无法影响应用程序的其余部分。在函数式编程风格中,每次都应该对不同的数据调用bar()函数,并返回应用程序其余部分可以作用的内容。
(ML确实允许在某些情况下产生副作用,但为了简单起见,我们暂时忽略它)
你到底想要达到什么目的? (你需要循环什么,这些功能有什么作用?
如果您提供更多细节,我们可以更具体地解释您应该如何编写程序。但事实上,你的程序在功能风格上根本没有意义。
答案 3 :(得分:2)
我不知道ML,但这是一些类似ML的伪代码:
fun foo stuff 0 = return () | foo stuff counter = (bar stuff; foo stuff (counter - 1))
我不知道如何在ML中“链接”命令;分号只是一个占位符。
通常,你不会循环。我宁愿期待通常的高阶函数。当你习惯了那些,手动编写一个循环就像编写汇编程序一样。
编辑:根据评论修改代码