Array#[]=

D

Daniel Schierbeck

I'm writing a class representing a coordinate system, and I want to be
able to give a point in the system a value (eg. a label). The problem is
that the system can have a variable number of dimensions. If it just had
three, I could write:

def []= (x, y, z, value); end

But this being an N-dimensional coordinate system, I have to come up
with something else. The most logical solution to me is this:

def[]= (*coordinates, value); end

But this gives a syntax error. Am I way off base, or would it be useful
if variable length argument lists could be written this way?


Daniel
 
J

James Edward Gray II

I'm writing a class representing a coordinate system, and I want to
be able to give a point in the system a value (eg. a label). The
problem is that the system can have a variable number of
dimensions. If it just had three, I could write:

def []= (x, y, z, value); end

But this being an N-dimensional coordinate system, I have to come
up with something else. The most logical solution to me is this:

def[]= (*coordinates, value); end

But this gives a syntax error. Am I way off base, or would it be
useful if variable length argument lists could be written this way?

If the slurpy arrays could be used anywhere in the list, if becomes
impossible to parse the arguments correctly.

In this case, you'll need to separate the value yourself:

def []=( *args )
value = args.pop
cooridinates = args
# ...
end

Hope that helps.

James Edward Gray II
 
A

Ara.T.Howard

I'm writing a class representing a coordinate system, and I want to be able
to give a point in the system a value (eg. a label). The problem is that the
system can have a variable number of dimensions. If it just had three, I
could write:

def []= (x, y, z, value); end

But this being an N-dimensional coordinate system, I have to come up with
something else. The most logical solution to me is this:

def[]= (*coordinates, value); end

But this gives a syntax error. Am I way off base, or would it be useful if
variable length argument lists could be written this way?

def []=(*a)
value = a.pop
coordinates = a
raise ArgumentError if value.nil? or coordinate.empty?
...
end

hth.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
 
D

Devin Mullins

Daniel said:
dimensions. If it just had three, I could write:

def []= (x, y, z, value); end

But this being an N-dimensional coordinate system, I have to come up
with something else. The most logical solution to me is this:

def[]= (*coordinates, value); end

But this gives a syntax error. Am I way off base, or would it be
useful if variable length argument lists could be written this way?

Yes, that would be useful. It has been discussed many-a-time, before,
too. :) For now, you'll have to implement your own solution in-method:
def []= *args
cords, value = args[0..-2],args[-1]
#...
end

Personally, I'd also like to see this:

def []= x, y, value
#...
ordef x, y, z, value
#...
ordef *args #gets here only if neither of the first two match
#...
end

But none of this exists. So live with it. :)

(I'd say, "Go write an RCR," but I can't imagine that 3 don't exist
already.)

Devin
 
D

Daniel Schierbeck

James said:
I'm writing a class representing a coordinate system, and I want to
be able to give a point in the system a value (eg. a label). The
problem is that the system can have a variable number of dimensions.
If it just had three, I could write:

def []= (x, y, z, value); end

But this being an N-dimensional coordinate system, I have to come up
with something else. The most logical solution to me is this:

def[]= (*coordinates, value); end

But this gives a syntax error. Am I way off base, or would it be
useful if variable length argument lists could be written this way?


If the slurpy arrays could be used anywhere in the list, if becomes
impossible to parse the arguments correctly.

In this case, you'll need to separate the value yourself:

def []=( *args )
value = args.pop
cooridinates = args
# ...
end

Hope that helps.

James Edward Gray II

Thanks! That looks a lot better.


Daniel
 
T

Trans

Devin said:
Daniel said:
dimensions. If it just had three, I could write:

def []= (x, y, z, value); end

But this being an N-dimensional coordinate system, I have to come up
with something else. The most logical solution to me is this:

def[]= (*coordinates, value); end

But this gives a syntax error. Am I way off base, or would it be
useful if variable length argument lists could be written this way?

Yes, that would be useful. It has been discussed many-a-time, before,
too. :) For now, you'll have to implement your own solution in-method:
def []= *args
cords, value = args[0..-2],args[-1]
#...
end

Personally, I'd also like to see this:

def []= x, y, value
#...
ordef x, y, z, value
#...
ordef *args #gets here only if neither of the first two match
#...
end

But none of this exists. So live with it. :)

(I'd say, "Go write an RCR," but I can't imagine that 3 don't exist
already.)

I think that you have the right sentiment, but the implemenation isn't
so good. It would make methods more compicated things to deal with. To
achieve signiture bases defintoins I think its best to stick with
multiple definitions:

def []= x, y, value
#...
end

def []= x, y, z, value
#...
end

def []= *args #gets here only if neither of the first two match
#...
end

I have often though they would be nice too. But how would you
distingush one from the other, by arity? Eg. #method:)[]=, 3) ?

T.
 
D

Devin Mullins

Trans said:
I think that you have the right sentiment, but the implemenation isn't
so good. It would make methods more compicated things to deal with. To
achieve signiture bases defintoins I think its best to stick with
multiple definitions:
There are a couple of problems with the typical definition of multiple defs:
1. Matz has said that he won't implement them. :)
2. What method are you refering to when you call method, remove_method,
etc.? In Ruby, the method signature is its name -- changing that would
be a bigger deal.
3. It doesn't play well with inheritance. Suddenly you've got to think
really hard when overriding a method (making sure to remove all
implementations with different arity, or whatever).
4. It doesn't play well with optional args and splats. My way
establishes an obvious order of resolution -- if the first one doesn't
match, go onto the next one. The typical way doesn't, and is one of the
confusing things about method overloading in C++ (by type in that case,
but same diff).

My way might squish ordef definitions together a little more (though
you're free to use blank lines), but it maintains the idea of a method
as an atomic unit -- the ordef thing is just an assistant to make
dealing with different arities nice. It would make method definitions as
complicated as you make them. If you really have one method doing three
different things based on arity, then your central ordef thing should be
nothing but a dispatcher to other methods.

The one problem I see with it -- not reproducible by blocks and
define_method. But, in that case, just do it the old fashioned way, as
has already been covered on this thread.

The other is that, if it were adopted, the next thing asked for would be
ordef's based on ===:

def foo String => bar
ordef foo Regexp => bar
end

def foo "add" => action, *args
ordef foo "delete" => action, *args
end

And that would condone some pretty obvious smells. :)

Devin
 
E

Eric Mahurin

--- Daniel Schierbeck said:
I'm writing a class representing a coordinate system, and I
want to be=20
able to give a point in the system a value (eg. a label). The
problem is=20
that the system can have a variable number of dimensions. If
it just had=20
three, I could write:
=20
def []=3D (x, y, z, value); end
=20
But this being an N-dimensional coordinate system, I have to
come up=20
with something else. The most logical solution to me is this:
=20
def[]=3D (*coordinates, value); end
=20
But this gives a syntax error. Am I way off base, or would it
be useful=20
if variable length argument lists could be written this way?

Coincidentally, I was just writing an RCR for this one. It is
#315. I'm also writing the corollary to this one which is to
be able to call a method with more arguments after the splat
(also applies to multi-assigns).


__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around=20
http://mail.yahoo.com=20
 
T

Trans

Devin said:
There are a couple of problems with the typical definition of multiple defs:
1. Matz has said that he won't implement them. :)
2. What method are you refering to when you call method, remove_method,
etc.? In Ruby, the method signature is its name -- changing that would
be a bigger deal.
3. It doesn't play well with inheritance. Suddenly you've got to think
really hard when overriding a method (making sure to remove all
implementations with different arity, or whatever).
4. It doesn't play well with optional args and splats. My way
establishes an obvious order of resolution -- if the first one doesn't
match, go onto the next one. The typical way doesn't, and is one of the
confusing things about method overloading in C++ (by type in that case,
but same diff).

My way might squish ordef definitions together a little more (though
you're free to use blank lines), but it maintains the idea of a method
as an atomic unit -- the ordef thing is just an assistant to make
dealing with different arities nice. It would make method definitions as
complicated as you make them. If you really have one method doing three
different things based on arity, then your central ordef thing should be
nothing but a dispatcher to other methods.

The one problem I see with it -- not reproducible by blocks and
define_method. But, in that case, just do it the old fashioned way, as
has already been covered on this thread.

You make some good points. But it occurs to me that having seperated
defs could in effect work in the same way as what you propose, with the
excpetion of controlling the order --but that I think should be airty
dictated anyway. How does the following, for instance, make any sense:

def x(*a)
...
ordef x(a)
...
end

If it works like a case statement, the the last will never be reached.
Also if this is just a helper, you probaby could do it now with a case
statement, let me see...

def x(*args)
case args.size
when 0
...
when 1
a = *args
...
when 2
a,b = *args
...
else
...
end
end

Pretty simpe, if not quite as concise. Also I reacall a "real" solution
to this somewhere --writen by an old school Japanese Ruby Hacker. But I
can't seem to track it down. Anyone recall?
The other is that, if it were adopted, the next thing asked for would be
ordef's based on ===:

def foo String => bar
ordef foo Regexp => bar
end

def foo "add" => action, *args
ordef foo "delete" => action, *args
end

And that would condone some pretty obvious smells. :)

You betchya :)

T.
 
D

Devin Mullins

Trans said:
If it works like a case statement, the the last will never be reached.
Yep. Shame on whomever wrote that code! :p
Also if this is just a helper, you probaby could do it now with a case
statement, let me see...

<snip/>

Pretty simpe, if not quite as concise.
Yeah, I guess what I'm seeking is a concise way to write that. Maybe
it's not deserving of its own construct, though. Can you think of a more
general solution that gets half-way there? Maybe a pattern-matching
thing akin to the way OCaml does case statements...

def x(*args)
case args
when [] then ...
when [a] then ...
when [a,b] then ...
else ...
end
end

That is totally un-Ruby, of course, so, I dunno.
Also I reacall a "real" solution
to this somewhere --writen by an old school Japanese Ruby Hacker. But I
can't seem to track it down. Anyone recall?
'd be interested to hear.

Thanks,
Devin
 
T

Trans

hmmm....

# holds some nift binding methods like []=
# for setting local vars, essentially
#
# eval %{ #{var}=#{val} }, binding
#
require 'nano/binding'

class Array
def to_p(bind)
P.new(bind,*self)
end
end

class P < Array
attr_reader :bind
def initialize(*args)
super()
@bind = args.shift if Binding === args.first
self.replace(args)
end
def ===(args)
if size == args.size
each_with_index{ |k, i|
args.bind[k] = args
}
return true
else
return false
end
end
end

def prms(bind,*args)
Params.new(bind,*args)
end

def x(*args)
a,b = nil,nil
case args.to_p(binding)
when P[] then p []
when P[:a] then p [a]
when P[:a,:b] then p [a,b]
else
puts "don't know"
end
end

x
x(1)
x(1,2)
x(1,2,3)
 

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,183
Messages
2,570,966
Members
47,513
Latest member
JeremyLabo

Latest Threads

Top