Closed som-snytt closed 11 years ago
I think this makes use of Andrew's suggestions from the superseded PR, although it may not be as simple at-a-glance as he'd like.
It plays on the current value of userName, as suggested, and shows the one-character change to make it work as expected.
I neglected to add humo(u)r.
The html might be iffy.
@som-snytt Thanks for the updated submission. I like! Couple of small comments. @nermin Thoughts from your side..?
Ah, I see the reason now for the object Test extends App
. Executing val printer = new Printer{ prompt }
"directly" in the REPL results in
scala> val printer = new Printer{ prompt }
Yes, Master> printer: Printer = $anon$1@76ad043
...
which unfortunately rather gives the game away :-( Here's a potential version that gets around that:
var userName: String = "root"
class Printer(labeller: =>Unit) {
def print(message: =>String, labelled: Boolean = false) {
if (labelled) labeller
Console println s"$message $message" // repeat message to make sure it gets thru
}
}
class Greeter(printer: Printer) {
def greet(whom: String) {
userName = whom // to whom are we speaking?
printer print (if (userName == "root") "I am Master of the Universe!" else "hello, world.")
}
}
def prompt() {
Console print (if (userName == "root") "Yes, Master> " else s"$userName$$ ")
}
new Greeter(printer = new Printer { prompt }) greet "paulp" // prints "Yes, Master> hello, world. hello, world."
I think this makes use of Andrew's suggestions from the superseded PR, although it may not be as simple at-a-glance as he'd like.
grin.
I guess my personal "puzzler aesthetic" is a one-line statement or single command that appears obvious but still does something totally unexpected is the goal for which to aim.
I this particular case, I think if we work back from the explanation we feel the "puzzling" part is the fact that the argument to Printer
is evaluated immediately. We're currently using this fact to produce two unexpected effects:
userName
is not paulp
labelled
is falseIf we can reduce this to one unexpected effect it the puzzler will hopefully be quicker and easier to scan and still be as puzzling. If we take the first effect, we could use something like:
var userName: String = "root"
class Printer(labeller: =>Unit) {
def print(message: =>String) {
labeller
Console println s"$message $message" // repeat message to make sure it gets thru
}
}
class Greeter(printer: Printer) {
def greet(whom: String) {
userName = whom // to whom are we speaking?
printer print s"Hello, $whom!"
}
}
def prompt() {
Console print (if (userName == "root") "Yes, Master> " else s"$userName$$ ")
}
new Greeter(printer = new Printer { prompt }) greet "paulp" // prints "Yes, Master> Hello, paulp! Hello, paulp!"
If we go for the second effect, we could use something like this (similar to the discussion item from the first submission):
class Printer(labeller: =>Unit) {
def print(message: =>String, labelled: Boolean = false) {
if (labelled) labeller
Console println s"$message $message" // repeat message to make sure it gets thru
}
}
def prompt() {
Console print "puzzler$ "
}
new Printer { prompt } print (message = "Hello, world!", labelled = true) // prints "puzzler$ Hello, world! Hello, world!"
new Printer { prompt } print (message = "Hello, world!") // also prints "puzzler$ Hello, world! Hello, world!"
@som-snytt will no doubt guess correctly that I personally my preference would be for the second version as it's shorter, avoids var
s (the use of which doesn't really feel like a "good example" to me) and hopefully is still puzzling because it's easy enough to reason correctly about what the first print
does and thus to (hopefully) just as easily set up a false expectation for the second one.
With the first version, the re-assignment to a var
in the greet
function might be "weird" enough for users to have more difficulty trying to figure out what the expected result should be. That would make the puzzler less puzzling.
Curious to hear everyone's thoughts!
OK, here's the demobox version.
I am pleased that, although the puzzler is about adapting to ()
, the puzzler doesn't actually print ()
.
Although that would have been pretty funny.
The answer starts with an outdated comment about evaluation of message. I remember now why I wanted emphasize that, but it's not a big deal. If you're unsure about what =>Unit
means, you'll see =>String
nearby and feel reassured.
I couldn't figure out how to annotate a non-diff line at the commit.
From the ML, the perils of adapting to Tuple0 aka Unit value.