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