Scheme 方案中缀到后缀

Scheme 方案中缀到后缀,scheme,functional-programming,Scheme,Functional Programming,让我确定这是课堂作业的一部分,所以我肯定不是在寻找完整的代码答案。本质上,我们需要在Scheme中编写一个转换器,它接受一个以中缀格式表示数学方程的列表,然后输出一个以后缀格式表示方程的列表 我们已经提供了这样做的算法,非常简单。问题是,使用任何可用的命令式语言功能都有限制。我不知道如何以一种纯粹的功能性方式来做这件事。这是我们在我的程序中第一次介绍函数式编程 我知道我将使用递归来迭代中缀表达式中的项列表,就像这样 (define (itp ifExpr) ( ; do some p

让我确定这是课堂作业的一部分,所以我肯定不是在寻找完整的代码答案。本质上,我们需要在Scheme中编写一个转换器,它接受一个以中缀格式表示数学方程的列表,然后输出一个以后缀格式表示方程的列表

我们已经提供了这样做的算法,非常简单。问题是,使用任何可用的命令式语言功能都有限制。我不知道如何以一种纯粹的功能性方式来做这件事。这是我们在我的程序中第一次介绍函数式编程

我知道我将使用递归来迭代中缀表达式中的项列表,就像这样

(define (itp ifExpr)
  (
    ; do some processing using cond statement
    (itp (cdr ifExpr))
  ))
我已经尽我所能实现了所有的处理,但不知道如何完成其余的处理,但是我用来实现这一点的算法要求将操作符推到堆栈上,并在以后使用。我的问题是如何在这个函数中实现一个也可用于所有递归调用的堆栈;请参阅原始答案下面的新部分

为堆栈使用列表,并使其成为循环变量之一。例如

(let loop ((stack (list))
           ... ; other loop variables here,
               ; like e.g. what remains of the infix expression
            )
  ... ; loop body
  )
然后,每当你想在下一次迭代中改变堆栈上的内容时,基本上就是这么做

(loop (cons 'foo stack) ...)
还请注意,如果您需要按顺序进行一系列更新,您通常可以使用let*表单对其进行建模。这实际上不适用于Scheme中的向量,尽管它适用于Clojure的持久性向量(如果您愿意查看的话),但它适用于标量值和列表,以及SRFI 40/41流

针对您关于循环被排除在必备功能之外的评论:

(let loop ((foo foo-val)
           (bar bar-val))
  (do-stuff))
语法上的糖是什么

(letrec ((loop (lambda (foo bar) (do-stuff))))
  (loop foo-val bar-val))
然后,letrec扩展为一种let形式,它很可能使用与set等价的东西!或局部定义,但被认为是完美的功能。顺便说一句,您可以自由使用其他符号来代替循环。此外,这种let被称为“命名let”,有时也被称为“标记let”

您可能会记得let的基本形式:

在巧妙使用lambda的基础上,还有语法上的甜点:

所以,这一切都归结为程序应用,就像在Scheme中一样

命名let使自递归更漂亮,仅此而已;我相信你已经知道,当用函数的方式对迭代计算过程建模时,带尾部调用的自递归是一种方法

显然,这种特殊的循环结构也非常适合命令式编程——只需使用set!或者循环体中的数据结构变体,如果这是您想要做的-但是如果您远离破坏性函数调用,那么通过递归或标记的let本身进行循环就没有什么内在的必要性。事实上,循环递归是函数式编程中最基本的技术之一,这类家庭作业的重点就是要准确地教授…:-

如果您真的不确定是否可以使用它,或者如果您只使用命名let,是否可以清楚地理解所涉及的模式,那么您可以按照上面的解释,使用本地define而不是letrec来对其进行去糖化。

根据OP的评论进行更新;请参阅原始答案下面的新部分

为堆栈使用列表,并使其成为循环变量之一。例如

(let loop ((stack (list))
           ... ; other loop variables here,
               ; like e.g. what remains of the infix expression
            )
  ... ; loop body
  )
然后,每当你想在下一次迭代中改变堆栈上的内容时,基本上就是这么做

(loop (cons 'foo stack) ...)
还请注意,如果您需要按顺序进行一系列更新,您通常可以使用let*表单对其进行建模。这实际上不适用于Scheme中的向量,尽管它适用于Clojure的持久性向量(如果您愿意查看的话),但它适用于标量值和列表,以及SRFI 40/41流

针对您关于循环被排除在必备功能之外的评论:

(let loop ((foo foo-val)
           (bar bar-val))
  (do-stuff))
语法上的糖是什么

(letrec ((loop (lambda (foo bar) (do-stuff))))
  (loop foo-val bar-val))
然后,letrec扩展为一种let形式,它很可能使用与set等价的东西!或局部定义,但被认为是完美的功能。顺便说一句,您可以自由使用其他符号来代替循环。此外,这种let被称为“命名let”,有时也被称为“标记let”

您可能会记得let的基本形式:

在巧妙使用lambda的基础上,还有语法上的甜点:

所以,这一切都归结为程序应用,就像在Scheme中一样

命名let使自递归更漂亮,仅此而已;我相信你已经知道,当用函数的方式对迭代计算过程建模时,带尾部调用的自递归是一种方法

显然,这种特殊的循环结构也非常适合命令式编程——只需使用set!或者循环体中的数据结构变体,如果这是您想要做的,但是如果您远离destruc 在函数调用中,通过递归或标记的let本身进行循环并没有本质上的必要性。事实上,循环递归是函数式编程中最基本的技术之一,这类家庭作业的重点就是要准确地教授…:-


如果您真的不确定是否可以使用它,或者如果您只使用命名let,是否可以清楚地理解所涉及的模式,那么您可以按照上面的解释,使用本地define而不是letrec来对其进行去糖化。

我不确定我是否正确理解了这一点,但这种简单的解决方案有什么问题:

第一:

您可以测试您的论点是否确实是一个列表:

如果是:将函数的映射附加到只包含头部的a列表的尾部映射后处理程序cdr lst上。地图只是将后固定器再次应用于尾部的每个连续元素

如果不是,只需原封不动地返回参数

在我的实施过程中,有三行方案:

(postfixer '(= 7 (/ (+ 10 4) 2)))
致:

通过map实现的递归不需要循环,甚至不需要尾循环,不需要变异,通过map展现函数风格。除非我完全误解了你的观点,否则我看不出有必要在上面这么复杂


编辑:哦,现在我读到了,中缀,不是前缀,是后缀。嗯,除了采用第二个元素而不是第一个元素外,同样的总体思路也适用。

我不确定我是否完全正确理解了这一点,但这个简单的解决方案有什么问题:

第一:

您可以测试您的论点是否确实是一个列表:

如果是:将函数的映射附加到只包含头部的a列表的尾部映射后处理程序cdr lst上。地图只是将后固定器再次应用于尾部的每个连续元素

如果不是,只需原封不动地返回参数

在我的实施过程中,有三行方案:

(postfixer '(= 7 (/ (+ 10 4) 2)))
致:

通过map实现的递归不需要循环,甚至不需要尾循环,不需要变异,通过map展现函数风格。除非我完全误解了你的观点,否则我看不出有必要在上面这么复杂


编辑:哦,现在我读到了,中缀,不是前缀,是后缀。好的,除了使用第二个元素而不是第一个元素外,同样的一般思路也适用。

如果要将表达式从中缀更改为前缀,那么它是否像将列表中的第一个元素与列表中的第二个元素交换一样简单?你提到必须强制执行,这是否意味着你被限制使用某些功能?@grettke:可能需要处理更长的表达式,比如1+2*3。表达式可以是任意长度,包括括号。执行转换的实际过程不是问题所在,我的问题在于如何使用函数式语言下面由Michal Marczyk给出的答案似乎正是我所需要的。如果你想把一个表达式从中缀改为前缀,那么把列表中的第一个元素和第二个元素交换就这么简单了吗?你提到必须强制执行,这是否意味着你被限制使用某些功能?@grettke:可能需要处理更长的表达式,比如1+2*3。表达式可以是任意长度,包括括号。执行转换的实际过程不是问题所在,我的问题在于如何使用函数式语言下面由Michal Marczyk给出的答案似乎正是我所需要的。我肯定能用他教我的东西来完成这件事。我很感激这个答案,看起来它会起作用,但是作业中说我不能使用任何命令式语言功能,包括循环这不是一个强制性循环;它是某种递归模式的语法糖。我会马上编辑一个解释。太棒了,我真的很感谢你的帮助。这应该足够让我走了!我很感激你的回答,看起来它会起作用,但是作业中说我不能使用任何命令式语言功能,包括循环这不是一个强制性循环;它是某种递归模式的语法糖。我会马上编辑一个解释。太棒了,我真的很感谢你的帮助。这应该足够让我走了!