Programmatically creating a local variable using a symol

T

tho_mica_l

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.
 
A

Austin Ziegler

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
 
T

tho_mica_l

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.
 
A

ara.t.howard

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://codeforpeople.com/
 
T

tho_mica_l

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

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.
 
T

Todd Benson

(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
 
T

tho_mica_l

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.
 
C

Charles Oliver Nutter

tho_mica_l said:
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
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,019
Latest member
RoxannaSta

Latest Threads

Top