Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > variable pointers

Reply
Thread Tools

variable pointers

 
 
xyz
Guest
Posts: n/a
 
      12-06-2006

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


 
Reply With Quote
 
 
 
 
Booker C. Bense
Guest
Posts: n/a
 
      12-06-2006
-----BEGIN PGP SIGNED MESSAGE-----

In article <(E-Mail Removed)>,
xyz <(E-Mail Removed)> 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


>
>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?
>


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+aB2CLKMaMl3IfaTNSUK0aJtzuJ pBi2/RUa6Mbz1j
EwD5qadlV9ZqQM50buQTUx+gGUVuYjXWSU7HKK0LrFfQlF3cD6 Bv47DCuqJNToc7
PvLGw2n0Qns=
=FwnP
-----END PGP SIGNATURE-----
 
Reply With Quote
 
 
 
 
Robert Klemme
Guest
Posts: n/a
 
      12-07-2006
On 06.12.2006 19:55, xyz 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.).
>
> 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.


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
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
pointers, pointers, pointers... cerr C Programming 12 04-07-2011 11:17 PM
"Variable variable name" or "variable lvalue" mfglinux Python 11 09-12-2007 03:08 AM
Function pointers, variable argument functions calling other variable-argument functions (sort of) S?ren Gammelmark C Programming 1 01-07-2005 09:41 PM
How do I scope a variable if the variable name contains a variable? David Filmer Perl Misc 19 05-21-2004 03:55 PM
Template specialization of pointers with function pointers Phil C++ 1 09-16-2003 02:17 AM



Advertisments