我对OCaml /函数式编程非常陌生,而且我对一些相对简单的其他语言的实现感到困惑。我可以使用任何和所有的帮助。
主要是:在我正在研究的程序中,我根据某个参数递增或递减变量。这是代表我所拥有的东西:
let tot = ref 0 in
for i = 0 to s do
if test_num > 0 then
tot := !tot + other_num
else
tot := !tot - other_num
done;;
这显然不是解决这个问题的方法,因为即使永远不会使用else
语句,代码的行为就好像每次一样,大概是因为它更接近底层程序?我知道OCaml有非常复杂的模式匹配,但在这个级别的男女同校中我需要访问我已经创建的一些列表,据我所知,我无法从顶级函数访问这些列表没有将它们全部作为参数传递。
我知道我会以错误的方式解决这个问题,但我不知道该如何做到这一点。
连连呢?感谢。
修改 这是一个更简洁的例子:
let ex_list = [1; -2; 3; -4] in
let max_mem = ref 0 in
let mem = ref 0 in
let () =
for i = 0 to 3 do
let transition = List.nth ex_list i in
if transition > 0 then (
mem := (!mem + 10);
) else
mem := (!mem - 1);
if (!mem > !max_mem) then (max_mem := !mem);
done;
print_int !max_mem; print_string "\n";
in !mem;
最后,当我打印max_mem
时,我得到19,尽管这个值应该是(0 + 10 - 1 + 10 - 1 = 18)。我的数学错误,或问题来自其他地方?
答案 0 :(得分:2)
您的代码对我来说很好。它作为实际代码没有多大意义,但我认为你只是想展示一个总体布局。它也是以命令式的方式写的,如果可能的话我通常会尽量避免。
OCaml中的if
就像在其他语言中一样,在程序的底部附近没有特别之处。 (更确切地说,它的行为类似于C和相关语言的? :
三元运算符;即,它是一个表达式。)
您的代码不会返回有用的值;它总是返回()
(典型的无趣值,称为“单位”)。
如果我们用常量替换你的自由变量(在这段代码中没有定义),并更改代码以返回一个值,我们可以运行它:
# let s = 8 in
let other_num = 7 in
let test_num = 3 in
let tot = ref 0 in
let () =
for i = 0 to s do
if test_num > 0 then
tot := !tot + other_num
else
tot := !tot - other_num
done
in
!tot;;
- : int = 63
#
如果您正在尝试学习函数样式(即没有可变变量),您可以将此循环编写为递归函数,并使tot
成为参数:
# let s = 8 in
let other_num = 7 in
let test_num = 3 in
let rec loop n tot =
if n > s then
tot
else
let tot' =
if test_num > 0 then tot + other_num else tot - other_num
in
loop (n + 1) tot'
in
loop 0 0;;
- : int = 63
如果你给了一个(编辑添加:小:-)你想要解决的自包含问题,可能会更容易提供帮助。
您问题的其他部分不够明确,无法提供任何建议。我可能会指出的一点是,在处理列表时使用模式匹配是完全惯用的。
此外,将事物作为参数传递并没有错。这就是为什么语言被称为“功能” - 你的代码由具有参数的函数组成。
<强>更新强>
我想写let () = expr1 in expr2
而不是expr1; expr2
。这只是我养成的一种习惯,抱歉,如果这让人感到困惑。实质是你正在评估第一个表达式只是为了它的副作用(它有类型unit
),然后返回第二个表达式的值。
如果您在for
之后没有内容,代码将评估为()
,正如我所说的那样。由于代码的目的似乎是计算!tot
的值,这就是我返回的内容。至少,这可以让你看到OCaml顶级的计算值。
tot'
只是另一个变量。如果直接从名为var
的变量计算新值,则通常将新值命名为var'
。它读作“var prime”。
更新2
您的示例代码工作正常,但它存在使用List.nth
遍历列表的问题,这是一个慢(二次)操作。事实上,您的代码自然被视为折叠。以下是您可以用函数式编写它的方法:
# let ex_list = [1; -2; 3; -4] in
let process (tot, maxtot) transition =
let tot' = if transition > 0 then tot + 10 else tot - 1 in
(tot', max maxtot tot')
in
List.fold_left process (0, 0) ex_list;;
- : int * int = (18, 19)
#
答案 1 :(得分:0)
除了Jeffrey的回答之外,让我再说一下,这不是你通常会在Ocaml中编写这样的代码的方式,因为它是一种非常低级的命令式方法。功能更强大的版本如下所示:
let high ex_list =
let deltas = List.map (fun x -> if x > 0 then 10 else -1) ex_list in
snd (List.fold_left (fun (n, hi) d -> (n+d, max (n+d) hi)) (0, 0) deltas)
let test = high [1; -2; 3; -4]