-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Yes, params like a: => Unit mean, in effect 'evaluate a only when it's
referenced, not when it's first passed to a method'.
The implementation is a function, so the notation is really a special
case of the function literal syntax.
if you have
def f1(a: => Unit) = a
it's almost the same as
//a is a funtion that takes an empty param list and returns Unit
def f2(a: () => Unit) = a
in the sense that both times, 'a' in the bodies of the defs means
'invoke the function a'.
But with the first form, you can do cool stuff like
f1 {
val x = ...
val y = stuff(x)
moreStuff(y)
}
I'm gald it worked. Scala is a fun language!
Bojan Vučinić wrote:
> 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:
> 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
iEYEARECAAYFAkzsLx8ACgkQ5IyIbnMUeTvCLwCdEe/4Lp+HODLNBicXjFez6bp2
rRIAnRRi9DprdAk5/IqlRLlU0/Wrl/i0
=V9kO
-----END PGP SIGNATURE-----