In this case, we could say, explaining it in object oriented fashion, that we are extending the existing map, vector and string classes in Clojure to support the digest function. A more functional explanation, and thus suitable for this context, would be that we are defining a function, which will execute implementation according to the type of the parameter.
Either way, we call digest with these types, and get the correct hash. In this example, probably needless to say, for demonstrative purposes, we don't return a hash but a text that helps us to see which method was called.

Note that in this example I'm using "digestible" instead of "this" to name the parameter (contrary to the first example I posted about protocols). There's no reason for this, besides I consider "this" maybe to be too engrained into object oriented world and misleading in this context. I may change the other post to use "data-provider" instead of "this". The source of the GitHub project I mentioned uses "message". I consider "digestible" better, since if we pass anything here that's not "digestible", we will get an error. It seems there is no (well known) convention about the naming of this parameter yet, since all the examples I have found use something different.

On a different note, this functionality can also be achieved using multimethods. This is the multimethod version of our example:

Sonntag, 18. Mai 2014

Today I found myself practicing a bit the concept of partials in Clojure, and ended writing a tutorial -like script. Here it is, maybe it helps someone else to learn how to use them.

;assume we have a function that does something with a list of numbers
;in this case, it adds a value to each number:
(defn add-value [value numbers]
(map (fn [number] (+ number value)) numbers))
;test
(add-value 2 [1 2 3]) ;(3 4 5)
;now we put this logic in a function "foo":
(defn foo []
(add-value 2 [1 2 3])
;test
(foo) ;(3 4 5)
;now imagine that besides of add-value we have a mult-value function:
(defn mult-value [value numbers]
(map (fn [number] (* number value)) numbers))
;or any other function that accept a value and numbers vector as
;parameters, and does something with them!
;we want to customise the
;behaviour - so we pass the behaviour as parameter:
(defn foo [some-function]
(some-function 2 [1 2 3]))
;now we can call foo with add-value:
(foo add-value) ;(3 4 5)
;or mult-value:
(foo mult-value) ;(2 4 6)
;now imagine a situation where foo passes the vector
;but not the value. Instead, we want to pass the value
;together with some-function
;we could do:
(defn foo [some-function value]
(some-function value [1 2 3]))
;test
(foo add-value 2) ;(3 4 5)
;this works but it's ugly, and in more complex use cases can quickly
;become a mess - we are altering the signature of foo with
;values which belong rather to some-function.
;so how can we pass the value to some-function instead of passing it
;to foo, despite we don't have all the parameters to call
;some-function yet?
;this is were a partial comes to help
;with a partial we can pass only a part of the parameters to a function,
;letting it "on hold" until the rest is passed.
;we revert to our old signature of foo:
(defn foo [some-function]
;note: value is "captured" (see call below) in some-function so we don't pass it here anymore
(some-function [1 2 3]))
;and we call foo using a partial, which captures the value:
(foo (partial add-value 2)) ;(3 4 5)
(foo (partial mult-value 2)) ;(2 4 6)
;an alternative would be to use partial in the definition of the function
;this would make sense if we are certain that the function is going to be always used as partial:
(defn add-value [value]
(partial map (fn [number] (+ number value))))
;and call it like this:
(foo (add-value 2)) ;(3 4 5)
;note that, with this implementation, (forgetting about foo for a moment) we can't do this anymore:
(add-value 2 [1 2 3]) ;error
;we would have to use this syntax in order to call add-value will all parameters:
((add-value 2) [1 2 3]) ;(3 4 5)
;if we want to be more flexible, meaning we have the options to use the function
;both as partial or passing all the parameters, we can use multiple arities
;(like before, it depends on the use case if this makes sense):
(defn add-value
([value] (partial add-value value))
([value numbers]
(map (fn [number] (+ number value)) numbers)))
;we also use it like this:
(foo (add-value 2)) ;(3 4 5)
;without foo, we can do this, like before:
((add-value 2) [1 2 3]) ;(3 4 5)
;but now we also can do:
(add-value 2 [1 2 3]) ;(3 4 5)

Note: I'm new to Clojure, glad to receive corrections or suggestions in the case something can be improved.
These snippets can be found (together with others) here.