为什么不能调用本地定义的相互递归函数的后半部分?

时间:2019-08-12 01:28:01

标签: ats

作为对Why can't generic function templates use fnx to ensure they are tail-recursive?的跟踪,在阅读了Compiler Friendly Tail Recursion + Tail Recursion Checking in ATS之后,我想看看我是否可以确保我的函数是否优化了尾调用或编译失败。这是功能:

fun {a:t@ype} repeat {n:nat} .<n>.
( x: a
, t: int n
, f: a -> a
) : a =
  if t = 0 then x
  else repeat (f x, t - 1, f)

因此,首先,我将其做成一个普通的相互递归函数,如下所示:

fnx {a:t@ype} repeat1 {n:nat} .<n>.
( x: a
, t: int n
, f: a -> a
) : a =
  if t = 0 then x
  else repeat1 (f x, t - 1, f)
and {a:t@ype} repeat2 {n:nat} .<>.
( x: a
, t: int n
, f: a -> a
) : a = repeat1 (x, t, f)

但是它不能编译,似乎不喜欢泛型类型参数。因此,我将定义放入第三个父函数中,该父函数具有泛型参数,并仅调用相互递归对。

fun {a:t@ype} repeat {n:nat} .<n>.
( x: a
, t: int n
, f: a -> a
) : a =
let
  fnx repeat1 {n:nat} .<n>.
  ( x: a
  , t: int n
  , f: a -> a
  ) : a =
    if t = 0 then x
    else repeat1 (f x, t - 1, f)
  and repeat2 {n:nat} .<>.
  ( x: a
  , t: int n
  , f: a -> a
  ) : a = repeat1 (x, t, f)
in
  repeat1 (x, t, f)
end

中提琴,它可以编译!但是然后我尝试在最后一行中调用repeat2而不是repeat1,就像这样:

fun {a:t@ype} repeat {n:nat} .<n>.
  //snip...
in
  repeat2 (x, t, f)
end

这无法编译,并显示错误:

the dynamic identifier [repeat2] is unrecognized.

因此,标题中的问题。

1 个答案:

答案 0 :(得分:1)

使用“ fnx”定义相互递归函数时,只有第一个定义的函数可用于后续使用。