How can I write the awesome kind of code?


#1

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


#2

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


#3

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


#4

On 5/8/06, James Edward G. II removed_email_address@domain.invalid 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?


#5

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


#6

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


#7

On 5/8/06, James Edward G. II removed_email_address@domain.invalid 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


#8

On 5/8/06, Logan C. removed_email_address@domain.invalid 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