The most common way to do this in Clojure is to define your function such
that if the input is not in the domain, the function returns nil.

Since nil and false are the only "falsey" values in Clojure, you can use
ordinary tests to determine if the function returned a result.  The idiom
that lets you apply a function and guarantee that there is a result is:

(when-let [result (pf x)]
  ...)

which is shorthand for:

(let [result (pf x)]
   (when result
       ...))

If the when test fails, then the expression returns nil, which means that
you naturally get another partial function restricted to the appropriate
domain.

There is a threading form, some->, which provides for certain kinds of
partial function composition (a chain of calls, but as soon as you hit a
nil result, the whole thing becomes nil).  I can't think of anything
exactly like orElse, but it's easy enough to write, since or returns the
first non-falsey value:
(defn orElse [pf1 pf2] (fn [x] (or (pf1 x) (pf2 x))))

Extending this to a variable number of arguments is left as an exercise.

As you can see, Clojure's punning of nil as both "no result" and a false
value, along with the way that all other values are treated as true and the
when idiom, allows for some compact code.

However, it's not all roses.  If you want your function to be able to
return nil as an actual meaningful result, this strategy won't work.  If
your function sometimes returns false, then the when idiom fails.  It works
well enough in local contexts where you really understand the kind of data
you're working with and know that nil and false won't be an issue, but if
you're building a larger library, this approach is fragile.  I've found
that this lack of precision surrounding nil and false is one of the biggest
source of bugs.  You'll have code that works on all tests and "reasonable"
input, but when someone uses your code on something that has nil or false
in a collection and boom, things get squirrely.  Since you're coming from
Scala which carefully protects you from this kind of confusion, you'll
probably find this to be a real annoyance.  Nevertheless, most Clojurians
just create partial functions in this way where a nil result means the
function is undefined for that input, and muddle through okay.

If partial functions play a central role in your library, then to be truly
robust, you'll have to work harder than the typical, sloppy approach.  Use
maps as a role model, since maps are essentially partial functions.  (get
{:a 1, :b 2} :c) returns nil.  But for special purposes, people can do (get
{:a 1, :b 2} :c ::undefined), choosing a distinctive value to represent
undefined.

Try modeling your partial functions as functions that typically return nil
if undefined, but an optional return value can be provided for undefined
inputs.

In general, the Clojure philosophy is that no guarantees are made if you
pass an invalid input to a function: you might get garbage out, you might
get nil, or you might get an error.  It's not really consistent and
different functions and libraries work in different ways.  The
nil-returning ones are the most easily composable, though, which is why
that tends to be the most common way.

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


Reply via email to