(but-last) ?

Started by Excalibor, March 24, 2009, 07:54:31 AM

Previous topic - Next topic

Excalibor

Hi there,



This is a problem that has arisen several times now in my programs (which do some heavy text file parsing)



I get a text line, (parse) it and then I need a list of tokens but the last one.



A silly example: getting the base URI from a given URI:



 "http://example.com/path/to/files/file1.html">http://example.com/path/to/files/file1.html"



There's surely a hundred ways to do this, but I simply (parse) it given all possible token separators and I get the list



("http" "example.com" "path" "to" "files" "file1.html")



I needed a simple (but-last) function to get all elements but the last one to use is some loops:



I came with different solutions, these are my favourites:


(define (but-last lst)
  (rest (rotate lst)))

(define (but-last2 lst)
  (1 (- (length lst) 1) lst))

(define (but-last3 lst)
  (chop lst))


You see, the first one is "less optimal" than the second, but it only mentions lst once and, alas, is more useful to on-the-fly generated lists . OTOH performance is not that horrible, so it's a nice hack (instead of slicing, twisting, kind of) :-)



Then, reading more into the documentation, I arrived to chop. Doh!



So...



We have an asymmetry in here:


'(this is a list)

 first    rest

 chop     last


So, maybe an alias chop = but-last, except-last, almost-all, firsts could be useful?



I mean, we have the "first" and the "rest" of a list, we could have the "firsts" and the "last"? The truth is (chop) is not an intuitive name for this task, even when it's covered by it.



In my view, the fact that newLISP treats strings and lists the same for many different kind of things is not a favor in this case. I'm thinking in the new user, because I'm a kind-of new user, and, well, you know... :-P



Anyway, your thoughts?



laters

xytroxon

#1
Time for newLISP's implicit indexing to come to the rescue!!! ;)


QuoteImplicit indexing for rest and slice



 Implicit forms of rest and slice can be created by prepending a list

 with one or two numbers for offset and length. If the length is

 negative it counts from the end of the list or string:


If implict indexing looks messy to your coding style, create a function:



(define (drop-last var)(0 -1 var))

Then...

(drop-last '("http" "example.com" "path" "to" "files" "file1.html"))
-> ("http" "example.com" "path" "to" "files")


-- xytroxon
\"Many computers can print only capital letters, so we shall not use lowercase letters.\"

-- Let\'s Talk Lisp (c) 1976

cormullion

#2
I'm not sure I'd consider such an easy to do task worthy of a new function all of its own ... most is quite fun, but a bit vague for some, perhaps.



but-first and but-last would be symmetrical alternatives.


QuoteThe truth is (chop) is not an intuitive name for this task, even when it's covered by it.


Well it's quite a good name for the task. in many ways, just not symmetrical like first/rest/last.

Excalibor

#3
Quote from: "cormullion"I'm not sure I'd consider such an easy to do task worthy of a new function all of its own ... most is quite fun, but a bit vague for some, perhaps.



but-first and but-last would be symmetrical alternatives.


QuoteThe truth is (chop) is not an intuitive name for this task, even when it's covered by it.


Well it's quite a good name for the task. in many ways, just not symmetrical like first/rest/last.


Yes, please don't misunderstand me, chop is great name, and applied to strings is actually a kind of standard (at least from a Perl/PHP POV), and extending it to lists is actually just as natural...



I was just thinking that if I can make that error, someone else could do it (please don't tell me I'm the only moron around! ;-) and following the Principle of Least Surprise, I'd prefer "nicer" names, even if I will surely use implicit splitting (i don't really use first, etc on quick scripts, but I tend to use them in more permanent things, as they express the code intention in a clearer, if you'll allow me, way.



but-first and but-last would really be great as names, they are clear and predictable, once you see the others around.



Another possibility, in a different plane, would be to allow for an extra index to first, such as (first lst n) would take the first n elements... (first lst -1) would "naturally" take all the first ones but the last one... :-P



Thanks for your comments, anyway, as I can easily gather these aliases in a common library for use and abuse :-P

Excalibor

#4
Quote from: "xytroxon"Time for newLISP's implicit indexing to come to the rescue!!! ;)



...



(drop-last '("http" "example.com" "path" "to" "files" "file1.html"))
-> ("http" "example.com" "path" "to" "files")


Yeah, it's actually something that doesn't easily arise just by browsing the functions index when reading the documentation... That's why I was proposing an alias, so it's easier to find just by looking... Implicit is cool, but for newbies, explicit is better :-)



thanks anyway!

Lutz

#5
for all implicit forms there is also a named function, look into 'slice':

http://www.newlisp.org/newlisp_manual.html#slice">http://www.newlisp.org/newlisp_manual.html#slice