Thanks for your suggestion, didn't know about that! One of the things that 
made someone say that "Clojure looks like a language from the near future". 
However, I'm having a hard time using it with its full power. Could you 
recommend any other resource, besides the overview page on github, to learn 
pattern matching? Maybe a project that uses them?

For the record, my code uses a simple truth table now:

(defn add-edge
  ([g v1 v2 & vs] (add-edge g (concat [v1 v2] vs)))
  ([g edge]
   (let [two? (= 2 (count edge))
         dist? (apply distinct? edge)
         e (match [(hyper? g) (looped? g)] ; e will be nil if edge is 
invalid for this graph
             [false false] (when (and two? dist?) edge)
             [false true ] (when two?  edge)
             [true  false] (when dist? edge)
             [true  true ] edge]
     (if e
       (update-in g [:edges] conj (if (directed? g) (vec e) (set e)))
       g))))

On Wednesday, September 4, 2013 7:07:06 PM UTC-3, Leonardo Borges wrote:
>
> You could use pattern matching with core.match 
> On 05/09/2013 6:57 AM, "Bruno Kim Medeiros Cesar" 
> <bruno...@gmail.com<javascript:>> 
> wrote:
>
>> I'm writing (another) basic graph library, and would like to treat inputs 
>> depending on the type of the graph. A graph can be
>>
>>    - Directed, in which case edges are vectors. Otherwise, edges are 
>>    sets; 
>>    - Looped, allowing edges from a node to itself; 
>>    - Pseudo (or multi), allowing multiples edges between the same 
>>    endpoints; and
>>    - Hyper, allowing edges with more than two vertices.
>>
>> To illustrate better these characteristics you can think of a scientific 
>> publication network as a directed, looped, pseudo-hypergraph. Vertices are 
>> authors, and edges are articles containing multiple researchers (hyper) who 
>> can publish alone (looped). There are multiple articles between the same 
>> researchers (pseudo) and in some contexts author order matters (directed). 
>>
>> Now, I've created a flowchart <http://imgur.com/IdgsGFG> to decide if an 
>> edge should be conjed in a graph :edges entry, that leads to the following 
>> straightforward function:
>>  (defn add-edge 
>>   ([graph v1 v2 & vs] (add-edge graph (concat [v1 v2] vs)))
>>   ([graph edge]
>>   (if (and (multi? graph) (not= 2 (count edge))) 
>>     graph
>>     (if (and (looped? graph) (not (distinct? edge)))
>>       graph
>>       (let [e (if (directed? edge) (vec edge) (set edge))]
>>         (update-in graph [:edges] conj e))))))
>>
>> That looks ugly and a pattern that could propagate in a codebase. So I 
>> tried to factor out multimethods from it, and ended with the following:
>>
>> (defmulti ^:private add-edge0 (fn [g e] (hyper? g)))
>> (defmulti ^:private add-edge1 (fn [g e] (looped? g)))
>> (defmulti ^:private add-edge2 (fn [g e] (directed? g)))
>> (defn     ^:private add-edge3 [g e]
>>   (update-in g [:edges] conj e))
>>
>> (defmethod add-edge0 :hyper [g e] (add-edge1 g e))
>> (defmethod add-edge0 :default [g e] (if (= 2 (count e))
>>                                       (add-edge1 g e)
>>                                       g))
>> (defmethod add-edge1 :looped  [g e] (add-edge2 g e))
>> (defmethod add-edge1 :default [g e] (if (distinct? e)
>>                                       (add-edge2 g e)
>>                                        g))
>> (defmethod add-edge2 :directed [g e] (add-edge3 g (vec e)))
>> (defmethod add-edge2 :default  [g e] (add-edge3 g (set e)))
>>
>> (defn add-edge
>>   ([g v1 v2 & vs] (add-edge g (concat [v1 v2] vs)))
>>   ([g edge]       (add-edge0 g edge)))
>>
>> That doesn't look much better, as the amount of boilerplate increased, 
>> but at least the concerns for each type are separated.
>>
>> Do you have any suggestions on how to improve this design? Thanks for any 
>> consideration!
>>
>> Bruno Kim Medeiros Cesar
>> Engenheiro de Computação
>> Pesquisador em Redes Complexas
>> www.brunokim.com.br
>>  
>> -- 
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com<javascript:>
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com <javascript:>
>> For more options, visit this group at
>> http://groups.google.com/group/clojure?hl=en
>> --- 
>> You received this message because you are subscribed to the Google Groups 
>> "Clojure" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to clojure+u...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to