How can I write the awesome kind of code?

I’m writing a small app to do poker simulations. I read a lot of
blogs in which the author shows off his cool DSL. I decided I want to
be able to specify a poker hand in my app like

hand “my_hand” do
players 10
chips 1000
end

my_hand.foo

How can I do something like that?

Pat

On May 8, 2006, at 1:38 PM, Pat M. wrote:

How can I do something like that?

class Hand

end

def hand( …, &init )
Hand.new( … ).instance_eval(&init)
end

I really think you’ll be happy in the long run though if you drop the
instance_eval() and pass the hand into the block instead.

James Edward G. II

On May 8, 2006, at 2:38 PM, Pat M. wrote:

How can I do something like that?

Pat

class Hand
def initialize(name, &block)
@name = name
if block
instance_eval(&block)
end
self
end
def players(i)
@players = i
end

def chips(i)
@chips = i
end

def foo
puts self.inspect
end
end

def hand(name, &block)
Hand.new(name, &block)
end

my_hand = hand “my_hand” do
players 10
chips 1000
end

my_hand.foo

#<Hand:0x363450 @name=“my_hand”, @chips=1000, @players=10>

If you want to automatically set ‘my_hand’ you can put it inside an
enclosing object and dynamically define the my_hand method

On 5/8/06, James Edward G. II [email protected] wrote:

end

I really think you’ll be happy in the long run though if you drop the
instance_eval() and pass the hand into the block instead.

James Edward G. II

Okay so now I have

class Hand
def players(p = nil)
@players = p unless p.nil?
@players
end

def chips(c = nil)
@chips = c unless c.nil?
@chips
end
end

def hand(&init)
yield(Hand.new) if block_given?
end

hand do |h|
h.players 10
h.chips 1000
end

Does that look right?

How can I use the Hand object that I just created?

On May 8, 2006, at 1:59 PM, Pat M. wrote:

chips 1000
def hand( …, &init )
Okay so now I have
end

Does that look right?

You can remove the &init parameter to hand(), since you are using
yield. You may also want to make players() and chips() more Rubyish
with players=() and chips=().

To keep the hand object you could have hand return it, or perhaps add
it to some global Hash by name.

Hope that helps.

James Edward G. II

On May 8, 2006, at 3:13 PM, Pat M. wrote:

players 10
class Hand

 Hand.new(name, &block)

#<Hand:0x363450 @name=“my_hand”, @chips=1000, @players=10>
Hey Logan,
class Hand

end

puts my_hand.inspect

proc { h }.call is redundant.

define_method(name) { h } should work

Though I question whether hand name { … } is necessary.

Why not just do

my_hand = hand do |h|
h.players 10
h.chips 1000
end

puts my_hand.inspect

On 5/8/06, James Edward G. II [email protected] wrote:

hand “my_hand” do
end

@chips = c unless c.nil?
h.chips 1000

Hope that helps.

James Edward G. II

I took out &init, I understand why I don’t need that in there.

However after doing all this, I’m not sure I get any benefit,
particularly if I stick to the more Rubyish players= and chips=

hand “my_hand” do |h|
h.chips = 1000
h.players = 10
end

vs

my_hand = Hand.new
my_hand.chips = 1000
my_hand.players = 10

It’s basically the same…

Pat

On 5/8/06, Logan C. [email protected] wrote:

end
@name = name
@chips = i

If you want to automatically set ‘my_hand’ you can put it inside an
enclosing object and dynamically define the my_hand method

Hey Logan,

Thanks for the input. Here’s what I ended up with. I don’t know if
I’m doing bad stuff though to define the object - please let me know.
In the hand method, I’m creating the hand and passing the block like
normally. Then to let me call the hand by the name I pass in, I
define a new method that calls a closure that simply returns the value
of the newly created object. It works great…I just don’t know if
there’s a better way, or if this is a bad approach.

class Hand
def players(p = nil)
@players = p unless p.nil?
@players
end

def chips(c = nil)
@chips = c unless c.nil?
@chips
end
end

def hand(name, &init)
h = Hand.new
yield(h) if block_given?
self.class.class_eval { define_method(name) { proc { h }.call } }
h
end

hand “my_hand” do |h|
h.players 10
h.chips 1000
end

puts my_hand.inspect