groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Winnebeck, Jason" <Jason.Winneb...@windstream.com>
Subject RE: "External" closures, why?
Date Tue, 01 Dec 2015 20:48:20 GMT
The explicit cast was needed before 2.2 only when you were trying to cast a Closure to an instance
of an interface (or other SAM type). In my example, the closure implicitly can be casted to
type X after 2.2. Before 2.2, you had to explicitly cast the closure to X.

Jochen's example worked because he didn't declare the type of his parameter. When no type
is declared, "Object" is used, which will take the Closure directly.

I started out understanding Groovy by understanding how Groovy maps to Java code. The closure
block is like an anonymous class block from Java, where you create a new instance extending
Closure. That's why you can pass it where Object is needed but not where explicit type X is
needed. Groovy allows ways to cast things more than Java does, for example in Groovy you can
say "1 as String" to "cast" (convert) to a String -- in Java: "Integer.valueOf(1).toString()".
For closures Groovy allows you to "cast" them to a proxy object implementing the target type,
if that interface or abstract class has only one abstract method.

Jason

-----Original Message-----
From: alessio [mailto:alessino@gmail.com] 
Sent: Tuesday, December 01, 2015 3:39 PM
To: users@groovy.apache.org
Subject: Re: "External" closures, why?

On Tue, Dec 1, 2015 at 9:24 PM, Winnebeck, Jason <Jason.Winnebeck@windstream.com> wrote:
> What was recently added is that you don't need to explicitly cast a closure to a SAM
(single abstract method), which was adding a feature to match Java 8 lambdas (that also don't
need a cast). So if you have a method taking an SAM, you no longer need to explicitly cast:
>
> interface X { void xf() }
> void func(X x) { x.xf() }
>
> func { println "Hello, World!" }
>
> It used to be before Groovy 2.2 that you had to call func this way:
>
> func({ println "Hello, World!" } as X)

Thanks, I am afraid I am getting lost though. Jochen's code from before (which ran just fine
on 2.0) didnt have an explicit cast either. So why would I need one here, but not in his example

  def bar(shouldCall, toBeCalled) {
    if (shouldCall) return toBeCalled() else return null
  } // the returns are actually optional

  assert bar(true) {1} == 1
  assert bar(true, {1}) == 1 //alternative syntax

The only difference I can spot is that he did not specify an explicit type in his declaration.
Is that the reason for the explicit cast pre-2.2?

>
> Closures are the closest equivalent to Java lambdas, but they do more than lambdas because
they support delegation (this is similar to setting "this" in JavaScript closures, except
in Groovy you detain both the delegate and the original "this" -- as the "owner" field). Closures
can also be queried for the number of arguments they take, allowing overloading of closures
that I don't believe is possible with Java 8 lambdas. And of course with Groovy closures work
back to Java 5, so if you can't use Java 8 yet, you can use Groovy.

I have already read about the owner and the delegate, have to admit though that it is not
yet fully clear (but then I just started reading today :) ).

My main question is admittedly though less about the overall concept but the fact that you
can pass a function outside of the method call.

My apologies for dwelling on this subject, but I am still baffled by this and find it quite
confusing in terms of readability (maybe just my personal view :) ). Why would the syntax
allow for an argument to be outside of the call? Maybe somebody could explain the "historical"
reason or an actual case where that made sense.

Thanks

----------------------------------------------------------------------
This email message and any attachments are for the sole use of the intended recipient(s).
Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the
intended recipient, please contact the sender by reply email and destroy all copies of the
original message and any attachments.
Mime
View raw message