Functional programming 更改为尾部递归SML

Functional programming 更改为尾部递归SML,functional-programming,sml,tail-recursion,Functional Programming,Sml,Tail Recursion,好的,我想把这个函数改成尾部递归。我对tailrecursive的定义是使用“局部帮助函数”来累积我的答案并返回它,而不递归调用主函数 这些功能正常工作 fun same_string(s1 : string, s2 : string) = s1 = s2 fun all_except_option (name, []) = NONE | all_except_option (name, x::xs)= case same_string (x , name) of true =>

好的,我想把这个函数改成尾部递归。我对tailrecursive的定义是使用“局部帮助函数”来累积我的答案并返回它,而不递归调用主函数

这些功能正常工作

fun same_string(s1 : string, s2 : string) =
s1 = s2

fun all_except_option (name, []) = NONE
  | all_except_option (name, x::xs)=
case same_string (x , name) of
true  => SOME xs
  | false => case all_except_option(name,xs) of
         NONE   => NONE
           | SOME z => SOME(x::z)

fun get_substitutions1 ([],name2)    = [] (*get_substitutions2 is same but tail recursive *)
  | get_substitutions1 (x::xs,name2) = 
    case all_except_option (name2,x) of
        NONE   => get_substitutions1 (xs,name2)
      | SOME z  => z @ get_substitutions1(xs,name2)
下面是我在尾部递归方面的尝试,这些尝试不起作用,我认为我缺少了一些基本的东西,因为我在SML方面缺乏经验,所以我忽略了这些东西

fun get_substitutions2 (lst,name3) = 
let fun aux (xs,acc) =
 case all_except_option(name3,x::xs) of
     NONE   => aux(xs, acc)
   | SOME z => aux(xs, z::acc)
in
aux(lst,[])
end

两个“get_substitution”函数应该做相同的事情。 比较String1和stringlist,返回由包含String1减去String1的所有列表组成的单个列表

我尝试使用尾部递归导致了以下错误

Error: unbound variable or constructor: x

uncaught exception Error
  raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
             ../compiler/TopLevel/interact/evalloop.sml:44.55
             ../compiler/TopLevel/interact/evalloop.sml:296.17-
下面是调用
get\u substitutions2
的几个示例:

get_substitutions2 ([["foo"],["there"]], "foo"); (* = [] *)
get_substitutions2 ([["fred","fredrick","freddie","F","freddy"],["Will","William","Willy","Bill"]],"Bill"); (* = ["Will","William","Willy"] *)
get_substitutions2 ([["a","b"],["a","c"],["x","y"]], "a"); (* = ["c","b"] *) 

您需要使用与
aux
函数定义中的
get\u substitutions1
相同的模式:

fun get_substitutions2 (lst,name3) = 
let fun aux ([],acc) = acc (* BASE CASE *)
      | aux (x::xs,acc) =  (* BINDING x IN PATTERN *)
 case all_except_option(name3,x) of
     NONE   => aux(xs, acc)
   | SOME z => aux(xs, z@acc)
in
aux(lst,[])
end

出现错误是因为(非常令人惊讶!)
x
在函数中未绑定。您没有在任何地方定义
x
,因此编译器不知道它是什么。我想你只是想要
xs
,而不是
x::xs
。然而,在花了大约10分钟查看您的代码之后,我无法确切地理解您正在尝试做什么,并且我认为您不知道您正在做什么。对于初学者来说,递归助手函数
acc
缺少基本情况。您还应该知道根据
z
的类型以及您对结果的要求,您应该使用
@
(连接)还是
(前置)。谢谢您的评论。你是对的,我不知道我在做什么,因为我被赋予了极端的基础知识,并被要求用我不熟悉的语言编写中间代码。这就是我寻求帮助的原因。我很难解决x::xs如何与hd xs同义,以及如何组合函数get_substitutions1中的列表。我不认为语言是问题所在,而认为语言是问题所在。您似乎不太熟悉很多函数式编程概念(递归、模式匹配等)。你应该试着问更具体的问题。与
#sml@irc.freenode.net
,因为您实际上可以在那里以适当的速度进行讨论,而不是在stackoverflow上留下评论。模式匹配正是我试图弄明白的。你提到了基本情况。正如我所展示的,这对于数字来说很简单。对于字符串,我知道的唯一方法是从一个空字符串开始,然后构建它以获得答案。这就是我想要做的。不是每个人都能接受“hey 1+1=2”,并从这个咒语中混淆。谢谢您的时间。从您发布的代码中,我甚至无法判断您正在使用字符串。但是,再一次,在这里发表评论实在太慢了,无法进行真正的讨论。您应该转到freenode.net(
#sml@irc.freenode.net
)。我现在在那里,还有很多其他人可能也经常使用SML(我更喜欢其他函数式语言,比如Clojure LISP和Scala,而不是ML)。如果你没有IRC客户端,你可以使用他们的在线界面:我认为这不对。当我们更改为尾部递归调用时,我们还需要更改追加顺序。应该是
aux(xs,acc@z)
而不是
aux(xs,z@acc)
fun get_substitutions2 (lst,name3) = 
let fun aux ([],acc) = acc (* BASE CASE *)
      | aux (x::xs,acc) =  (* BINDING x IN PATTERN *)
 case all_except_option(name3,x) of
     NONE   => aux(xs, acc)
   | SOME z => aux(xs, z@acc)
in
aux(lst,[])
end