【问题标题】:Multiple if statemens in one Function in SMLSML 中的一个函数中的多个 if 语句
【发布时间】:2018-04-11 10:35:07
【问题描述】:

我想在 SML 中编写一个函数来检查参数 abc 是否为 true,如果是,则将 x 的值增加为 1.0、@987654327 @ 或 3.0。 例如:

fun calc(a:bool, b:bool, c:bool, d:int) = 
let
    val x = 0.0
in
    if a then x+1.0 else x+0.0
    ;if b then x+2.0 else x+0.0
    ;if c then x+3.0 else x+0.0
    ;if d<120 then x+4.0 else x+0.0
end

如果我使用abc trued &lt; 120 运行此代码,那么我会得到输出:

val it = 0.0 : real

但我想得到输出x

【问题讨论】:

  • 为什么不直接使用if a 而不是if a=true?其他子句也一样。
  • 谢谢。不知道我可以这样写。
  • 由于inend 之间的前三个表达式没有副作用,因此这些语句没有效果,整个块相当于if d&lt;120 then x+4.0 else x+0.0。您是否打算在这些子句中修改 x 的值?似乎是——但你是在命令式而不是功能上思考。另外——“将输出作为x”是什么意思?
  • 我想获取 x 的值。例如,如果我调用函数 calc(false,false,true,119) => 7.0.
  • 您需要在let 部分有几个连续的val 绑定(不需要分号),然后在in 部分有一个表达式。

标签: function if-statement standards sml ml


【解决方案1】:

首先,在单个函数定义中有多个if 表达式没有问题。例如,以下是没有问题的:

fun sign x = if x < 0  then ~1
            else if x = 0 then 0
            else 1;

请注意,if ... then ... else 是一个产生值的表达式,而不是控制结构。在 in 块中有几个独立的 if 表达式,用分号分隔。当您在这样的in 块中有多个表达式时,它们会按顺序计算,最后一个表达式的结果是该块的整体值。这仅在早期表达式有副作用时才有意义(例如,向终端打印某些内容或使用 ref 变量修改存储)。在您的情况下,您的表达式没有副作用,您只是丢弃了这些值(最后一个除外)。

您似乎想要拥有一系列 val 绑定,其中后面的绑定依赖于较早的绑定。这可以做到,但它需要在构造的let 部分中,而不是在in 部分中。比如:

fun calc(a:bool, b:bool, c:bool, d:int) = 
let
    val x = 0.0
    val x = if a then x+1.0 else x
    val x = if b then x+2.0 else x
    val x = if c then x+3.0 else x
in
    if d<120 then x+4.0 else x
end

例如:

- calc(false,false,true,119);
val it = 7.0 : real

您可以通过编写辅助函数更直接地做到这一点:

fun f(a,x) = if a then x else 0.0;

然后:

fun calc(a,b,c,d) =  
let
   val x = f(a,1.0) + f(b,2.0) + f(c,3.0)
in
   if d < 120 then x + 4.0 else x
end 

【讨论】:

  • "if ... then ... else ... 是一个返回值的函数,而不是一个控制结构"——它与函数不同,它的“操作数”仅根据条件进行评估;函数确实会评估其参数(严格评估)。我认为更准确的说法是:if ... 是一个表达式,而不是一个语句
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-10
  • 1970-01-01
  • 2020-02-29
  • 2017-04-23
相关资源
最近更新 更多