(module functional

  (define (partiall fun val)
    (partiall fun val) partially applies fun to val, val fixing the left-most argument to fun
    (lambda args
      (apply fun (append args (list val)))))

  (define (partialr fun val)
    (partialr fun val) partially applies fun to val, val fixing the right most argument to fun
    (lambda args
      (apply fun (cons val args))))

  (define (make-arg-list null-symbol curried-args partial-list)
    (make-arg-list null-symbol curried-args partial-list) constructs
    the argument list to be passed to a function which has been partially
    PARTIAL-LIST is the list of arguments passed to the
      PARTIALX procedure where some elements are equal to NULL-SYMBOL,
      indicating that they should be replaced by CURRIED-ARGS in the same
    NULL-SYMBOL is either a symbol or false indicating which
      arguments in PARTIAL-LIST are provided by the partially applied
    CURRIED-ARGS are the arguments to put in the slots of PARTIAL-LIST
    see also: PARTIALX|#
    (let loop ((out '())
               (rst-c-args curried-args)
               (rst-prt partial-list))
       ((null? rst-prt) (reverse out))
       ((eq? (car rst-prt) null-symbol)
        (loop (cons (car rst-c-args) out)
              (cdr rst-c-args)
              (cdr rst-prt)))
        (loop (cons (car rst-prt) out)
              (cdr rst-prt))))))

  (define (symbol-or-false? p)
    (or (symbol? p)
        (not p)))
  (define (partialx . args)
    (partialx fun arg-or#f ...) partially applies fun to the arguments,
      leaving "unfixed" arguments which are false.
    (partialx sym fun arg-or-sym ...) partially applies fun to the
      arguments leaving "unfixed" all the values equal to sim.
      (map (partialx + 10 #f) (list 0 1 2 3 4))
      -> (10 11 12 13 14)
      (map (partialx 'tail string-append "dogs" 'tail)
           (list " are awesome" "are not awesome"))
      -> ("dogs are awesome" "dogs are not awesome")
    For convenience, a nickname is provided via PLX, which
    is just this function.
     ((procedure? (car args))
      (apply partialx (cons #f args)))
     ((symbol-or-false? (car args))
      (let ((nuller (car args))
            (fun    (cadr args))
            (rest   (cddr args)))
        (lambda lamargs (apply fun (make-arg-list nuller lamargs rest)))))))

  (define plx partialx)

  (define (fix f arg0 . args)
    (fix f arg0) Repeatedly applies f to arg (and subsequent results)
    until two successive results are equal by "eq?".
    (fix f arg0 predicate) like above but uses PREDICATE for equality.
    (cond ((= 0 (length args))
           (fix-helper f arg0 eq?))
          ((= 1 (length args))
           (fix-helper f arg0 (car args)))
          (else (error "Fix expects at most 3 arguments"))))
  (define (fix-helper f arg0 pred)
    (let loop ((arg arg0))
      (let ((argn (f arg)))
        (if (pred argn arg) argn
            (loop argn)))))

  (define (map-apply f list)
    (map-apply f list)
    equivalent to (map (plx apply f #f) list)
    (map (lambda (arguments) (apply f arguments)) list))
  (provide partiall partialr partialx plx map-apply fix))