Reputation: 3519
Clojure varies on what happens when the requested element does not exist:
(get {:a 1} :b) ; nil, no b
(second [0]) ; nil, only one element.
; nil seems to be by far the most common but:
(nth [0] 1) ; ERROR: java.lang.IndexOutOfBoundsException.
(nth nil 1) ; but this works (returning nil)
Is there a general logic behind when to return nil and when to throw an error?
Upvotes: 1
Views: 116
Reputation: 1331
For me the logic is :
nth
: you assume that data exist AND you want to have its indexget
: it is more exploratory, you ask for data and if it does not exist it returns nothingIn both cases you can pass a value if the value is not found
(nth [1 2] 3 nil) = nil
EDIT
In a more pragmatic perspective, I would also add thse inputs.
In general, you will process in a Clojure program several "rows"/"records" and not single data. Imagine you have a list of items like
({:name "A" :type "bicycle" :range "premium"} {:name "B" :type "helmet"})
Here you have a list of items (for instance in a shop). Let's say you have defined ranges for your bicylces but not for helmets so that this property does not exist for records associated with helmets.
Then if you process all this data using map
(or reduce
, etc.) you might want to output a default value for :range, like "normal" or "none" in order to show it on a UI.
You can also use a cond
or filter
based on the result to split up data.
Etc.
The function nth
is used on vectors. First, using a collection of vectors to represent a record would be akward (a subcollection OK, but not the primary one). If I really want to use it instead of a hashmap
for normalized data structures, it would be for a constant lenght and with positions clearly defined (for instance [purchase_price selling_price].
So if I use nth
for big data, it would be for on a subcollection.
First I "query" a main collection
((first items) :name) = "A"
Then on a secondary table, I will track the position (for instance if I have a vector to represent items sorted by user score ; a vector is made for sorted data)
(nth ranks "A")
Here I know that the article exist and if is not on the rank table, it means that there is a problem in data, so that I want an error.
Vector -> homogeneous or sorted data Map/Record -> non sorted properties that might exist
Upvotes: 3
Reputation: 13185
get
does a lookup by a key in the collection. It works for maps and vectors (where index is a key). Lookup returns nil
if the key is not found.
second
works on seq
s and is actually implemented on top of next
and first
. They return nil
when no value is available (with an addition of rest
which returns empty seq
when no value is available).
nth
works with sequences and assumes that the requested index can be found in the collection.
As for the logic behind them I think it gives you a choice and decide if an index is out of bounds is an error or is a valid state. By choosing between get
and nth
you might decide to fail fast or use nil
as a default value.
Upvotes: 3