In a possible messaging system, a user could denote a recipient using one of three ways - 1) select an existing user id, 2) enter a new name and email, 3) pick a placeholder "all my team mates".
Possible F# (might not compipe!!) Recipient = | Placeholder of string | Existing of ContactId | OneoffRecipient of string * string Possible options in Clojure {:type :placeholder ; or :existing :one-off :placeholder-text :all-my-team-mates :name nil :email nil :contact-id nil } ;; or (defrecord PlaceholdRecipient [placeholder-text]) (defrecord ExistingReceipient [contact-id]) (defrecord OneoffReceipient [name email]) ;; or [:one-off name email] [:existing contact-id] [:placeholder text] ;; [:self] The variant needed not be a two element vector. It is a 1 or more element vector. We could just as easily have a fourth variant [:self] with no data to indicate send message to self. To actually use the above data structures and get the actual email addresses from them, we need atleast three methods - 1) fetch the emails of all the users team mates, 2) fetch the email for a contact in the datastore, 3) return the email as is. We could implement these using a multi method or implement some protocol or use a pattern matched method. Each choice has a different extensibility story and are all equally valid. We don't always replace every hashmap with a record. Variants are a viable alternative over using a map like the one shown in the first Clojure choice. >> As much as possible I try to build my apps in such a way that the program can self-explore the data you give it to self-optimize, self-extend, or otherwise provide flexibility to the programmer. You can't do that with a variant as a vector. Hand a vector to a function and the logic has to be something like "If this is a two element vector and the first thing is a keyword, then this might be a variant, but I'm not sure because it could also just be a vector". While if you pass in a record, type, or even a variant type, it's trivial to have a program recognize that value and act upon it. I have no experience writing apps that had to operate on any arbitrary data with any arbitrary structure. Pretty much all the functions in my apps could rely on data arriving in a particular format in a particular order (positional destructuring). More importantly we are pretty much agreeing that [:tagged vectors with some data] are only a representation of a variant. One chosen out of convenience and existing feature set. We could have a defrecord Variant with two fields, a type keyword and value hashmap. If core.match was able to easily pattern match over a record as well as easily destructure the values in the value hashmap, we would use it. From what I have seen of core.match, it is nowhere near as easy/clean as pattern matching a vector. >> As far as performance goes, this is normally the sort of thing that gets baked into an app at a pretty low level, that's why I suggest it should be as fast as possible. If you're going to be processing millions of these things during the life of an app, and transforming them from one format to another, a little tweaking here and there may save you some pain in the end. Pattern matching itself is too slow for it to be viable in any performance sensitive context. That said, I feel optimize first for readability/maintainability, if profiling shows a bottleneck, then and only then optimize that area for performance. -- 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/d/optout.