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.

Reply via email to