[plt-scheme] Abstracting Visitors (is in Java)
Hmmm I'll try again. I suppose the measly indentation didn't help the
readability.
The initial question I asked is now moot since the code I was asking how to
abstract was removed after I applied the right design recipe template.
What I have is a class that runs filters on an object called MyFile which
has two attributes - a name and a file size.
The PatternMatch filter Visitor filters the name against a lightweight
regular expression parser written by yours truly.
The SizeFilter filters the MyFiles by file size.
I have managed to abstract out common functionality into a filter function.
The last 2 parameters of are the calling expression and a lambda that
implements the boolean function.
private static Object filter(Object first, AList rest, IList visitor,
ILambda op) {
final AList getTheRest = ((AList)rest.accept(visitor));
return ((Boolean)op.execute()).booleanValue() ?
new AList.Cons(first, getTheRest) :
getTheRest;
The PatternMatch Visitors contributes the predicate for the filter by
calling it and passing the lambda expression
new ILambda() {
public Object execute() {
return new PatternMatch(pattern.toString(),
((MyFile)first).name).match();
}
});
public static class PatternMatchV extends Filter implements IList {
AList pattern;
PatternMatchV(AList pattern) {
this.pattern = pattern;
}
//________________________________________________________________________
public Object forCons(final Object first, final AList rest) {
//Pattern Matching Filter
return filter(first, rest, this, new ILambda() {
public Object execute() {
return new PatternMatch(pattern.toString(),
((MyFile)first).name).match();
}
});
}
}
The Size filter does same but of course invokes with a different lambda
new ILambda() {
public Object execute() {
return maxFileSize?
size > fileSize:
size < fileSize;
}
});
If maxFileSize is false it looks for files smaller than the fileSize
otherwise it looks for files bigger than fileSize
public static class SizeV extends Filter implements IList {
long fileSize;
boolean maxFileSize;
SizeV(long fileSize, boolean maxFileSize) {
this.fileSize = fileSize;
this.maxFileSize = maxFileSize;
}
//__________________________________________________________________________
public Object forCons(final Object first, final AList rest) {
//File size filter
final long size = ((MyFile)first).size;
return filter(first, rest, this, new ILambda() {
public Object execute() {
return maxFileSize?
size > fileSize:
size < fileSize;
}
});
}
}
}
Some observations. I spent the best part of the week looking for one bug.
Eventually I found it had been caused because I was using Cons where I
needed Append and thus was passing a nested instead of a flat list.
With Scheme this would have been apparent from the results I got. With Java
you get a classCastException - not very helpful when you've had to put a
bazillion casts in the code hence why it took so long to find.
There are no destructive assignment statements in the code and all the
non-Visitor code has been written tail recursively (I haven't figured out
how to do the equivalent with a Visitor yet).
Good you say... yeah well given a deep enough directory structure I get a
stack overflow!!
Haven't yet thought about what the fate of my so called filter higher order
function will be in situations that require the Lambda to take arguments.
The fold idea is interesting. I was wondering whether that could be done. I
find Java obfuscates the isomorphism between what little I know of OO and
FP. That makes things unnecessarily hard.
Wondering whether threading the code will solve my stack overflow problem
(searching each subdirectory in a different thread), not sure how to bring
it all together later?
>From: Noel Welsh <noelwelsh at yahoo.com>
>To: "wooks ." <wookiz at hotmail.com>, plt-scheme at list.cs.brown.edu
>Subject: Re: [plt-scheme] Abstracting Visitors (is in Java)
>Date: Thu, 4 Jan 2007 06:15:47 -0800 (PST)
>
>Interesting question. If I understand the code correctly
>(and that's no sure thing; I found the code very difficult
>to read (Java's fault -- excessive casting etc)) there are
>two possible implementations:
>
> !. Pass in the action to perform in the case of the empty
>list
>
> 2. Delegate this decision to the subclass (use an
>abstract method)
>
>Do the 1st and you've just about implemented fold. The 2nd
>I consider more OO style, but you end up writing classes
>that are really functions, as you need to have a new class
>for every possible action
>
>The interplay between OO and FP is certainly interesting!
>
>N.
>
>--- "wooks ." <wookiz at hotmail.com> wrote:
>
> > However there is more that could be abstracted. Both
> > forCons methods start
> > with
> >
> > return first instanceof Cons ?
> > new Cons(((Cons)first).accept(this),
> > ((AList)rest.accept(this))):
> >
> > to deal with the case of nested lists.
> >
> > I thought of hoisting that test into an abstract forCons
> > class and then
> > calling it via a super method in which case it would
> > become
> >
> > if ( first instanceof Cons)
> > return new Cons(((Cons)first).accept(this),
> > ((AList)rest.accept(this)));
> >
> > but what would I return if the If statement failed?
>
>
>Email: noelwelsh <at> yahoo <dot> com noel <at> untyped <dot> com
>AIM: noelhwelsh
>Blogs: http://monospaced.blogspot.com/ http://www.untyped.com/untyping/
>
>__________________________________________________
>Do You Yahoo!?
>Tired of spam? Yahoo! Mail has the best spam protection around
>http://mail.yahoo.com
_________________________________________________________________
MSN Hotmail is evolving check out the new Windows Live Mail
http://ideas.live.com