Tassilo Horn <[email protected]> writes:

Hi Justin,

>> https://github.com/ninjudd/ordered-set
>
> Oh, yes, that looks exactly as what I was looking for.  And judging
> from the implementation, it looks promising performance-wise for my
> usecase.

I've now switched to that, and I get some slight performance
improvements.  However, I noticed that lazyness supresses the
"no-duplicates" property.

Here's the context: I develop a graph querying DSL in Clojure.  From a
given vertex v1, you can get the directly reachable vertices with right
to the connecting edge's direction using (--> v1), (<-- v1), or (<->
v1), which all return them as ordered-set.

Now I also have functions that compose these simple expressions, like
`p-alt' for a alternative of path expressions.

--8<---------------cut here---------------start------------->8---
(defn p-alt
  "Path alternative starting at v and traversing one of p.
v may be a vertex or a seq of vertices.
p is a varags seq of alternative path descriptions."
  [v & p]
  (apply concat
         (map #(p-apply v %1)
              p)))
--8<---------------cut here---------------end--------------->8---

You call it like (p-alt v1 --> <--), meaning one may either traverse one
outgoing or one incoming edge.

That function (and others) return lazy sequences, because of the use of
`apply', `concat' and friends.  Because the graph is finite, these seqs
should be finite as well, and most of the time one is interested in the
complete seqs of reachable vertices, anyway.  Now the problem is, that

  (count my-lazy-seq) != (count (apply ordered-set my-lazy-seq))

although the basic functions -->, <->, <-- that all these expressions
boil down to return ordered-sets.  So in my path iteration function
`p-+', which iterates the given path description one or many times, I
have to use this ugly code in order to specify a termination condition
(iteration may stop if nothing new is found anymore):

--8<---------------cut here---------------start------------->8---
(defn p-+
  "Path iteration starting at v and traversing p one or many times.
v may be a vertex or a seq of vertices.
p is a path description."
  ([v p]
     (p-+ (if (coll? v) v (ordered-set v)) p true))
  ([v p skip-v]
     (let [n (p-apply v p)
           ;; FIXME:
           ;; The transformation into ordered set is needed, because it seems
           ;; in the LazySeq form, (count vn) counts duplicates, which the
           ;; backing ordered-set would suppress...
           vn (apply ordered-set (concat v n))]
       (if (and (not skip-v)
                (= (count vn) (count v)))
         vn
         (recur (if skip-v n vn) p false)))))
--8<---------------cut here---------------end--------------->8---

Ok, long story.  I guess, my question is:

  Is there a way to drop lazyness completely for these path expression
  functions?

IMO, it doesn't make much sense in my context, because `p-+' has to
realize the seqs for its termination condition, and most of the time one
is interested in all reachable vertices, anyway.

Bye,
Tassilo

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to