pivot-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Clint Gilbert <clint_gilb...@hms.harvard.edu>
Subject Re: Scala
Date Tue, 23 Nov 2010 21:16:15 GMT
-----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/>
>>>>>>>> bojan.vucinic@ma-cad.com<mailto:bojan.vucinic@ma-cad.com>
>>>>>>>> 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-----

Mime
View raw message