can you elaborate on #3? What constraints did you run into with type-based dispatch that a multimethod that dispatched on :op allowed you to get around? It seems like, if that's your pattern, lifting the :op field up into an actual record type would only give you MORE freedom. You rely on the convention of a type, and the typeclass-like protocol dispatch, rather than re-inventing the identifier with an :op field.

Just curious as to what problems that records have caused (especially since you could write multimethods that dispatched on type and change that later if you actually do need the flexibility).

Timothy Baldridge <mailto:tbaldri...@gmail.com>
January 19, 2014 5:10 PM
A couple of things on this subject:

1) protocols were invented primarily for their speed. If one was going to write Clojure in Clojure it would be a little hard to implement PersistentHashMaps using pure data. You have to start with something. Thus deftype and defprotocol were born.

2) Unlike in most OOP, the protocol methods are not tied to the object. Instead they are tied to the function. You can see that with the function clojure.core/extend. Extend says "when you call function A with a type T as the first argument, dispatch to function B". This is quite a bit different from normal polymorphism (especially in languages like Python/Ruby, etc).

3) Thirdly I'd say that using protocols/types for data is often considered a bit un-idiomatic. For example, see the ClojureScript compiler: https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/compiler.clj#L377

The AST of ClojureScript is stored in nested hashmaps, and dispatching is done on the :op value in each map. No records, no protocols, no types. Just hashmaps and multimethods. I would argue that this is the "Clojure way". Use data, except when performance requirements dictate otherwise. Almost everytime I've built a large codebase using protocols instead of multimethods, I've regretted it. "Data all the things"...as the saying goes.

Timothy Baldridge





--
“One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.”
(Robert Firth)
--
--
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.
James Reeves <mailto:ja...@booleanknot.com>
January 19, 2014 2:55 PM
On 19 January 2014 19:55, Brian Craft <craft.br...@gmail.com <mailto:craft.br...@gmail.com>> wrote:

    http://www.youtube.com/watch?v=ROor6_NGIWU

    Around 56:28 Rich is talking about whether components pass a data
    structure, or "an object that has all these verbs and knows how to
    do stuff ...".

    Clojure data types also have verbs, in protocols, and if one
    component passes a record to another component, the receiver will
    need to use those verbs to make use of the data. How is that
    different than the OOP example? There's the syntactic difference
    that in OOP you write it object, verb, arguments, and in clojure
    you write it verb, object, arguments. But that's trivial. How is
    it architecturally different to pass an object with methods vs
    passing a record with protocol?


Protocols should be considered a tool for polymorphism, rather than a tool for encapsulation. You shouldn't consider protocols to be tightly coupled to a record or type.

To give a more concrete example, consider a edn data structure like:

    #inst "2014-01-19T21:44:46.471-00:00"

By default Clojure reads this as a java.util.Date object, but we could equally read this as a org.joda.time.DateTime object, or a hirondelle.date4j.DateTime object.

All these implementations describe the same data, but will have subtly different methods and interfaces. The data structure serialised in edn doesn't mandate a particular class, or a particular set of methods.

Similarly, if we imagine a data structure like:

    #myapp/Person {:first "Fred" :last "Mertz"}

You should think of this as a map tagged with "#myapp/Person", not a representation of a specific Clojure record that has a specific set of functions. It's up to the receiver to interpret this data, and the functions that operate on this data might differ between components. For instance, a component that displays the data to the user might have a function to derive a person's full name, but a component that archives the data wouldn't need this functionality.

- James
--
--
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.
Brian Craft <mailto:craft.br...@gmail.com>
January 19, 2014 12:55 PM
http://www.youtube.com/watch?v=ROor6_NGIWU

Around 56:28 Rich is talking about whether components pass a data structure, or "an object that has all these verbs and knows how to do stuff ...".

Clojure data types also have verbs, in protocols, and if one component passes a record to another component, the receiver will need to use those verbs to make use of the data. How is that different than the OOP example? There's the syntactic difference that in OOP you write it object, verb, arguments, and in clojure you write it verb, object, arguments. But that's trivial. How is it architecturally different to pass an object with methods vs passing a record with protocol?
--
--
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.

--
Sam Ritchie (@sritchie)
Paddleguru Co-Founder
703.863.8561
www.paddleguru.com <http://www.paddleguru.com/>
Twitter <http://twitter.com/paddleguru>// Facebook <http://facebook.com/paddleguru>

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

<<inline: postbox-contact.jpg>>

<<inline: compose-unknown-contact.jpg>>

Reply via email to