Fixed point combinator for mutually recursive functions?

后端 未结 3 1557
眼角桃花
眼角桃花 2021-01-02 01:38

Is there a fixed point combinator for creating tuples of mutually recursive functions? I.e. I\'m looking for something like the Y-Combinator but which takes multiple \"recu

3条回答
  •  Happy的楠姐
    2021-01-02 02:08

    The creature you are looking for is Y* combinator.

    Basing on this page by oleg-at-okmij.org I ported the Y* to Clojure:

    (defn Y* [& fs]
      (map (fn [f] (f))
        ((fn [x] (x x))
          (fn [p]
            (map
              (fn [f]
                (fn []
                  (apply f
                    (map
                      (fn [ff]
                        (fn [& y] (apply (ff) y)))
                      (p p)))))
              fs)))))
    

    The classic example of mutual recursive function is even/odd so here is the example:

    (let
      [[even? odd?]
       (Y*
         (fn [e o]
           (fn [n]
             (or (= 0 n) (o (dec n)))))
         (fn [e o]
           (fn [n]
             (and (not= 0 n) (e (dec n)))))
         )
       ]
      (do
        (assert (even? 14))
        (assert (odd? 333))
        ))
    

    You can easily blow the stack with this functions if you use big enough arguments, so here is trampolined version of it for example completeness which do not consume stack at all:

    (let
      [[even? odd?]
       (Y*
         (fn [e o]
           (fn [n]
             (or (= 0 n) #(o (dec n)))))
         (fn [e o]
           (fn [n]
             (and (not= 0 n) #(e (dec n)))))
         )
       ]
      (do
        (assert (trampoline even? 144444))
        (assert (trampoline odd? 333333))
        ))
    

    The Y* combinator is very useful for defining mutual recursive definitions of monadic parsers, of which I'll blog soon on lambder.com , stay tuned ;)

    -- Lambder

提交回复
热议问题