Forum: Ruby How can I write the awesome kind of code?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Pat M. (Guest)
on 2006-05-08 22:40
(Received via mailing list)
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
James G. (Guest)
on 2006-05-08 22:49
(Received via mailing list)
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
Logan C. (Guest)
on 2006-05-08 22:59
(Received via mailing list)
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
Pat M. (Guest)
on 2006-05-08 23:02
(Received via mailing list)
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?
James G. (Guest)
on 2006-05-08 23:14
(Received via mailing list)
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
Pat M. (Guest)
on 2006-05-08 23:14
(Received via mailing list)
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
Logan C. (Guest)
on 2006-05-08 23:24
(Received via mailing list)
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
Pat M. (Guest)
on 2006-05-08 23:27
(Received via mailing list)
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
This topic is locked and can not be replied to.