On 30 April 2014 10:41, Roelof Wobben <rwob...@hotmail.com> wrote: > > Op woensdag 30 april 2014 09:58:26 UTC+2 schreef James Reeves: > >> >> Unlike vectors, seqs are simple structures and don't know their own >> length. >> >> You can count seqs, but this involves iterating through every element in >> turn. If all you want to do is find out whether there is more than one >> element, there's a much simpler and more efficient way. >> >> > Yep, if there is only 1 item is a list (rest coll) is nil. >
Almost. Clojure distinguishes between nil and the empty list. The function you want is "next": (rest [1]) => () (next [1]) => nil Why the distinction between next and rest? It has to do with laziness, and if you're interested I can go into more detail. Otherwise just remember that rest returns an empty list, and next returns nil. > Can you think of a way of making this function recursive to work with any >> number of elements? >> > > I think I can but I have to try some things but untested it looks > like this > > (defn last* [coll] > (if (nil? (rest coll) > (first coll))) > >> (last* (rest coll)) >> > That's pretty much right. You just need to use (nil? (next coll)) or (empty? (rest coll)) (defn last* [coll] (if (nil? (next coll)) (first coll) (last* (next coll)))) You can also write it with loop/recur: (defn last* [coll] (loop [coll coll] (if (nil? (next coll)) (first coll) (recur (next coll)))) See how the recursive step is replaced with "recur"? This is more efficient because we're not filling the stack up as we would with recursion. You can also write the above as: (defn last* [coll] (if (nil? (next coll)) (first coll) (recur (next coll)))) If a recur is used without an outer loop, the whole function acts as an implicit loop. There's one more optimisation you can perform, and that's to take advantage of nil being a "falsey" value. (defn last* [coll] (if (next coll) (recur (next coll)) (first coll))) If (next coll) isn't nil, it recurs. If it is, then the if statement fails and the first item of the collection is returned. The above code is actually how it's defined in clojure.core. Now I wonder how I can make it work if I want to find lets say the 5th > value of a array of any number of elements > Then rest is never nil. So at first glance if I do not know the length it > cannnot be done recursive. > I have to do it in a for loop. > You need a counter. Take a look at the version of last* that has a loop/recur: (defn last* [coll] (loop [coll coll] (if (nil? (next coll)) (first coll) (recur (next coll)))) Consider how you might add a counter to the loop. You'll want to increment the counter, then stop when it reaches the desired number. - James -- 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.