【问题标题】:printing string and calling recursive function打印字符串并调用递归函数
【发布时间】:2015-10-10 16:33:46
【问题描述】:

我目前正在学习 sml,但我有一个问题找不到答案。我已经用谷歌搜索了,但仍然没有找到任何东西。

这是我的代码:

fun diamond(n) =
  if(n=1) then (
    print("*")
  ) else (

    print("*")
    diamond(n-1)

  )

diamond(5);

那行不通。我希望代码显示与数字 n 一样多的 * 并且我想通过递归来做到这一点,但我不明白如何做到这一点。

当我尝试运行该代码时出现错误。这是错误:

新泽西州标准 ML v110.78 [构建时间:2015 年 8 月 20 日星期四 19:23:18] [opening a4_p2.sml] a4_p2.sml:8.5-9.17 Error: operator is not a 函数 [tycon mismatch] 运算符:表达式中的单位: (print "*") diamond /usr/local/bin/sml: Fatal error -- Uncaught exception Error with 0 raise at ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27

谢谢

【问题讨论】:

  • 你的输出是什么?
  • @Zabari 我收到一个错误。这是错误:新泽西州 v110.78 的标准 ML [构建:2015 年 8 月 20 日星期四 19:23:18] [打开 a4_p2.sml] a4_p2.sml:8.5-9.17 错误:运算符不是函数 [tycon 不匹配]运算符:表达式中的单元:(打印“*”)菱形/usr/local/bin/sml:致命错误-未捕获的异常错误,在../compiler/TopLevel/interact/evalloop.sml:66.19-66.27

标签: recursion sml smlnj


【解决方案1】:

您可以使用 ';' 在 ML 中产生副作用 它将评估';'之前的任何内容并丢弃其结果。

   fun diamond(n) =
      if(n=1)
      then (print "*"; 1)
      else (print "*"; diamond(n-1));

    diamond(5);

错误的原因是因为 ML 是一种强类型语言,虽然您不需要显式指定类型,但它会在编译时根据环境因素推断它们。出于这个原因,函数的每一次求值,像ifelse 这样的语句都需要求值为一个明确的单数类型。

如果您被允许执行以下操作:

      if(n=1)
      then 1
      else print "*";

然后编译器将分别为thenelse 分支获得不同的类型。 对于then 分支,类型为int -> int,而else 分支的类型为int -> unit 这种二分法在强类型语言下是不允许的。

当您需要评估为单一类型时,您将了解 ML 不支持执行指令块,正如我们在其他范式中通常看到的那样,天真地转换为 ML 会呈现如下内容:

....
    if(n=1)
    then (print "1"
          print "2"
         )
    else (print "3"
          diamond(n-1)
         )
...

因为 then 分支将评估为什么类型? int -> unit?那么另一个打印语句呢?一个语句必须返回一个单数结果(即使它是一个复合),这样就没有意义了。 int -> unit * unit 呢?除了从语法上讲,您没有将元组传达给编译器之外,这没有问题。

因此,以下将起作用:

fun diamond(n) =
  if(n=1)
  then (print "a", 1)  /* A tuple of the type unit * int */
  else diamond(n-1);

diamond(5);

在这种情况下,您有一个 int 类型的函数 -> unit * int。

因此,为了满足强类型函数式编程范式的要求,我们努力构建评估为一种结果类型的机制,因此我们需要与编译器沟通某些语句将作为指令执行,并且不得在所考虑的功能的类型下合并。 出于这个原因,你使用';'与编译器通信以简单地评估该语句并丢弃其结果,使其不被合并到函数的类型评估中。

就您的实际目标而言,以下是编写函数的更好方法,diamond as type int -> string:

fun diamond(n) =
  if(n=1)
  then "*"
  else "*" ^ diamond(n-1);

print( diamond(5) );

以上方式更多用于调试目的。

【讨论】:

  • 谢谢它有效,但我不明白为什么 1 在 print "*";
  • 根本不需要。我只是把它包括在内是为了强调做副作用的说明。这也很好用:fun diamond(n) = if(n=1) then print "*" else (print "*"; diamond(n-1)); diamond(5);
猜你喜欢
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
  • 2014-03-05
  • 2023-02-18
  • 1970-01-01
  • 2022-01-18
相关资源
最近更新 更多