scheme-编写一个foldl / fold-left like函数,该函数适用于给定列表的前3项

时间:2016-11-24 12:08:28

标签: scheme fold chez-scheme

我想编写一个获取和中缀表达式并将其更改为前缀的函数。 首先让我们假设我们只处理+运算符,所以我想将表达式1 + 1 + 1改为:(+(+ 1 1)1)

我想使用foldl或foldl-like来做到这一点: 取下列表中的第二项(总是操作数),用第一项和第三项(按顺序)附加它然后我希望我们刚刚附加的表达式成为列表中的第一项,所以我会在递归的列表的其余部分做同样的事情。

我尝试了以下内容:

(lambda (lst)
       (fold-left (lambda (pmLst)
          `(,((cadr pmLst) ,(car pmLst) (caddr pmLst)) ,(cddr pmLst)))
                        '()
                        lst))

然后我意识到给予fold-left的lambda必须有2个参数但是我想处理列表的前3项。

我希望我能让自己明白,因为它有点棘手......

1 个答案:

答案 0 :(得分:0)

A fold不会做你想要的。如果您想象表达式(5 + 3 + 2)然后使用带有proc的折叠作为过程执行此操作:

(proc 2 (proc '+ (proc 3 (proc '+ (proc 5 '())))))

一种方法是创建一个函数,在其自己的列表中返回奇数和偶数元素,以便'(+ 2 - 3)变为(+ -) and (2 3)然后你就可以这样做:

(define (infix->prefix expr)
  (if (pair? expr)
      (let-values ([(ops args) (split (cdr expr))])
        (fold (lambda (op arg acc)
                (list op acc (infix->prefix arg)))
              (car expr)
              ops
              args))
      expr))

然而,两者的大小远远大于滚动自己的递归:

(define (infix->prefix expr)
    (define (aux lst acc)
      (if (pair? lst)
          (aux (cddr lst)
               (list (car lst)
                     acc
                     (infix->prefix (cadr lst))))
          acc))

    (if (pair? expr)
        (aux (cdr expr) (infix->prefix (car expr)))
        expr))

(infix->prefix '(1 + 2 - 3))
; ==> (- (+ 1 2) 3)

此处没有运算符优先级。一切都严格从左到右。