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.