> Gesendet: Freitag, 04. Dezember 2015 um 12:11 Uhr
> Von: "Felix Dorner" <[email protected]>
[...]
> >> 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
 

Reply via email to