On Thu, Jul 2, 2009 at 1:59 PM, Raoul Duke<rao...@gmail.com> wrote: > >> clojure functions should return a value. This is good advice, but I >> have code that sometimes return nil. Is it better to return 'nil' or >> an object with no data. I guess a simple example, if you have a > > imho, null/nil/etc. are more often than not pretty evil. > > random related links: > http://lukeplant.me.uk/blog.php?id=1107301659 > http://weblogs.asp.net/fmarguerie/archive/2009/02/12/null-object-design-pattern.aspx
That may be somewhat less relevant: (map int "foo") ==> (102 111 111) (map int "") ==> () (map int nil) ==> () In general, almost anything that can handle an empty collection will behave the same when given nil. So when designing your API you may want to consider: 1. Do you need to differentiate between an empty collection an nil? For example, perhaps an empty string means the user left a field blank, but nil means they've not yet been given the opportunity to fill it out. Or some other more useful example. :-P 2. Will your user want to conj onto the thing you return? In some cases it's convenient to take, say, a vector returned by some function and just 'conj' onto it. Returning nil would cause such user code to build an list instead of a vector, and this may not be what you want. 3. Do you want to make plain truth tests useless? On the other hand, returning an empty collection forces the user to use 'empty?' like this: (when-not (empty? (my-things x)) (do something with my-things)) ...obscuring the main point of the test in layers of 'not' and 'empty?'. While returning nil allows nil-punning like: (when (my-things x) (do something with my-things)) It gets worse if the user was hoping to use when-let... 4. Is laziness a factor? If a collection is empty 'rest' returns an empty seq, but 'next' returns nil. In fact, this is a defining difference between the two functions. The reason in this case is that in order to return nil for an empty collection, you first need to find out if the collection is empty which forces the realization of more of a lazy seq than you sometimes want, so 'rest' refuses and simply returns the un-realized rest of the seq. Conversely, you often don't care about that extra laziness and want the convenience of nil-punning in which case 'next' is perfect. So these are all things to keep in mind, and there are probably others as well. However in practice it often turns out that what's easiest to write in your API code is also what will be most convenient for your users. For example, for cases where point 2 resonates with you, it's also likely you're getting that empty vector by doing something like 'pop', which will itself return an empty vector rather than nil. Conversely, if 3 seem more important in your case, it's like you're could you 'when' in your API code, which returns nil (not an empty collection) in false cases. --Chouser --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---