Array#rest

G

Georgy

| first / rest is symmetric...
| head / tail unix commands don't default to 1 "line"
| car + cdr have crappy names.
| i'm sure there is something better for this :)

Could be take / drop (with optional argument, number of items):

[1,2,3,4].take --> 1
[1,2,3,4].take(1) --> 1 # or can be [1]
[1,2,3,4].take(2) --> [1,2]
[1,2,3,4].drop --> [2,3,4]
[1,2,3,4].drop(2) --> [3,4]
[1,2,3,4].take(-3) --> [2,3,4]
[1,2,3,4].drop(-1) --> [1,2,3]

And in some language there was a pair 'first / butfirst'.
 
C

Charles Comstock

Hi,

I don't want a destructive function. A number of times I have used
the shift
and the remainder, but there are a number of times you want a non
destructive
copy of the rest of the list. Hence rest ;p

If you don't want to destroy the original list you can use the splat
operator
in an assignment:

a = [ 1, 2, 3, 4 ]
# => [1, 2, 3, 4]
first, *rest = a
# => [1, 2, 3, 4]
first
# => 1
rest
# => [2, 3, 4]

Yea I know I can do it like that, but sometimes I don't want the extra variable
running around. The most recent case I wanted a rest function was a situation
where I had an array in which the first arg was used to select the command
object and then the rest of the array was used as the parameter list to the
command's instanciation. I wanted to keep the original input as a single
array so that I could print it out for debug output later if I needed to,
keeping the command name so it was clearer. Obviously I could seperate it into
command name and params and keep around the original input, but I really only
need each of the parts once, so it seemed logical to just grab out the parts I
needed when I passed them as parameters. It's not an issue of not knowing how
to split them, or even that the method isn't already available through
slice(1..-1), I just thought that array rest would be more readable in this
case. It's not something really frequent but I find myself using stuff like
this here and there, and it just seemed like a useful function to have. It
just seemed to make sense what with ruby already having a first function.

On a side note, I had to double check your above example. I knew you could
split like that, but I didn't realize that it performed a copy and was not
referencing the original parts of a. I suppose it is more useful that way, and
am glad it is, but my gut reaction to the symantics of that was that it
performed like ='s generally does, acting as an alias instead. You learn
something every day I guess.

Charles Comstock
 
J

Jean-Hugues ROBERT

Hi,

I don't want a destructive function. A number of times I have used the shift
and the remainder, but there are a number of times you want a non destructive
copy of the rest of the list. Hence rest ;p

If you don't want to destroy the original list you can use the splat operator
in an assignment:

a = [ 1, 2, 3, 4 ]
# => [1, 2, 3, 4]
first, *rest = a
# => [1, 2, 3, 4]
first
# => 1
rest
# => [2, 3, 4]

Florian Frank

Nice! And probably efficient too.
That is an often overlooked feature of ruby.
It somehow reminds me of Prolog:
([First|Tail], A).
Free/Bound variables is a missing concept in
Ruby today (not talking about backtracking).
I am working on that (the former, matching).

Yours,

JeanHuguesRobert
 
J

Jean-Hugues ROBERT

| first / rest is symmetric...
| head / tail unix commands don't default to 1 "line"
| car + cdr have crappy names.
| i'm sure there is something better for this :)

Could be take / drop (with optional argument, number of items):

[1,2,3,4].take --> 1
[1,2,3,4].take(1) --> 1 # or can be [1]
[1,2,3,4].take(2) --> [1,2]
[1,2,3,4].drop --> [2,3,4]
[1,2,3,4].drop(2) --> [3,4]
[1,2,3,4].take(-3) --> [2,3,4]
[1,2,3,4].drop(-1) --> [1,2,3]

And in some language there was a pair 'first / butfirst'.
Georgy Pruss

That is what I ended up in some language I designed. I
was not perfectly happy with the result, but that was
the best I found. Was more like but_first() however
(well... it actually was butFirst(), Smalltalk camelCase).
It worked on strings, lists and arrays and was the main
style for iterating:
while item = a_list.first()
a_list = a_list.but_first()
xxx
end
I for sure prefer Ruby's
for item in a_list do
xxx
end
or even more Rubyish (or Smalltalkish) I guess:
a_list.each do |item|
xxx
end
It was efficient because I had implemented copy-on-write
optimization and but_first() was just a pointer increment.

Yours,

JeanHuguesRobert
 
P

Patrick Gundlach

Hello Robert,

Robert Klemme said:
Huh? What am I missing here? It seems (caar x) is short for (car (car
x))...

sorry, two stupid typos in one row. :-( I can't put it on the late
hour, it was afternoon when I wrote my reply.

You're right. it should be (car (car ...)) = (caar ..) and not
'mylist but unquoted mylist.

Patrick
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,146
Messages
2,570,832
Members
47,374
Latest member
EmeliaBryc

Latest Threads

Top