Well done!
It's now working as expected.
So if I understand correctly the => in the parameter declaration defers
function's invocation to a later stage?
Anyway, thanks for the shared insight with Scala.
Clint Gilbert said the following on 23/11/2010 21:46:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Bojan Vučinić wrote:
Clint, Greg,
Thanks for taking the time to look into this.
Here is the code that works:
def initButtons = {
...
pressedDo(printButton, print)
...
}
def pressedDo (aB: PushButton, action: Unit) = {
aB.getButtonPressListeners.add(new ButtonPressListener {
override def buttonPressed(b: Button): Unit = action })
'print' is a function or method, right?
Try changing the signature of predded do from
def pressedDo (aB: PushButton, action: Unit)
to
def pressedDo (aB: PushButton, action: => Unit)
When you call the first version,
pressedDo(printButton, print)
print is actually invoked right then, instead of when the button is
pressed. The semantics for parameters of this type are the same as
Java's. The second version
def pressedDo (aB: PushButton, action: => Unit)
means that the second param is an anonymous function that takes no
parameters and returns Unit. Calling this version of pressedDo with
pressedDo(printButton, print)
correctly makes that function - in this case a function that takes no
params, calls 'print', and returns Unit - get called when the button is
pressed.
Now, when initButtons, and in turn pressedDo, is called, the window var
should be non-null, so the error you're seeing is weird. But the first
version of pressedDo, where print isn't called when the button is
pressed, is almost certainly not what you want. Fix that, and see what
happens.
I get the error that display is null??
It is really strange.
Clint Gilbert said the following on 23/11/2010 20:37:
Actually, the type of b is the problem:
override def buttonPressed(b: Button): Unit = action
or even
override def buttonPressed(b: Button) = action
instead of
override def buttonPressed(b: PushButton): Unit = action
is what you want.
Clint Gilbert wrote:
This is getting off-topic, but it's something I actually know a tiny bit
about.
The compiler is complaining (I think) because you're not actually
overriding buttonPressed. This can happen when type inference goes a
little astray, especially with methods that return Unit. Naming
buttonPressed's param 'b' shouldn't be a problem. I'd try explicitly
specifying the return type, like
def pressedDo (aB: PushButton, action: Unit) = {
aB.getButtonPressListeners.add(new ButtonPressListener {
override def buttonPressed(b: PushButton): Unit = action
})
}
There are also inference rule that take effect regarding the = in
def foo(...) = { }
vs def foo(...) { }
The latter (I believe) is assumed to return Unit, but I always add the =
just to be sure. (/Programming Scala/ by Odersky, Venners, and Spoon
explains things like this very, very well.)
Additionally, you probably want something like this:
def pressedDo (aB: PushButton, action: => Unit) = {
aB.getButtonPressListeners.add(new ButtonPressListener {
override def buttonPressed(b: PushButton) = action
})
}
Note the new type of the 'action' param. It's now "a function that
takes no params and returns Unit", instead of an actual value of type
Unit. This is an easy way to have lazily-evaluated parameters.
Due to some neat syntactic sugar for writing anonymous functions of this
type, if you split the parameter list for pressedDo, like
def pressedDo (aB: PushButton)(action: => Unit) = {
aB.getButtonPressListeners.add(new ButtonPressListener {
override def buttonPressed(b: PushButton) = action
})
}
You could call it like:
pressedDo(someButton) {
val foo = new Foo
someOtherThing.doStuff(foo)
//etc
}
Here the stuff in the braces becomes an anonymous function that gets
passed to pressedDo.
It's also possible to use implicit conversions (the perhaps
tastelessly-named "Pimp-My-Library" pattern[1]) to "add" the pressedDo
method to the Button class. Well, kind of, not really to the Button
class, but combined with the above technique, you could make a call like
val someButton: Button = ...
someButton pressed {
val foo = new Foo
someOtherThing.doStuff(foo)
}
which is starting to look smooth. Implicits can get pretty black-magic
though, so use them with care and restraint if you do.
[1]: http://scala.sygneca.com/patterns/pimp-my-library
Bojan Vu ini wrote:
Hi All,
If you are using Scala for your code then you are obliged to write listeners in
the following way:
printButton.getButtonPressListeners.add(new ButtonPressListener {
override def buttonPressed(b: Button) {
print
}
})
I've tried to simplify this by defining the following method:
def pressedDo (aB: PushButton, action: Unit) = {
aB.getButtonPressListeners.add(new ButtonPressListener {
override def buttonPressed(b: PushButton) { action }})
}
and than invoking the method in this way (example)
pressedDo(printButton, print)
however, this results in a compiler error:
error: object creation impossible, since method buttonPressed in trait
ButtonPressListener of type (x$1: org.apache.pivot.wtk.Button)Unit is not
defined
aB.getButtonPressListeners.add(new ButtonPressListener {
I'm not a programming language specialist, and in addition a Scala novice, but
I'm puzzled why putting boilerplate code in a separate method is not working??
Best regards,
Bojan
Dr. Bojan Vu ini
President, Ma-CAD<http://www.ma-cad.com/>
[email protected]<mailto:[email protected]>
IM: bvucinic (Skype)
http://fr.linkedin.com/in/bvucinic
Maintenance Concept Adjustment& Design 31, rue Chanzy
Paris, Ile de France 75011 France
Work: +33 (6) 14 15 36 70
Mobile: +33 (6) 14 15 36 70
Fax: +33 (1) 53 01 38 28
See who we know in common<http://www.linkedin.com/e/wwk/4839994/> Want a
signature like this?<http://www.linkedin.com/e/sig/4839994/>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkzsKEEACgkQ5IyIbnMUeTvZuACeNSx8S8WlJuKapvMUifzEyPFi
fuYAn2rDRNUzKa35nM9rbLXEnrj/ESKU
=uLdg
-----END PGP SIGNATURE-----