Simple ruby syntax: variable assignment

Just curious if there is a more elegant way to set a variable if it
happens
to not exist yet. I often find I am doing somthing like the following:

regex = ''
10.times { regex += '.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*\n' }

Is there some prettier way to within the second line create the variable
if
it does not exist yet? The above just looks ugly. I know I could use a
class
variable but that also does not seem right as I do not need it to be a
class
variable:

10.times { @regex += '.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*\n' }

On Friday, April 22, 2011 10:32:35 AM UTC-6, DK wrote:

variable:

10.times { @regex += '.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*,.*\n' }

Having no idea what the context is I’ll try to answer:

Since the code where you’re modifying your variable is w/in a block, any
variables referenced therein that don’t already exist (outside the
block)
won’t exist outside the block once after it has run:

$ cat test.rb
1.times { hi = “hello” }
defined?(hi) ? hi += " bye" : hi = “NOT DEFINED”
puts hi
$ ruby test.rb
NOT DEFINED

Thus, for your block to have any effect on local variables that exist in
the
enclosing scope these variables must already “exist” before the block.
This
means the parser must see the local variable (in some context where it
is
clear it is a local variable and not a method call, such as in an
assignment
statement) before the block definition in the enclosing scope.

So, assuming I understand your intent, the answer is no. The local must
already be defined (whether initialized with an actual value is another
matter (*see example below)) or you should use an instance, class, or
global.

  • (

$ cat test.rb
hi = nil if false # defines hi even though assignment never executed
1.times { hi = “hello” }
defined?(hi) ? hi += " bye" : hi = “NOT DEFINED”
puts hi
$ ruby test.rb
hello bye

I don’t know if this helps any or not…

I guess you could do something like this:
x = defined?(x) ? x+=“string” : “”

You can assign a value to a variable if it doesn’t exist like this:
s ||= “”
but in your case you want to use the operand + so the string needs to
exist.

Also an alternative for the loop example
regex = ‘’
10.times { regex += ‘.,.,.,.,.,.,.,.,.,.,.,.,.,.\n’ }

could be changed to
regex = ‘.,.,.,.,.,.,.,.,.,.,.,.,.,.\n’ *10

hope it helps

On Fri, Apr 22, 2011 at 1:19 PM, David K.
[email protected]wrote:

regex = ''

Having no idea what the context is I’ll try to answer:

NOT DEFINED
global.
I don’t know if this helps any or not…
regex += ‘something else’
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.


Jazmin

On Fri, Apr 22, 2011 at 1:15 PM, Kendall G.
[email protected]wrote:

if it does not exist yet? The above just looks ugly. I know I could use a
won’t exist outside the block once after it has run:
This means the parser must see the local variable (in some context where it
hi = nil if false # defines hi even though assignment never executed
1.times { hi = “hello” }
defined?(hi) ? hi += " bye" : hi = “NOT DEFINED”
puts hi
$ ruby test.rb
hello bye

I don’t know if this helps any or not…

Thanks Kendall… actually I think I confused things by putting the
block
but I think the answer is still pretty much the same for a case such as
the
following, that if I did not want to first create the variable by
assignment, that I should use an instance, class or global as you say.

regex = ‘’
regex += ‘something’

regex += ‘something else’

regex += ‘and another something’

On Fri, Apr 22, 2011 at 1:42 PM, Jazmin [email protected]
wrote:

I guess you could do something like this:
x = defined?(x) ? x+=“string” : “”

Thanks Jazmin, this is the kind of thing I was looking for although I
guess
in the end it is probably less readable than just assigning the variable
at
the top, hmmm… and am seeing also why it wouldnt make sense to override
a
base class like object or something with the above to handle undefined
cases
as it would not know the type of variable to create.

On Apr 22, 12:32pm, David K. [email protected] wrote:

Just curious if there is a more elegant way to set a variable if it happens
to not exist yet. I often find I am doing somthing like the following:

regex = ‘’
10.times { regex += ‘.,.,.,.,.,.,.,.,.,.,.,.,.,.\n’ }

A mostly unrelated note - if you’re really matching against a pattern
like this, you may want to consider changing the .* bits to [^,]* to
keep the backtracking under control. I put together a short set of
benchmarks:

Here’s the results on my system (2010 13" MBP) (1000 iterations,
except regex3):

                 user     system      total        real

regex1: 2.490000 0.000000 2.490000 ( 2.590084)
regex2: 0.050000 0.000000 0.050000 ( 0.048411)
regex3 (/100): 25.600000 0.060000 25.660000 ( 26.839205)
regex4: 0.080000 0.000000 0.080000 ( 0.090349)

regex3 is the same .* pattern as regex1 but with 20 fields instead of
10 - note that in order to benchmark it in a reasonable time I cut the
number of iterations from 1000 to 10 - in other words, regex3 would
have taken 2560 seconds to complete the whole benchmark.

One additional note - make sure you’re not using any of these
patterns with the Regexp::MULTILINE modifier, which makes ‘.’ match
newlines as well. I let a single instance matching regex1 run for
about 10 minutes before giving up.

Here’s an article on this phenomenon (‘catastrophic backtracking’)
with more detail:

Hope this helps!

–Matt J.