groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Jochen Theodorou" <blackd...@gmx.org>
Subject Aw: Re: Do closures always return a value?
Date Fri, 04 Dec 2015 13:53:03 GMT
> Gesendet: Freitag, 04. Dezember 2015 um 12:11 Uhr
> Von: "Felix Dorner" <felix.dorner@gmail.com>
[...]
> >> Is it possible to declare a closure to have type 'void' somehow?
> >
> > currently not
> 
> Ok. What happens if the last statement in a closure is a call to a void 
> method?

void will return as null... a convention added through reflection, because there too every
method can return something, even if void is supposed to be even less than null ;)
 
> >> I would like to exploit this somehow like this:
> >>
> >> def someMethod(Closure closure){
> >>
> >>       if (closure has no return value, or is somehow defined to be 'void'){
> >>         closure()
> >>       } else {
> >>               if (closure()){
> >>                     doSomething()
> >>               } else {
> >>                     doSomethingElse()
> >>               }
> >>       }
> >> }
> >
> > normally it makes no sense to have a logic like this.
> 
> I wouldn't ask for it if it wouldn't make at least a bit of sense to me, 
> but I'm maybe overwhelmed and want to define a WorldDomination API in a 
> single method definition. 

it happens to the best of us ;)

> So here you go:
> 
> interface TreeIterator extends Iterator {
>      void prune()
> }
> 
> Instances of this interface are used to walk over a tree structure and 
> can be used like this:
> 
> while (iterator.hasNext()){
>      Object next = it.next()
>      doSomethingWith(next)
>      if (!childrenAreInteresting(next)){
> 	it.prune() // this skips the subtree of the current element
>      }
> }
> 
> In groovy it would work somehow like this, with a closure:
> 
> iterator.each {
>      doSomethingWith(it)
>      childrenAreInteresting(next) // the 'each' implementation takes the 
> closure result and calls prune() if the result is false
> }
> 
> But sometimes I want to walk the whole tree and forget about having to 
> return a value:
> 
> iterator.each {
>      doSomethingWith(it)
>      true
> }

The design has two problems I see right-away. You use an object for an external iteration
to realize an internal iteration and then you use "each" for the iteration, which operates
on more or less linear data. Well, it surely is not bad, that it is an Iterator. But you will
provide the implementation, so it would be easy for you to have a different method do the
job. Because your tree is most probably not linear, so the standard each will not cut it.
So I would go for something like this:

in a more Java8 style:

iterator.filter (this.&childrenAreInteresting).each (this.&doSomething) 

or instead of using MethodClosure with the normal ones:

iterator.filter {childrenAreInteresting(it)}.each {doSomethingWith(it)}

or a more traditional variant:

iterator.traverse({childrenAreInteresting(it)}) {doSomething(it)}

In the first case I could for example let filter return "this", and set a filter field, that
is by default a closure returning true, or simply act on the field been set or not. In the
second case I would work with a method with a default value for the children test part in
a similar manner to the field before

bye Jochen
 

Mime
View raw message