
My
experience with objects comes from Common List, Clean, Hasekell and
Nice. In all these languages, the function behavior is determined by
many objects. I think that this is more powerful and clear than the
Java way. In Nice one can see the superiority of type-driven behavior
over the Java dot notation, since the dot notation is a particular case
of the type driven behavior. To make a long story short, one can apply
the dot notation to the first argument, or put it together with the
other arguments. For instance, consider the followin init() function
(entirely in dot notation):
c l a s s DrawLines ext ends Applet {
Button ext = new Button ( ”Exi t ” ) ;
Button dbutton= new Button ( ”Exec” ) ;
TextFi e ld t f= new TextFi e ld ( 1 5 ) ;
i n t xx= 5 ;
i n i
t ( ) {
this.setBackground ( Color . l ightGray ) ;
t h i s . add ( dbutton ) ; t h i s . add ( t f ) ;
t h i s . add ( ext ) ;
t h i s . setLayout ( n u l l ) ;
ext . r e shape (50 , 30 , 50 , 2 0 ) ;
dbutton . r e shape ( 50 , 80 , 80 , 3 0 ) ;
t f . r e shape (140 , 80 , 200 , 3 0 ) ; } ... etc. }
However,
in Nice the method is selected not only by the dotted object, but by
all arguments. This becomes clear by placing the dotted object inside
the argument list:
c l a s s DrawLines ext ends Applet {
Button ext = new Button ( ”Exi t ” ) ;
Button dbutton= new Button ( ”Exec” ) ;
TextFi e ld t f= new TextFi e ld ( 1 5 ) ;
i n t xx= 5 ;
i n i t ( ) {
setBackground (this, Color . l ightGray ) ;
add (this, dbutton ) ; t h i s . add ( t f ) ;
add (this, ext ) ;
setLayout (this, n u l l ) ;
reshape (ext, 50 , 30 , 50 , 2 0 ) ;
reshape (dbutton, 50 , 80 , 80 , 3 0 ) ;
reshape (tf, 140 , 80 , 200 , 3 0 ) ; } ... etc. }
In
order to see how useful and practical is the generalization of dot
selection, let us suppose that one needs to write Lisp-like lists in
Nice. I am using Nice because it has both the simpler, more restricted
dot notation as Java and Python, and the argument selection, more
general and powerful, as Haskell and Lisp. Here is the Nice definition
of polymorphic lists:
import java . i o . * ;
class Lst<T> { T head ; ?Lst<T> t a i l ; }
?Lst<int> cons ( i n t x , ?Lst<int> xs ) {
?Lst<int> newList= new Lst ( head : x , tail : xs ) ;
return ( newList ) ; }
?Lst<String> cons ( String x , ?Lst<String> xs ) {
?Lst<String> newList= newLst ( head : x , tail : xs ) ;
return ( newList ) ; }
String
car (? Lst<String> xs ) {
if ( xs==null ) return ( "" ) ; else return ( xs.head ) ; }
int car (? Lst<int> xs ) {
if ( xs==null ) return ( 0 ) ; else return ( xs.head ) ; }
boolean isEmpty (? Lst<String> xs )= xs==null ;
?Lst<String> cdr (? Lst<String> xs ) {
if ( xs== null ) return ( xs ) ; else return ( xs.tail ) ; }
?Lst<String> cdr (? Lst<String> xs ) {
if ( xs== null ) return ( xs ) ; else return ( xs.tail ) ; }
?Lst<int> cdr (? Lst<int> xs ) {
if ( xs== null ) return ( xs ) ; else return ( xs.tail ) ; }
void main ( String [ ] args ) {
InputStreamReader converter =
new InputStreamReader ( System.in ) ;
Buf feredReader in = new BufferedReader ( converter ) ;
?String s= "Type a sentence and press <Enter>"
;
println ( s ) ; s= in.readLine ( ) ;
?Lst<String> words=null ;
StringTokenizerst = new StringTokenizer ( s ) ;
while ( st.hasMoreTokens ( ) ) {
words= cons ( st.nextToken ( ), words ) ; }
var xs= words ;
while ( ! isEmpty ( xs ) ) { println ( car ( xs ) ) ;
xs= cdr ( xs ) ; } }
If
you want to see how the above program can be generalized into a full
fledged Lisp like stucture, take a look at my page on Nice:
www.discenda.org. In any case, since Haskell has the more general
method selection, there is no need to have the more restricted dot
selector. Nice has both method selectors, but I seldom use the dot
selector.
--- On Wed, 11/25/09, Michael Mossey