# Variable pointers

**URL:** <https://www.ruby-forum.com/t/variable-pointers/78550>\
**Category:** Ruby\
**Created:** [December 6, 2006, 8:01pm UTC](https://www.ruby-forum.com/t/variable-pointers/78550 "2006-12-06T20:01:44Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![xyz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/b5a626/32.png) [@xyz](https://www.ruby-forum.com/u/xyz)\
**Post date:** [December 6, 2006, 8:01pm UTC](https://www.ruby-forum.com/t/variable-pointers/78550/1 "2006-12-06T20:01:44Z")

</div>

I have a situation where I’m walking through an unordered sequence of  
text  
(splitting at newlines) looking for particular patterns. If a particular  
pattern  
matches then I perform some processing unique to that pattern and assign  
the  
output to a particular location (the location could be anything, e.g.  
local  
scalar, a particular array element, an instance variable, etc.).

WARNING: C syntax approaching. Please restore your seats to their  
upright and  
locked positions and apply seat belts.

Using “&” (take address) and “\*” (de-reference pointer) from C,  
conceptually  
what I want to do is:

template = [  
[patternRegex, processingProc, &storage]  
…  
]  
textSequence.each { |line|  
template.each { |tuple|  
\*tuple[2] = tuple[1].call(line) if line =~ tuple[0]  
}  
}

Obviously this could be achieved with eval() but that is very  
heavyweight.

Are there other options?

It doesn’t seem that using Symbol’s will work since they’re not  
addresses (and  
thus can’t be de-referenced) and they’re scope-independent, i.e. if I  
use :foo I  
can’t distinguish between a local variable foo, a method foo(), etc.  
even if  
they’re not lexically visible within the current scope.

As a kludge I could change tuple[2] to be an integer that indexes into  
an array  
and after the main loop is finished manually scatter the array elements  
to their  
final locations (note the word “kludge” at the beginning). The locations  
being  
stored may be all over the place so collecting them in a single object  
would be  
difficult, no less kludgy, and would obfuscate the code.

Thanx.

Jake

---

<div class="post-metadata">

**Author:** ![xyz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/b5a626/32.png) [@xyz](https://www.ruby-forum.com/u/xyz)\
**Post date:** [December 7, 2006, 7:56pm UTC](https://www.ruby-forum.com/t/variable-pointers/78550/2 "2006-12-07T19:56:25Z")

</div>

On 06.12.2006 19:55, xyz wrote:

> what I want to do is:
> 
> and after the main loop is finished manually scatter the array elements to their  
> final locations (note the word “kludge” at the beginning). The locations being  
> stored may be all over the place so collecting them in a single object would be  
> difficult, no less kludgy, and would obfuscate the code.

I can think of several approaches one of them being:

class Foo  
INSTRUCTIONS = {  
/(\d+)\s\*+\s\*(\d+)/ =\> lambda {|t, a, b| a.to\_i + b.to\_i},  
}

def process (enum)  
result = {}  
enum.each do |line|  
INSTRUCTIONS.each do |rx, fun|  
md = rx.match(line) and result[rx] = fun[\*md.to\_a]  
end  
end  
result  
end  
end

irb(main):051:0\> Foo.new.process [“1+2”, “3”]  
=\> {/(\d+)\s\*+\s\*(\d+)/=\>3}

Of course, you could use a symbol as label in INSTRUCTIONS and use that  
to reference results. And then you might as well store multiple results  
(if it is possible that a pattern matches multiple times).

class Foo  
INSTRUCTIONS = {  
:sum =\> [/(\d+)\s\*+\s\*(\d+)/, lambda {|t, a, b| a.to\_i + b.to\_i}],  
}

def process (enum)  
result = Hash.new {|h,k| h[k]=[]}  
enum.each do |line|  
INSTRUCTIONS.each do |label, (rx, fun)|  
md = rx.match(line) and result[label] \<\< fun[\*md.to\_a]  
end  
end  
result  
end  
end

irb(main):087:0\> Foo.new.process [“1+2”, “3”, " 4 + 4"]  
=\> {:sum=\>[3, 8]}

You can as well hand over the MatchData instance directly to the lambda  
etc. but I guess you get the picture.

Btw, that method also works with an IO instance.

Kind regards

```
robert
```

---

<div class="post-metadata">

**Author:** ![xyz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/x/b5a626/32.png) [@xyz](https://www.ruby-forum.com/u/xyz)\
**Post date:** [December 6, 2006, 8:45pm UTC](https://www.ruby-forum.com/t/variable-pointers/78550/3 "2006-12-06T20:45:55Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----

In article [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid),  
xyz [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I have a situation where I’m walking through an unordered sequence of text  
> (splitting at newlines) looking for particular patterns. If a particular pattern  
> matches then I perform some processing unique to that pattern and assign the  
> output to a particular location (the location could be anything, e.g. local  
> scalar, a particular array element, an instance variable, etc.).

You are thinking in “C”, this just doesn’t work well in  
Ruby. Everything in Ruby is an object and every variable is just  
a pointer to that object. When you say

a = b

in Ruby, it means in C

a = &b

and

a

always evaluates to

\*a

> ```
> ]
> 
> ```
> 
> textSequence.each { |line|  
> template.each { |tuple|  
> \*tuple[2] = tuple[1].call(line) if line =~ tuple[0]  
> }  
> }
> 
> Obviously this could be achieved with eval() but that is very heavyweight.
> 
> Are there other options?

Just use

tuple[2] = tuple[1].call(line) if line =~ tuple[0]

You can’t easily pass storage around in Ruby, like you can in  
C. What you pass around is a pointer to an object. The  
processingProc should handle the createtion of the object,  
the storage item is just a name for where you store the pointer  
to the object. If you are managing storage, rather than objects  
you are doing things the hard way in Ruby.

\_ Booker C. Bense

-----BEGIN PGP SIGNATURE-----  
Version: 2.6.2

iQCVAwUBRXccaGTWTAjn5N/lAQH8KwQAvIk0tnWmc1aGr3MYFqfg08CBWXa5cBLw  
rQRJEfnxMuW9WyaHBikO2Gb+aB2CLKMaMl3IfaTNSUK0aJtzuJpBi2/RUa6Mbz1j  
EwD5qadlV9ZqQM50buQTUx+gGUVuYjXWSU7HKK0LrFfQlF3cD6Bv47DCuqJNToc7  
PvLGw2n0Qns=  
=FwnP  
-----END PGP SIGNATURE-----
