Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Syntax sugar: method[](...) => method(...)

Reply
Thread Tools

Syntax sugar: method[](...) => method(...)

 
 
Erwin Abbott
Guest
Posts: n/a
 
      06-29-2007
Hi,

The [] method is really handy when you have an object that should
behave like a hash or array. One thing I find myself wishing I could
also do is something like

def logins[](date)
@events.select{|e| e.action == :login and e.date == date}
end

There may be a better way to deal with this example, but this is just
to demonstrate the circumstances where you don't have an array or hash
called logins, but you'd like to be able to use that [] syntax. One
way I though about doing it is

def logins
EventList.new @events.select{|e| e.action == :login}
end

class EventList
def initialize data
@data = data
end
def [] date
@data.select{|e| e.date == date}
end
end

logins[Date.today] # => all logins today from @events

I guess some people might prefer to write a method like
get_logins(date), but I like this syntax. It seems reasonable to also
define []= in EventList to update the original @events. What I'd like
to know is if there's another way to solve this problem, or if there
are any simple optimizations (maybe only keep one instance of
EventList and update its contents with each call to #events).

Lastly, has there been any mention of allowing function names like so
in ruby 1.9:
def logins[] date
# ...
end

Thanks,
- Erwin

 
Reply With Quote
 
 
 
 
Trans
Guest
Posts: n/a
 
      06-30-2007


On Jun 29, 4:17 pm, "Erwin Abbott" <erwin.abb...@gmail.com> wrote:
> Hi,
>
> The [] method is really handy when you have an object that should
> behave like a hash or array. One thing I find myself wishing I could
> also do is something like
>
> def logins[](date)
> @events.select{|e| e.action == :login and e.date == date}
> end
>
> There may be a better way to deal with this example, but this is just
> to demonstrate the circumstances where you don't have an array or hash
> called logins, but you'd like to be able to use that [] syntax. One
> way I though about doing it is
>
> def logins
> EventList.new @events.select{|e| e.action == :login}
> end
>
> class EventList
> def initialize data
> @data = data
> end
> def [] date
> @data.select{|e| e.date == date}
> end
> end
>
> logins[Date.today] # => all logins today from @events
>
> I guess some people might prefer to write a method like
> get_logins(date), but I like this syntax. It seems reasonable to also
> define []= in EventList to update the original @events. What I'd like
> to know is if there's another way to solve this problem, or if there
> are any simple optimizations (maybe only keep one instance of
> EventList and update its contents with each call to #events).


def logins
@_logins ||= Proc.new do |date|
@events.select{|e| e.action == :login and e.date == date}
end
end

However, I feel you are limiting yourself. Try something like this
instead:

def logins
@_logins ||= (
l = @events.select{|e| e.action == :login}
def l.by_date(date)
select{|e| e.date == date}
end
l
)
end

Then you can use:

logins.by_date(date)

If needed, you could change #logins to lazy evaluate too.

T.


 
Reply With Quote
 
 
 
 
Robert Klemme
Guest
Posts: n/a
 
      07-09-2007
On 29.06.2007 22:17, Erwin Abbott wrote:
> Hi,
>
> The [] method is really handy when you have an object that should
> behave like a hash or array. One thing I find myself wishing I could
> also do is something like
>
> def logins[](date)
> @events.select{|e| e.action == :login and e.date == date}
> end
>
> There may be a better way to deal with this example, but this is just
> to demonstrate the circumstances where you don't have an array or hash
> called logins, but you'd like to be able to use that [] syntax. One
> way I though about doing it is
>
> def logins
> EventList.new @events.select{|e| e.action == :login}
> end
>
> class EventList
> def initialize data
> @data = data
> end
> def [] date
> @data.select{|e| e.date == date}
> end
> end
>
> logins[Date.today] # => all logins today from @events
>
> I guess some people might prefer to write a method like
> get_logins(date), but I like this syntax. It seems reasonable to also
> define []= in EventList to update the original @events. What I'd like
> to know is if there's another way to solve this problem, or if there
> are any simple optimizations (maybe only keep one instance of
> EventList and update its contents with each call to #events).


It's pretty easy to achieve what you want:

irb(main):001:0> class Foo
irb(main):002:1> def logins
irb(main):003:2> x = %w{a b c}
irb(main):004:2> def x.[](a)
irb(main):005:3> select {|e| e == a}
irb(main):006:3> end
irb(main):007:2> x
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> f=Foo.new
=> #<Foo:0x7ff7abc8>
irb(main):014:0> f.logins["w"]
=> []
irb(main):015:0> f.logins["a"]
=> ["a"]

Here's another variant:

irb(main):016:0> class Bar
irb(main):017:1> def logins
irb(main):018:2> x = %w{a b c}
irb(main):019:2> lambda {|a| x.select {|e| e == a}}
irb(main):020:2> end
irb(main):021:1> end
=> nil
irb(main):022:0> b=Bar.new
=> #<Bar:0x7ff5bfe8>
irb(main):023:0> b.logins["a"]
=> ["a"]
irb(main):024:0> b.logins["w"]
=> []

I.e. you just create a proxy object that will handle the [] call.
However I am not sure it's a good idea - it's probably better to return
the original array or a copy of it.

Kind regards

robert
 
Reply With Quote
 
Erwin Abbott
Guest
Posts: n/a
 
      07-10-2007
Hi Logan,

Really cool stuff going on there, that was worth a thousand words. I
never knew about this UnboundMethod#bind thing, curious if Proc has a
similar mechanism. Also happy to learn Method#[] is an alias to
Method#call

Let me summarize what's going on here to make sure I understand. First
we're creating an UnboundMethod from the given block. Next we create
the named method, which returns a blank object with a [] method that
calls the block. Okay, that was simpler than I thought!

One thing I'll be trying to work out is calling the method "logins"
will return a plain Object instead of a list of @events that are of
the type :login. I think for my purposes defining a few more singleton
methods like obj.each and obj.size would be good enough.

On 7/9/07, Logan Capaldo <> wrote:
> class Module
> def bracket(name, &code)
> define_method("#{name}_bracketed", &code)
> m = instance_method("#{name}_bracketed")
> remove_method "#{name}_bracketed"
>
> define_method(name) do ||
> obj = Object.new
> m1 = m.bind(self)
> (class << obj; self; end).module_eval { define_method(:[]) { |x|
> m1[x] } }
> obj
> end
> end
> end
>
>
> class Foo
> bracket :logins do |date|
> @data.select { |e| e.date == date }
> end
> end
>
> Who needs sugar?
>
> (I so didn't test this at all)


Thanks,
- Erwin

 
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
Syntax Checker that's better than the normal syntax checker Jacob Grover Ruby 5 07-18-2008 05:07 AM
Syntax error? What syntax error? Assignment fo default values? Mark Richards Perl Misc 3 11-18-2007 05:01 PM
Syntax bug, in 1.8.5? return not (some expr) <-- syntax error vsreturn (not (some expr)) <-- fine Good Night Moon Ruby 9 07-25-2007 04:51 PM
[ANN] SqlStatement 1.0.0 - hide the syntax of SQL behind familiarruby syntax Ken Bloom Ruby 3 10-09-2006 06:46 PM
Syntax highligth with textile: Syntax+RedCloth ? gabriele renzi Ruby 2 12-31-2005 02:44 AM



Advertisments