Problem
The behavior of *self
and @instanceVariables
is not always clear. We cannot be sure just by looking what they are referring to. By default, *self
within on
blocks refers to the outer *self
from the containing scope. However, this can be overridden by _self
and other methods. At that point, there is no certainty.
Example
This is an example where I had to create a second variable to weakly reference the outer *self
. I can't just access @commands
directly because *self
within the on
block refers to the IRC::Connection instance. This is because an explicit _self
argument is used when calling command handlers.
$bot = *self
weaken $bot
# TODO: need better way to do this
on $connection.handlers.PRIVMSG, :handleCommand {
need $msg
# commands only work in channels right now
if !$msg.target.*instanceOf(Channel):
return
# find the command
$trim = detail $msg.params[1].word(0).trimPrefix(".")
if !$trim.trimmed:
return
$command = $trim.result
# call the command
$bot?.commands.[$command.lowercase]?(
msg: $msg,
channel: $msg.target
)
}
Solution
I think in situations like this, we should not specify an explicit _self
. Instead, we should specify _this
which would force an override of *this
. The problem with this solution is that writing *this
over and over is ugly and inconvenient. I know we already have a lot of sigils, but perhaps an additional one to reference properties of *this
would provide a more elegant solution.
Example
Here is the above example, adjusted in accordance with this idea.
on $connection.handlers.PRIVMSG, :handleCommand {
need $msg
# commands only work in channels right now
if !$msg.target.*instanceOf(Channel):
return
# find the command
$trim = detail $msg.params[1].word(0).trimPrefix(".")
if !$trim.trimmed:
return
$command = $trim.result
# call the command
# (note that instance variables refer to the outer *self, the Bot instance)
@commands.[$command.lowercase]?(
msg: $msg,
channel: $msg.target
)
}
And to access properties of *this
(assuming we adopt the %
sigil):
on $person.haveBirthday {
%age++
say("Happy birthday %name!")
}