123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- ;; (define flat?
- ;; (λ (lst)
- ;; (cond
- ;; [(null? lst) #t]
- ;; [(pair? (car lst)) #f]
- ;; [(null? (car lst)) #f] ; needed because (pair? '()) is #f
- ;; [else (flat? (cdr lst))])))
- (library (prefix-to-postfix)
- (export arity-lookup-table
- known-operation?
- look-for-next-list
- adapt-arity
- prefix->postfix)
- (import
- (except (rnrs base) let-values map)
- (only (guile)
- lambda* λ
- simple-format
- current-output-port)
- (srfi srfi-69) ; hash-table
- (srfi srfi-1) ; lists
- )
- (define arity-lookup-table
- (alist->hash-table
- '((+ . 3)
- (- . 2)
- (* . 2)
- (/ . 2))))
- (define known-operation?
- (λ (op)
- (hash-table-exists? arity-lookup-table op)))
- (define look-for-next-list
- (λ (lst callback)
- "LST is the list which is looked at element by element, to find the
- next sublist. CALLBACK is the function called for the next found
- sublist."
- (cond
- [(null? lst) '()]
- [(null? (car lst))
- (cons '() (look-for-next-list (cdr lst) callback))]
- [(pair? (car lst))
- (cons (callback (car lst))
- (look-for-next-list (cdr lst) callback))]
- [else
- (cons (car lst)
- (look-for-next-list (cdr lst) callback))])))
- (define adapt-arity
- (λ (lst)
- ;; (+ 1 2 3 4) --> (+ 1 (+ 2 3 4)) --> (+ 1 (+ 2 (+ 3 4)))
- (let ([operation (car lst)])
- (cond
- ;; base case empty list
- [(null? lst) '()]
- [(known-operation? operation)
- (let ([wanted-arity (hash-table-ref arity-lookup-table (car lst))])
- ;; check, if we have sufficient arguments for another "split"
- (cond
- [(<= (length lst) wanted-arity)
- (cons (car lst)
- ;; But there could still be other operations in the
- ;; remaining too few arguments, so we need to check,
- ;; whether they are operations and then adapt their
- ;; arity as well.
- (look-for-next-list (cdr lst) adapt-arity))]
- [else
- ;; make a proper list - append takes 2 proper lists as input
- (append
- ;; The list still contains the operation. Take 1 less
- ;; argument than operation arity to keep 1 argument for the
- ;; new call to the operation.
- (take lst wanted-arity)
- ;; Build the last argument, which is a new call to the
- ;; operation with the remaining arguments. However, those
- ;; could be too many, so do a recursive call.
- (list
- (adapt-arity
- (cons operation
- (drop lst wanted-arity)))))]))]
- ;; Ignore unrecognized operations. We do not have arity
- ;; information for them, so just leave them as they are.
- [else lst]))))
- (define prefix->postfix
- (λ (lst)
- (cond
- [(null? lst) '()]
- [else
- (append
- ;; "Look for the next sublist and call me back, when you find
- ;; it!"
- (look-for-next-list (cdr lst)
- prefix->postfix)
- (list (car lst)))])))
- (define (flatten lst)
- (let loop ([remaining-lst lst]
- [acc '()])
- (cond
- [(null? remaining-lst) acc]
- [(pair? remaining-lst)
- (loop (car remaining-lst)
- (loop (cdr remaining-lst)
- acc))]
- [else
- (cons remaining-lst acc)])))
- (simple-format (current-output-port)
- "adapted arity: ~a\n"
- (adapt-arity '(+ 1 2 (- 3 4) 5)))
- (simple-format (current-output-port)
- "postfix: ~a\n"
- (prefix->postfix (adapt-arity '(+ 1 2 (- 3 4) 5))))
- (simple-format (current-output-port)
- "flattened: ~a\n"
- (flatten (prefix->postfix (adapt-arity '(+ 1 2 (- 3 4) 5))))))
|