[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Programmatically creating a local variable using a symol

ThoML

1/6/2008 1:49:00 PM

Hi,

Where are variables actually stored? Or rather: how do I create a new
variable without using eval?

I'd like to write something like this.

bind :a, 1
p a
=> 1

How could I accompish this? How could a definition of "bind" look
like?

Local variables are registered in Binding and local_variables, but
how
do I get them there? = is no method, but it's no keyword either?

Regards,
Thomas.

7 Answers

Austin Ziegler

1/6/2008 2:51:00 PM

0

On Jan 6, 2008 8:49 AM, tho_mica_l <micathom@gmail.com> wrote:
> Where are variables actually stored? Or rather: how do I create a new
> variable without using eval?

Why do you want to do this with a local variable?

Consider using a hash and make your own "binding" table for the
purposes of which you're speaking.

-austin
--
Austin Ziegler * halostatue@gmail.com * http://www.halo...
* austin@halostatue.ca * http://www.halo...feed/
* austin@zieglers.ca

ThoML

1/6/2008 4:35:00 PM

0

> Why do you want to do this with a local variable?

First, I'd like to know a little bit more about ruby. And I would
have
found such a thing useful once or twice in the past.

Secondly (the background for my question), I'd like to implement some
ocaml'ish match command (for the moment, as some kind of exercise
only).
I'm not sure yet how this could best be done but I thought it would
be
nice if it could look somewhat like this:

val = Foo(1, 2)

case val
when Foo(:x, :y)
a = x * y
when Bar(:x)
a = x
end

But this form would require the variables to be set from Foo#=== which
I
don't think is possible anyway.

What I managed to do is this:

class Matchtype
class << self
def match(other, &block)
if other.class == self
block.call(*other.value)
true
else
false
end
end
end

attr_reader :value

def initialize(*value)
@value = value
end

end

Sample use:

class Foo < Matchtype
end

class Bar < Matchtype
end

x = Foo.new(1, 2)
y = Bar.new(1)

if Foo.match(x) {|a, b| p "Foo", a + b}
elsif Bar.match(x) {|a| p "Bar", a}
end

if Foo.match(y) {|a, b| p "Foo", a + b}
elsif Bar.match(y) {|a| p "Bar", a}
end

But this is quite useless the way it is because the value of the
block
cannot be used and because it's ugly and ...

One could of course do it this way which would come close:

class Boo < Array
end

class Baa < Array
end

z = Boo[1, 2]
case z
when Baa
p "Nope"
when Boo
a, b = z
p "Boo", a + b
end

It would be nice being able to eliminate the "a, b = z" line though.

Ideally, one would also be able to do something like this:

z = Boo[1, :a]
case z
when Boo(0, '')
p "Nope"
when Boo(1, :a)
p "Boo", a
end

Any ideas are welcome.

Regards,
Thomas.

ara.t.howard

1/6/2008 5:21:00 PM

0


On Jan 6, 2008, at 9:34 AM, tho_mica_l wrote:

> nice if it could look somewhat like this:
>
> val = Foo(1, 2)
>
> case val
> when Foo(:x, :y)
> a = x * y
> when Bar(:x)
> a = x
> end


invert the var binding: make them instance variables and it falls out
easily:

class Foo
attr :x, :y
def initialize x, y
@x, @y = x, y
end
end
def Foo(*a, &b) Foo.new(*a, &b) end

class Bar < Foo; end
def Bar(*a, &b) Bar.new(*a, &b) end



val = Foo 1, 2

a =
case val
when Foo
val.x * val.y
when Bar
val.x
end



a @ http://codeforp...
--
share your knowledge. it's a way to achieve immortality.
h.h. the 14th dalai lama



ThoML

1/7/2008 6:42:00 AM

0

> invert the var binding: make them instance variables and it falls out
> easily:

Okay, this idea with the variable binding is pointless in this
context.
(I still would like to know if it's possible to create a local
variable
though.)

I now defined a subclass of Array with a more clever === method,
which
knows how to match wildcards. This version comes pretty close to what
I
intended.

class Foo < MatchStruct
fields :a, :b, :c, :d, :e
end

class Bar < MatchStruct
fields :a, :b
end

x = Foo[1, 2, 3, 4, 5]
a = MatchStruct(x) do
match Foo[1, :_, 3, :_, 5] do
["Foo", *x]
end
match Bar[:_, "b"] do
["Bar", x.a + x.b]
end
end
p a

Regards,
Thomas.

Todd Benson

1/7/2008 7:12:00 AM

0

On Jan 7, 2008 12:45 AM, tho_mica_l <micathom@gmail.com> wrote:
> (I still would like to know if it's possible to create a local
> variable
> though.)

You might have to use #instance_eval.

irb> a = "hello"
=> "hello"
irb> instance_eval( "#{a} = 3" )
=> 3
irb> a
=> "hello"
irb> hello
=> 3

Not much help, but sort of answers the question.

Todd

ThoML

1/7/2008 8:01:00 AM

0

> You might have to use #instance_eval.

This is about what I try to avoid. Some interpreters make variables
available via some pseudomagic dictionary/hash. Based on ruby's nature
and my previous experiences I'd assumed ruby would provide such a
solution too but couldn't find it out myself.

Charles Oliver Nutter

1/7/2008 8:17:00 AM

0

tho_mica_l wrote:
>> You might have to use #instance_eval.
>
> This is about what I try to avoid. Some interpreters make variables
> available via some pseudomagic dictionary/hash. Based on ruby's nature
> and my previous experiences I'd assumed ruby would provide such a
> solution too but couldn't find it out myself.
>

There is no way in either Ruby 1.8 or Ruby 1.9. The names of variables
and "variable calls" are determined at parse time, both for normal
scopes and for eval. eval can add new variables, but only to the eval
scope, and only in 1.8 (I believe 1.9 provides a separate eval scope for
each eval).

Your only change of dynamically defining things that look like variables
is the attr binding a few people have described.

- Charlie