Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Hashes and Blocks (Syntactical/Feature question)

Reply
Thread Tools

Hashes and Blocks (Syntactical/Feature question)

 
 
Pete Elmore
Guest
Posts: n/a
 
      10-30-2004
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I haven't been able to find any documentation on the syntax for a
certain feature, and am not sure the feature exists. What I would like
to do is add a block of code to a hash, so I could do something like this:

state = 0
states = {
0 => { puts "State 0"; state = 1 },
1 => { puts "State 1"; state = 0 }
}

However, I haven't found any documentation on doing anything like this,
so I'm not sure you can. What I'm doing right now is a little ugly:

state = 0
states = {
0 => "puts 'State 0'; state = 1",
1 => "puts 'State 1'; state = 0"
}

while a_condition
eval states[state]
end

Obviously, keeping code as a string and then using eval gets pretty
hairy if it gets any more complicated than this. The ability to pass
blocks as data is one of Ruby's best features, and this would allow
programmers to avoid constructs like
state = X
data.each { |datum|
if state == 0
code
elsif state == 1
other code
...
}

(If this is repugnant to the nature of Ruby, there's a better way to do
it, or it already exists and I've missed it, please forgive my n00b
question!)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)
Comment: Using GnuPG with Debian - http://enigmail.mozdev.org

iD8DBQFBgu+Yv24lB609Ih8RAvYhAKCSYQyZcpT/nj6LJJCBlxKHhkceUACfVca5
hrLw6eGQwZ7XZh2B2an/toc=
=uKEd
-----END PGP SIGNATURE-----


 
Reply With Quote
 
 
 
 
Andreas Schwarz
Guest
Posts: n/a
 
      10-30-2004
Pete Elmore wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> I haven't been able to find any documentation on the syntax for a
> certain feature, and am not sure the feature exists. What I would like
> to do is add a block of code to a hash, so I could do something like this:
>
> state = 0
> states = {
> 0 => { puts "State 0"; state = 1 },
> 1 => { puts "State 1"; state = 0 }
> }


state = 0
states = {
0 => Proc.new { puts "State 0"; state = 1 },
1 => Proc.new { puts "State 1"; state = 0 }
}

while a_condition
states[state].call
end
 
Reply With Quote
 
 
 
 
Gavin Sinclair
Guest
Posts: n/a
 
      10-30-2004
On Saturday, October 30, 2004, 11:29:20 AM, Pete wrote:

> I haven't been able to find any documentation on the syntax for a
> certain feature, and am not sure the feature exists. What I would like
> to do is add a block of code to a hash, so I could do something like this:


> state = 0
> states = {
> 0 => { puts "State 0"; state = 1 },
> 1 => { puts "State 1"; state = 0 }
> }


It's pretty easy:

state = 0
states = {
0 => lambda { puts "State 0"; state = 1 },
...
}

while a_condition
states[state].call
end

Cheers,
Gavin



 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      10-30-2004

"Gavin Sinclair" <(E-Mail Removed)> schrieb im Newsbeitrag
news:(E-Mail Removed)...
> On Saturday, October 30, 2004, 11:29:20 AM, Pete wrote:
>
>> I haven't been able to find any documentation on the syntax for a
>> certain feature, and am not sure the feature exists. What I would like
>> to do is add a block of code to a hash, so I could do something like
>> this:

>
>> state = 0
>> states = {
>> 0 => { puts "State 0"; state = 1 },
>> 1 => { puts "State 1"; state = 0 }
>> }

>
> It's pretty easy:
>
> state = 0
> states = {
> 0 => lambda { puts "State 0"; state = 1 },
> ...
> }
>
> while a_condition
> states[state].call
> end


And you can even define default behavior:

state = 0
states = Hash.new( lambda { puts "fallback" } ).update(
0 => lambda { puts "State 0"; state = 1 },
1 => lambda { puts "State 1"; state = 0 }
)

loop do
states[rand 100].call
end

or even (for individual fallbacks)

states = Hash.new { |h,k| h[k] = lambda { puts "fallback for #{k}" } }
..update(
0 => lambda { puts "State 0"; state = 1 },
1 => lambda { puts "State 1"; state = 0 }
)

>> 10.times {|i| states[i].call }

State 0
State 1
fallback for 2
fallback for 3
fallback for 4
fallback for 5
fallback for 6
fallback for 7
fallback for 8
fallback for 9
=> 10

Kind regards

robert


 
Reply With Quote
 
Jim Haungs
Guest
Posts: n/a
 
      11-04-2004
What's a hashtable with names pointing to code blocks?
Hmm... Sounds like a class!

What you're trying to do is an example of the State pattern, which is
often implemented with sensibly-named states (as opposed to the
numbers in the example here). The state names are really method names;
you perform the operation for some state X by sending the X message to
an instance of the State class. The class can also encapsulate the
current state of the machine, track state transitions, or whatever.

And if you need multiple instances of the state machine, you just
create a new instance of the State class.

With the hash table scheme, the cohesion is poor because the current
machine state is separated from the operations on that state.

On Sat, 30 Oct 2004 14:31:19 +0200, "Robert Klemme" <(E-Mail Removed)>
wrote:

>
>"Gavin Sinclair" <(E-Mail Removed)> schrieb im Newsbeitrag
>news:(E-Mail Removed)...
>> On Saturday, October 30, 2004, 11:29:20 AM, Pete wrote:
>>
>>> I haven't been able to find any documentation on the syntax for a
>>> certain feature, and am not sure the feature exists. What I would like
>>> to do is add a block of code to a hash, so I could do something like
>>> this:

>>
>>> state = 0
>>> states = {
>>> 0 => { puts "State 0"; state = 1 },
>>> 1 => { puts "State 1"; state = 0 }
>>> }

>>
>> It's pretty easy:
>>
>> state = 0
>> states = {
>> 0 => lambda { puts "State 0"; state = 1 },
>> ...
>> }
>>
>> while a_condition
>> states[state].call
>> end

>
>And you can even define default behavior:
>
>state = 0
>states = Hash.new( lambda { puts "fallback" } ).update(
> 0 => lambda { puts "State 0"; state = 1 },
> 1 => lambda { puts "State 1"; state = 0 }
>)
>
>loop do
> states[rand 100].call
>end
>
>or even (for individual fallbacks)
>
>states = Hash.new { |h,k| h[k] = lambda { puts "fallback for #{k}" } }
>.update(
> 0 => lambda { puts "State 0"; state = 1 },
> 1 => lambda { puts "State 1"; state = 0 }
>)
>
>>> 10.times {|i| states[i].call }

>State 0
>State 1
>fallback for 2
>fallback for 3
>fallback for 4
>fallback for 5
>fallback for 6
>fallback for 7
>fallback for 8
>fallback for 9
>=> 10
>
>Kind regards
>
> robert
>


 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      11-04-2004

"Jim Haungs" <(E-Mail Removed)> schrieb im Newsbeitrag
news:(E-Mail Removed)...
> What's a hashtable with names pointing to code blocks?
> Hmm... Sounds like a class!


Yeah, you can view it that way.

> What you're trying to do is an example of the State pattern, which is
> often implemented with sensibly-named states (as opposed to the
> numbers in the example here). The state names are really method names;


I beg to differ at this point: state names are usually translated to class
names. Events are translated to methods (see the example below).

> you perform the operation for some state X by sending the X message to
> an instance of the State class.


Again, I'd rephrase that to "you perform some operation Y for state X by
sending the message Y to an instance of X.

> The class can also encapsulate the
> current state of the machine, track state transitions, or whatever.


State transitions are tracked by exchanging the instance.

> And if you need multiple instances of the state machine, you just
> create a new instance of the State class.


Yep.

> With the hash table scheme, the cohesion is poor because the current
> machine state is separated from the operations on that state.


That's true although it's what the OP asked for.

Kind regards

robert


Example

class Window
def initialize
@state = WinClose.new
end

# actions
def look() @state.look end

# queries
def open?() @state.open? end

# transitions
def open() @state = @state.open end
def close() @state = @state.close end

private
class WinOpen
# actions
def look() "beautiful landscape" end

# queries
def open?() true end

# transitions
def open() raise "You can't open an open window" end
def close() WinClose.new end
end

class WinClose
# actions
def look() nil end

# queries
def open?() false end

# transitions
def open() WinOpen.new end
def close() raise "You can't close a closed window" end
end
end


> On Sat, 30 Oct 2004 14:31:19 +0200, "Robert Klemme" <(E-Mail Removed)>
> wrote:
>
> >
> >"Gavin Sinclair" <(E-Mail Removed)> schrieb im Newsbeitrag
> >news:(E-Mail Removed)...
> >> On Saturday, October 30, 2004, 11:29:20 AM, Pete wrote:
> >>
> >>> I haven't been able to find any documentation on the syntax for a
> >>> certain feature, and am not sure the feature exists. What I would

like
> >>> to do is add a block of code to a hash, so I could do something like
> >>> this:
> >>
> >>> state = 0
> >>> states = {
> >>> 0 => { puts "State 0"; state = 1 },
> >>> 1 => { puts "State 1"; state = 0 }
> >>> }
> >>
> >> It's pretty easy:
> >>
> >> state = 0
> >> states = {
> >> 0 => lambda { puts "State 0"; state = 1 },
> >> ...
> >> }
> >>
> >> while a_condition
> >> states[state].call
> >> end

> >
> >And you can even define default behavior:
> >
> >state = 0
> >states = Hash.new( lambda { puts "fallback" } ).update(
> > 0 => lambda { puts "State 0"; state = 1 },
> > 1 => lambda { puts "State 1"; state = 0 }
> >)
> >
> >loop do
> > states[rand 100].call
> >end
> >
> >or even (for individual fallbacks)
> >
> >states = Hash.new { |h,k| h[k] = lambda { puts "fallback for #{k}" } }
> >.update(
> > 0 => lambda { puts "State 0"; state = 1 },
> > 1 => lambda { puts "State 1"; state = 0 }
> >)
> >
> >>> 10.times {|i| states[i].call }

> >State 0
> >State 1
> >fallback for 2
> >fallback for 3
> >fallback for 4
> >fallback for 5
> >fallback for 6
> >fallback for 7
> >fallback for 8
> >fallback for 9
> >=> 10
> >
> >Kind regards
> >
> > robert
> >

>


 
Reply With Quote
 
Pete Elmore
Guest
Posts: n/a
 
      11-04-2004
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Thanks for all of the helpful responses!

"Gavin Sinclair" <(E-Mail Removed)> wrote:
| states = Hash.new( lambda { puts "fallback" } ).update(
That's interesting; it had not occurred to me to use the default hash
value like that.

"Jim Haungs" <(E-Mail Removed)> wrote:
| What you're trying to do is an example of the State pattern, which is
| often implemented with sensibly-named states (as opposed to the
| numbers in the example here).
Yeah, actually, I was simplifying it a little; I used names for the states.
| With the hash table scheme, the cohesion is poor because the current
| machine state is separated from the operations on that state.
Very good point. But writing a class to handle a state machine for a
program that was about thirty lines could have made it quite a bit
longer/more complicated.

The program actually generated Ruby code that was used by another Ruby
program to perform the tedious task of writing assembly language for the
PIC microcontroller (whew).
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)
Comment: Using GnuPG with Debian - http://enigmail.mozdev.org

iD8DBQFBigJTv24lB609Ih8RAtbdAJsHdHSY7pik1xWT8bYSGk ef7sIpqgCfV2JQ
QN9AALBzXPT1Puc6DbIx+Sw=
=KcEB
-----END PGP SIGNATURE-----


 
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
"Pseudo-hashes are deprecated" error and accessing a hash of hashes ernestm@mindspring.com Perl Misc 3 01-31-2006 04:40 AM
Hash of hashes, of hashes, of arrays of hashes Tim O'Donovan Perl Misc 5 10-28-2005 05:59 AM
procs/blocks - blocks with procs, blocks with blocks? matt Ruby 1 08-06-2004 01:33 AM
Hashes of Hashes via subs Ben Holness Perl 8 10-08-2003 06:57 AM



Advertisments