我正在编写一个接受int
列表的程序,并返回其交替总和的值。
Input: [1,2,3,4]
Output: 1 + (-2) + 3 + (-4)
下面是我为此尝试编写的代码,但我不断收到错误syntax error: inserting ORELSE
我的if then else
声明看起来是正确的,因此我不确定导致错误的原因
fun alternate([]) = 0
| alternate(x::xs, count) =
count = count + 1
if count mod 2 == 0 then (~x) + alternate(xs)
else x + alternate(xs)
答案 0 :(得分:2)
此错误是由count = count + 1
和if ... else ...
是多个表达式引起的。如果要执行多个表达式,可以编写如下代码:
(expression1;
expression2;
...
expressionN);
您的代码中还有其他两个错误
1.参数在函数alternate
的不同模式子句中的类型不同。
2.在SML中=
表示相等,而不是==
。
所以正确的解决方案可能如下所示:
fun alternate([]) = 0
| alternate(x::xs) =
let
fun alt([], count) = 0
| alt(x::xs, count) =
if count mod 2 = 0 then x + alt(xs, count+1)
else (~x) + alt(xs, count+1)
in
alt(x::xs, 0)
end;
答案 1 :(得分:1)
以my previous answer为基础我建议实施sum
:
val sum = foldr (op +) 0;
使用小错误修正复制此答案中的alternate
函数以获得完整性:
fun alternate l =
let
fun alternate1 [] = []
| alternate1 (x::xs) = x :: alternate2 xs
and alternate2 [] = []
| alternate2 (x::xs) = (~x) :: alternate1 xs
in
alternate1 l
end
然后您可以非常简单地定义alternate_sum
:
val alternate_sum = sum o alternate
当然会以表现的名义提出异议。 Haskell能够在这些类型的调用中执行砍伐森林/融合优化,因为它知道函数的纯度;标准ML不会要求这些优化,虽然有些实现可能会尝试它们,我不知道。
这个特定问题的开销可能是荒谬的,也可能不是荒谬的,但我认为这是函数式编程原则的一个很好的例子:从更简单,无法控制的行为中构建复杂的行为。此版本中的“举证责任”几乎全部在alternate
。 @ SunsetRider的版本很好(它可能会表现得更好)但是你可能会说代码更“单一”。
另外,@ SunsetRider的代码比它需要的要复杂一点,这个版本就足够了:
fun alternate l =
let
fun alt([], count) = 0
| alt(x::xs, count) =
if count mod 2 = 0 then x + alt(xs, count+1)
else (~x) + alt(xs, count+1)
in
alt(l, 0)
end
除了@SunsetRider所说的一条评论:一般来说,在函数式语言中x = x + 1
和其他突变都有点代码味道。您可以在代码中看到他们多次使用count+1
。从功能上思考,重要的是表达式所评估的是什么,而不是变量的状态,因此传递的值是至关重要的。这可以追溯到优秀且被低估的书Functional C by Pieter Hartel开头的精湛定义:
功能和命令范式从不同的角度运作。功能范例基于表达式的评估以及将变量绑定到值。基本程序短语是表达式,评估表达式的目的是产生一个值。评估子表达式的顺序不会影响结果值。
命令式范例基于语句的执行并且有一个商店,语句可以在其中留下结果。基本程序短语是声明;执行语句的目的是更改商店。执行语句的顺序 会影响商店中的结果值。商店中的当前值集称为程序的 state 。