From the O’Reilly Cookbook there is code that keeps call functions in a
hash as a subscriber/listener type pattern. What I don’t understand (or
I don’t understand how it works is the line:
(@EventDispatcher_listeners[event] ||= []) << callback
module EventDispatcher
def setup_listeners @EventDispatcher_listeners = {}
end
def subscribe(event, &callback)
(@EventDispatcher_listeners[event] ||= []) << callback
end
protected
def notify(event, *args)
if @EventDispatcher_listeners[event] @EventDispatcher_listeners[event].each do |m|
m.call(*args) if m.respond_to? :call
end
end
return nil
end
end
From the O’Reilly Cookbook there is code that keeps call functions in a
hash as a subscriber/listener type pattern. What I don’t understand (or
I don’t understand how it works is the line:
(@EventDispatcher_listeners[event] ||= []) << callback
You can split it into two, which will make it more clear:
@EventDispatcher_listeners[event] ||= [] # makes it an empty array if
it doesn’t exist @EventDispatcher_listeners[event] << callback # and pushes the callback
on top of it
I agree that this kind of compact notation is very hand but slightly
indecipherable… Cheers,
From the O’Reilly Cookbook there is code that keeps call functions in a
hash as a subscriber/listener type pattern. What I don’t understand (or
I don’t understand how it works is the line:
(@EventDispatcher_listeners[event] ||= []) << callback
a ||= b
is equivalent to
a || (a = b)
IOW
a = b unless a
IOW
unless a
a = b
end
IOW
“eval b and assign the result to a if a is nil or false”.
In this case, since a Hash is also involved the lengthy form looks like
this:
unless @EventDispatcher_listeners[event] @EventDispatcher_listeners[event] = []
end @EventDispatcher_listeners[event] << callback
I hope you admit that ||= is much more concise and elegant.
What I don’t understand (or
I don’t understand how it works is the line:
(@EventDispatcher_listeners[event] ||= []) << callback
Here is a verbose a description:
@EventDispatcher_listeners is a hash.
Look up the entry in that hash, the entry named “event”.
But perhaps there is no such entry. (The entry is reported as nil.) In
that case, create one, and set it to be an empty array.
Now you have an array - either the array that was already the “event”
entry in the hash, or the empty array that is now the “event” entry in
the hash. Append “callback” as the last item of that array.
It is indeed functionally equivalent to those, though all of them
would blow up
Not all of them.
a = b unless a
works, for the same reason you described
a = a || b
working. Here, the “a =” is parsed before the “unless a” is evaluated.
It is indeed functionally equivalent to those, though all of them
would blow up
Not all of them.
a = b unless a
works, for the same reason you described
a = a || b
working. Here, the “a =” is parsed before the “unless a” is evaluated.
But yes, a ||= b maps more closely to a = a || b, just like a += b maps
to a = a + b.
Devin
(Though, I tend to use the ||= idiom most often with instance/class
variables, who don’t raise NameError like locals do.)
a = a || b
working. Here, the “a =” is parsed before the “unless a” is evaluated.
Whoops, right; thanks.
David
Might I be a curmudgeon on this Christmas eve eve? I say that any idiom
that’s confusing enough that its semantics isn’t instantly
recognizable to an old FORTRAN programmer like my curmudgeonly self
probably doesn’t contribute to code readability. So I would write
this out in “longhand” and not let the parser have an opportunity to
confuse me. So my “idiom” would be
if (!a) then
a = b
end
Or, since my curmudgeonly self has managed to learn Perl,
On Sun, 24 Dec 2006, M. Edward (Ed) Borasky wrote:
Might I be a curmudgeon on this Christmas eve eve? I say that any idiom
that’s confusing enough that its semantics isn’t instantly recognizable to
an old FORTRAN programmer like my curmudgeonly self probably doesn’t
contribute to code readability. So I would write this out in “longhand”
and not let the parser have an opportunity to confuse me. So my “idiom” would
be
if (!a) then
a = b
end
That won’t work though:
ruby -e ‘if (!a) then a = b end’
-e:1: undefined local variable or method `a’ for main:Object
(NameError)
because of the forward reference to a.
Or, since my curmudgeonly self has managed to learn Perl,
a = b if !a
||= is used a lot in Perl, too I guess I’m just used to it; my
eye takes it in pretty readily.
Might I be a curmudgeon on this Christmas eve eve? I say that any
idiom
that’s confusing enough that its semantics isn’t instantly
recognizable to an old FORTRAN programmer like my curmudgeonly self
probably doesn’t contribute to code readability.
Isn’t an idiom by definition somewhat unique to its cultural/language
context? If an expression is instantly recognizable by non-native
speakers of the language then it isn’t an idiom at all.
speakers of the language then it isn’t an idiom at all.
Gary W.
Uh … OK … I’ll be the curmudgeon and you can be the pedant.
Seriously though, you’re right. As David Black pointed out, it’s more or
less
inherited from Perl, as is “unless”. I find “unless” difficult to read
in many
circumstances, although it does seem natural in this one:
a = b unless defined?(a)
the missing word “already” gets filled in by my mind.
Or, since my curmudgeonly self has managed to learn Perl,
a = b if !a
||= is used a lot in Perl, too I guess I’m just used to it; my
eye takes it in pretty readily.
With no Perl background whatsoever, and a chronic dislike of things
terse / golfy, I’ll admit to using and liking ||=. Mostly because it
maps to a single simple concept - I don’t even begin to read it as
“assign b to a if a doesn’t exist”, I mentally parse it as “the lazy
initialisation operator” as a unit.
(Though, I tend to use the ||= idiom most often with instance/class
variables, who don’t raise NameError like locals do.)
Not to be picky, but class variables do raise NameError:
C:>ruby -e “puts @@a”
-e:1: uninitialized class variable @@a in Object (NameError)
C:>ruby -v
ruby 1.8.2 (2004-12-25) [i386-mswin32]
Personally, the way I remember this is that if there’s an even
number of prefix characters before the variable name
(like a or @@a) it raises NameError, but if there’s an odd
number (like @a or $a), it doesn’t.
Merry Christmas!
Wayne
Wayne V.
No Bugs Software
Ruby, C# and Erlang Agile Contract Programming in Silicon Valley
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.