[plt-scheme] Abstracting Visitors (is in Java)

From: wooks . (wookiz at hotmail.com)
Date: Sun Dec 31 20:44:39 EST 2006

Below is a class that houses some file filters. At the moment there are 2 
filters defined - one to match on file sizes, the other is a file name 
pattern matcher.

I have achieved one level of abstraction by hoisting the filter code to the 
abstract class and passing the required filter as a "lambda" function.

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?

Perhaps there is a structural fault with my design.


abstract class Filter {
  //This class house classes that run filters on the list of files
  //  So far we have a file size filter and a pattern match filter
  //

  //Constructors
  Filter() {}

  public Object forEmpty(){
    return Empty.ONLY;
  }

  //The code for both filters has been abstracted as it is identical save 
for
  // the filter condition.
  //The filter condition is defined as an anonymous function (implementing 
class lambda)
  // and passed in as a parameter.
  //It was also necessary to pass in the visitor as a parameter so that the 
abtracted
  // routine would know where it had been called from

  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 Cons(first, getTheRest) :
      getTheRest;
  }
  static class PatternMatchV extends Filter implements IList  {
    AList pattern;
    PatternMatchV(AList pattern) {
      this.pattern = pattern;
    }
    
//________________________________________________________________________
    public Object forCons(final Object first, final AList rest) {
      return first instanceof Cons ?
        new Cons(((Cons)first).accept(this), ((AList)rest.accept(this))):
        //Pattern Matching Filter
        filter(first, rest, this, new ILambda() {
          public Object execute() {
            return new PatternMatch(pattern.toString(), 
((MyFile)first).name).match();
          }
        });
    }
  }

  static class SizeV extends Filter implements IList {
    long fileSize;
    SizeV(long fileSize) {
      this.fileSize = fileSize;
    }
    
//__________________________________________________________________________
    public Object forCons(final Object first, final AList rest) {
      return first instanceof Cons?
        new Cons(((Cons)first).accept(this), ((AList)rest.accept(this))):
      //File size filter
        filter(first, rest, this, new ILambda() {
          public Object execute() {
            return ((MyFile)first).size > fileSize;
         }
        });
    }
  }
}

_________________________________________________________________
Windows Live™ Messenger has arrived. Click here to download it for free!  
http://imagine-msn.com/messenger/launch80/?locale=en-gb



Posted on the users mailing list.