patching strings together to make a variable

S

Sy Ali

I'm curious to know if I can patch multiple things together to make a variable.

I have some imaginary code snippets. The most direct way I can think
of is something like this:

$a = true
$var = "fail"
$variable = "pass"

puts "#{$var(if $a == true then "iable" end)}"

since $a == true, I would like this to become:
puts "#{$variable}"

But this doesn't work. I didn't expect it to, but is something like
this possible? Am I stuck with this? :

puts "#{if $a == true then $variable else $var end}"


What I'd really like to learn is how I can patch multiple strings
together and call it a variable. I think I'm just missing some simple
piece of this puzzle..

The imaginary code would be:

ab = "pass"
puts ("a" + "b").to_variable

Or to a global, an instance variable, etc.. envisioned like this:

puts $("a" + "b")
puts @("a" + "b")


If there's a simple way to do this, a code snippet or a pointer to a
manual reference would be all I need.
 
D

dblack

Hi --

I'm curious to know if I can patch multiple things together to make a
variable.

I have some imaginary code snippets. The most direct way I can think
of is something like this:

$a = true
$var = "fail"
$variable = "pass"

puts "#{$var(if $a == true then "iable" end)}"

since $a == true, I would like this to become:
puts "#{$variable}"

But this doesn't work. I didn't expect it to, but is something like
this possible? Am I stuck with this? :

puts "#{if $a == true then $variable else $var end}"


What I'd really like to learn is how I can patch multiple strings
together and call it a variable. I think I'm just missing some simple
piece of this puzzle..

The imaginary code would be:

ab = "pass"
puts ("a" + "b").to_variable

Or to a global, an instance variable, etc.. envisioned like this:

puts $("a" + "b")
puts @("a" + "b")


If there's a simple way to do this, a code snippet or a pointer to a
manual reference would be all I need.

http://www.perl.org :) Perl has these "soft" or "symbolic"
references, plus a whole chorus of people to tell you that you should
use hashes instead :)

Ruby gives you ways to examine available existing variables, and you
can pry into them:

@ab = "pass"
puts instance_variable_get("@#{"a" + "b"}")

and so on.


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
D

David Vallner

Sy said:
What I'd really like to learn is how I can patch multiple strings
together and call it a variable. I think I'm just missing some simple
piece of this puzzle..

The imaginary code would be:

ab = "pass"
puts ("a" + "b").to_variable

This sounds very, very PHP to me. And subjectively speaking, I think
variable variables from that language are the worst abomination in a
structured programming language since VB goto.

Does that really make code clearer instead of just "clever"?

David Vallner
 
S

Sy Ali

This sounds very, very PHP to me. And subjectively speaking, I think
variable variables from that language are the worst abomination in a
structured programming language since VB goto.

Does that really make code clearer instead of just "clever"?

I know nothing of PHP, but this trick would make my code much clearer.
With David.first's recommendation of instance_variable_get I can
re-use blocks of code much more intelligently.

Previously, I've been duplicating methods and just renaming a single
variable.. (just to ensure that method1 works the same as method2) a
variation of this would be cleaner I think.

My code is still quite hackish, so it's likely that I'll figure things
out in some time, and will be able to evolve towards even cleaner
code, perhaps dropping this trick.


Thanks for the help Davids.. =)
 
M

Mike Stok

I know nothing of PHP, but this trick would make my code much clearer.
With David.first's recommendation of instance_variable_get I can
re-use blocks of code much more intelligently.

Previously, I've been duplicating methods and just renaming a single
variable.. (just to ensure that method1 works the same as method2) a
variation of this would be cleaner I think.

My code is still quite hackish, so it's likely that I'll figure things
out in some time, and will be able to evolve towards even cleaner
code, perhaps dropping this trick.

What are you actually trying to do? Sometimes stepping back from a
particular obstacle can give a fresh point of view which sometimes
leads to "nicer" code.

Mention of duplicating methods and renaming a single variable hints
strongly there may be more ways to skin this cat.

Mike

--

Mike Stok <[email protected]>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.
 
D

dblack

Hi --

How about:

puts "#{eval('$' + 'var' + (if $a == true then "iable" end))}"
# => pass

If your if fails you end up adding nil to a string, which will give
you an error.

So.....

puts eval('$' + 'var' + ($a ? "iable" : ""))

or something.


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
S

Sy Ali

What are you actually trying to do? Sometimes stepping back from a
particular obstacle can give a fresh point of view which sometimes
leads to "nicer" code.

Mention of duplicating methods and renaming a single variable hints
strongly there may be more ways to skin this cat.

I was just looking for an alternative to the classic if/then/else.

My original method would do this:

def test1
puts "#{@something_something}"
end

def test2
puts "#{@something_something_else}"
end

or maybe I could have done this:

def test(string)
if string == "something" then
puts "#{@something_something}"
elsif string == "something_else" then
puts "#{@something_something_else}"
end
end

What if I wanted to expand this a thousand-fold? I'd have to do this:

def test(string)
case string
when "something" : puts "#{@something_something}"
when "something_else" : puts "#{@something_something_else}"
# ... repeated many more times
end
end

But that thousand-line case could be replaced with a one-liner:

def test(string)
puts "#{instance_variable_get("@#{string + "_something"}")}"
end


I got here because I was looking at my inelegant code and wanted to
know how it could be simplified when faced with greater use.

Thinking in infinites.. yes, it's optimising early, but I wanted to
learn something new.
 
A

Axis Sivitz

Sy said:
I was just looking for an alternative to the classic if/then/else.

My original method would do this:

def test1
puts "#{@something_something}"
end

def test2
puts "#{@something_something_else}"
end

or maybe I could have done this:

def test(string)
if string == "something" then
puts "#{@something_something}"
elsif string == "something_else" then
puts "#{@something_something_else}"
end
end

What if I wanted to expand this a thousand-fold? I'd have to do this:

def test(string)
case string
when "something" : puts "#{@something_something}"
when "something_else" : puts "#{@something_something_else}"
# ... repeated many more times
end
end

But that thousand-line case could be replaced with a one-liner:

def test(string)
puts "#{instance_variable_get("@#{string + "_something"}")}"
end


I got here because I was looking at my inelegant code and wanted to
know how it could be simplified when faced with greater use.

Thinking in infinites.. yes, it's optimising early, but I wanted to
learn something new.

Uh...if you have so many similarly named variables, it sounds like you
should be using an array or a map.

The map could be set up with the keys (a certain string) indexing to
the values of your old variables.

@some_map['var'] = "pass"

def test(string)
puts @some_map[string]
end

test('var') #=> "pass"
 
D

dblack

Hi --

Uh...if you have so many similarly named variables, it sounds like you
should be using an array or a map.

The map could be set up with the keys (a certain string) indexing to
the values of your old variables.

@some_map['var'] = "pass"

def test(string)
puts @some_map[string]
end

test('var') #=> "pass"

Which brings us back to:
http://www.perl.org :) Perl has these "soft" or "symbolic"
references, plus a whole chorus of people to tell you that you
should use hashes instead :)

:)


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
M

Mike Stok

Hi --

Uh...if you have so many similarly named variables, it sounds like
you
should be using an array or a map.

The map could be set up with the keys (a certain string) indexing to
the values of your old variables.

@some_map['var'] = "pass"

def test(string)
puts @some_map[string]
end

test('var') #=> "pass"

Which brings us back to:
http://www.perl.org :) Perl has these "soft" or "symbolic"
references, plus a whole chorus of people to tell you that you
should use hashes instead :)

:)

One of the reasons for the Perl chorus is that in Perl the "soft
references" can only point to non-lexical variables, and this can
cause much opportunity for enlightenment later!

#!/usr/bin/env perl

# use strict;
# use warnings;

$foo = 'foo1';
my $foo = 'foo2';

$soft_ref = 'foo';
$real_ref = \$foo;

print "soft says $$soft_ref\n";
print "real says $$real_ref\n";

__END__

produces:

soft says foo1
real says foo2

... which is one of the reasons the strict and warnings pragmata are
considered useful.

Mike

--

Mike Stok <[email protected]>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.
 
M

Mike Stok

I was just looking for an alternative to the classic if/then/else.

My original method would do this:

def test1
puts "#{@something_something}"
end

def test2
puts "#{@something_something_else}"
end

or maybe I could have done this:

def test(string)
if string == "something" then
puts "#{@something_something}"
elsif string == "something_else" then
puts "#{@something_something_else}"
end
end

What if I wanted to expand this a thousand-fold? I'd have to do this:

def test(string)
case string
when "something" : puts "#{@something_something}"
when "something_else" : puts "#{@something_something_else}"
# ... repeated many more times
end
end

But that thousand-line case could be replaced with a one-liner:

def test(string)
puts "#{instance_variable_get("@#{string + "_something"}")}"
end


I got here because I was looking at my inelegant code and wanted to
know how it could be simplified when faced with greater use.

Thinking in infinites.. yes, it's optimising early, but I wanted to
learn something new.

Depending on what's in your instance variables and how you call test
you might be able to throw away some punctuation e.g.

def test(string)
puts instance_variable_get('@something_' + string)
end

Mike

--

Mike Stok <[email protected]>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.
 
S

Sy Ali

Uh...if you have so many similarly named variables, it sounds like you
should be using an array or a map.

The map could be set up with the keys (a certain string) indexing to
the values of your old variables.

Oh, good point. =)
 
S

Sy Ali

How about:

puts "#{eval('$' + 'var' + (if $a == true then "iable" end))}"
# => pass


I can see the value with this, but what if I wanted to add a number to
the resulting variable?

Something like this:

a = "var"
b = "iable"
$variable = 1
eval('$' + 'var' + 'iable') += 1
 
D

dblack

Hi --

One of the reasons for the Perl chorus is that in Perl the "soft references"
can only point to non-lexical variables, and this can cause much opportunity
for enlightenment later!

Interesting. I've always been part of the "use hashes" chorus (long
ago in Perl and now in Ruby), though I can't remember whether I ever
knew this or just vaguely perceived symbolic references as (usually)
involving very brittle and tightly coupled code.


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
J

John W. Long

Sy said:
The imaginary code would be:

ab = "pass"
puts ("a" + "b").to_variable

I've occasionally used something like this with methods. For instance, I
recently wrote an Exporter that worked something like this:

class Exporter
def export(format=:yaml)
method = "export_#{format}"
if respond_to?(method)
send(method)
else
raise "invalid format"
end
end

private

def export_yaml
...
end

def export_xml
...
end
end

Not sure what you are doing, but perhaps a method oriented solution
would work better.
 
M

Mike Dvorkin

I'm not quite clear what exactly you're trying to achieve, but you
can perform any operation on $variable by making it part of eval()
string:

puts eval('$' + 'var' + 'iable += 1')
#=> 2
puts eval('$' + 'var' + 'iable *=' + 10.to_s)
#=> 20

HTH :)

Mike Dvorkin
http://www.rubywizards.com
 
S

Sy Ali

I'm not quite clear what exactly you're trying to achieve, but you
can perform any operation on $variable by making it part of eval()
string:

puts eval('$' + 'var' + 'iable += 1')
#=> 2
puts eval('$' + 'var' + 'iable *=' + 10.to_s)
#=> 20

That's definitely what I wanted for one little snippet I was working
on. Thanks. =)
 
S

Sy Ali

I've occasionally used something like this with methods. For instance, I
recently wrote an Exporter that worked something like this:

Not sure what you are doing, but perhaps a method oriented solution
would work better.

That's pretty interesting.. I think I could adapt that for some other
stuff I've been thinking about.
 

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
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top