Search code examples
schemefoldchez-scheme

scheme- writing a foldl /fold-left like function that works on first 3 items of the given list


I would like to write a function that gets and infix expression and changes it to prefix. at first let's assume we only deal with + operator, so I want to change the expression 1+1+1 into: (+ (+ 1 1) 1)

I want to do it using foldl or foldl-like matter: taking the second item in the list (which is always the operand) appending it with the first and the third (in that order) then I would like the expression we've just appended to become the first item in the list so I would do the same on the rest of the list recursively.

Iv'e tried the following:

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

but then I realized that the lambda given to the fold-left has to have 2 arguments but I would like to deal with the first 3 items of the list.

I hope I've made myself clear cause it got a bit tricky..


Solution

  • A fold wont do what you want. If you imagine the expression (5 + 3 + 2) then using a fold with proc as the procedure do this:

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

    A way would be to make a function that returns the odd and even elements in their own list so that '(+ 2 - 3) becomes (+ -) and (2 3) and then you could do it like this:

    (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))
    

    However the size of both is much greater than just rolling your own recursion:

    (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)
    

    There is no operator precedence here. Everything is strictly left to right.