Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Tree traversal primitives (clojure.walk):

    (defn walk [inner outer form]
      (cond
       (list? form) (outer (with-meta (apply list (map inner form)) (meta form)))
       (instance? clojure.lang.IMapEntry form)
       (outer (clojure.lang.MapEntry/create (inner (key form)) (inner (val form))))
       (seq? form) (outer (with-meta (doall (map inner form)) (meta form)))
       (instance? clojure.lang.IRecord form)
         (outer (reduce (fn [r x] (conj r (inner x))) form form))
       (coll? form) (outer (into (empty form) (map inner form)))
       :else (outer form)))
    
    (defn postwalk [f form]
      (walk (partial postwalk f) f form))
    
    (defn prewalk [f form]
      (walk (partial prewalk f) identity (f form)))

Another reason why this perlisism holds:

    9. It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.
"Let's move on."


In addition, clojure.core has the handy tree-seq function:

    (defn tree-seq
      "Returns a lazy sequence of the nodes in a tree, via a depth-first walk.
       branch? must be a fn of one arg that returns true if passed a node
       that can have children (but may not).  children must be a fn of one
       arg that returns a sequence of the children. Will only be called on
       nodes for which branch? returns true. Root is the root node of the
      tree."
      {:added "1.0"
       :static true}
       [branch? children root]
       (let [walk (fn walk [node]
                    (lazy-seq
                     (cons node
                      (when (branch? node)
                        (mapcat walk (children node))))))]
         (walk root)))


    (defn tree-seq-breadth
      "Like tree-seq, but in breadth-first order"
      [branch? children root]
      (let [walk (fn walk [node]
                   (when (branch? node)
                     (let [cs (children node)]
                       (lazy-cat cs (mapcat walk cs)))))]
        (cons root (walk root))))



Didn't Wirth(may be it was someone else) say that it is better to have a complex data structure and simple algorithm/code that works on them than having simple data structures and complex code.

Complex data structures absorb lot of the complexity of the problem and reduce the complexity of the rest of the code.


Linus Torvalds also spoke in favour of using adequate data structures instead of the code.


It is even better to have 100 functions work on 100 data structures. Powerful programming languages like Lisp and Haskell give you that. Generics gives you most of that.

If every ounce of performance matters, e.g. in a database, you want 10000 functions, 100 for each data structure.


Lisp gives you an infinite amount of functions that operate on one data structure: the cons cell. :P

I guess all you really need are dynamically allocated arrays. A cons cell is an array of two. A struct with N fields is an array of N. Everything else is built on that.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: