;; 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.barano...@gmail.com> 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 <
> brunokim...@gmail.com> 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 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.
>>
>
>

-- 
-- 
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