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-----


Reply via email to