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
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 Gray II
···
On May 8, 2006, at 1:38 PM, Pat Maddox wrote:
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?
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 May 8, 2006, at 2:38 PM, Pat Maddox wrote:
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
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 5/8/06, James Edward Gray II <james@grayproductions.net> wrote:
On May 8, 2006, at 1:38 PM, Pat Maddox wrote:
> 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?
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 Gray II
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
···
On 5/8/06, Logan Capaldo <logancapaldo@gmail.com> wrote:
On May 8, 2006, at 2:38 PM, Pat Maddox wrote:
> 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
>
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
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 Gray II
···
On May 8, 2006, at 1:59 PM, Pat Maddox wrote:
On 5/8/06, James Edward Gray II <james@grayproductions.net> wrote:
On May 8, 2006, at 1:38 PM, Pat Maddox wrote:
> 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?
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 Gray 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?
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 May 8, 2006, at 3:13 PM, Pat Maddox wrote:
On 5/8/06, Logan Capaldo <logancapaldo@gmail.com> wrote:
On May 8, 2006, at 2:38 PM, Pat Maddox wrote:
> 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
>
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
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
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, James Edward Gray II <james@grayproductions.net> wrote:
On May 8, 2006, at 1:59 PM, Pat Maddox wrote:
> On 5/8/06, James Edward Gray II <james@grayproductions.net> wrote:
>> On May 8, 2006, at 1:38 PM, Pat Maddox wrote:
>>
>> > 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?
>>
>> 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 Gray 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?
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 Gray II