Thanks, Alex, I was going down an over-engineering rabbit hole. Your 
solution just lacks a not before multi? and looped?.

On Thursday, September 5, 2013 6:24:13 PM UTC-3, Alex Baranosky wrote:
>
> ;; Better yet...
>
> (if (or (and (multi? graph) (not= 2 (count edge))) 
>         (and (looped? graph) (not (distinct? edge))))
>     graph
>     (let [e (if (directed? edge) (vec edge) (set edge))]
>       (update-in graph [:edges] conj e))))
>
>
> On Thu, Sep 5, 2013 at 2:22 PM, Alex Baranosky 
> <alexander...@gmail.com<javascript:>
> > wrote:
>
>> I'd just use a cond to flatten a nested if. That's usually all you need, 
>> imo.
>>
>>
>> On Thu, Sep 5, 2013 at 1:07 PM, Bruno Kim Medeiros Cesar <
>> bruno...@gmail.com <javascript:>> wrote:
>>
>>> 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> 
>>>> 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
>>>>>
>>>>> 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
>>>>>
>>>>> For more options, visit this group at
>>>>> http://groups.google.com/**group/clojure?hl=en<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.
>>>>>
>>>>> For more options, visit 
>>>>> https://groups.google.com/**groups/opt_out<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 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