From: Timothy H. <tim...@ma...> - 2002-06-03 14:53:44
|
On Monday, June 3, 2002, at 04:03 AM, Matthias Radestock wrote: > Timothy Hickey wrote: > >> Jscheme does have a form of multi-methods similar to SISC's >> define-method, but rather than >> using chaining it lets you bind multiple functions to the same name >> and then selects the best match >> using dynamic dispatch, > > Perhaps you misunderstood me. Generic procedures in SISC have methods > that get selected based on the argument types - just like in JScheme > (and CLOS, Dylan etc etc). Chaining is an additional concept that > allows one generic procedure to delegate calls to another generic > procedure when it cannot find a suitable match. By default > (define-generic foo) > will create a "normal" generic procedure to which any methods are added > with (define-methd (foo ...) ...), and chain it to a *special* generic > procedure containing all Java methods "foo" of all classes. Now I understand. Thanks. > >>> * The names of generic procedures by default are mapped to Java >>> method names via an "unschemification" conversion, e.g. foo-bar-baz? >>> becomes isFooBarBaz. This further blurs the distinction between doing >>> "schemy" things and "javay" things. >> This is cute! But its not essential, is it? Couldn't you just as well >> have used straight Java syntax here... > > Yes. The philosophy behind the S2J interface in SISC is very much one > of making Java blend in with Scheme. Another reason is that SISC, by > default, is case-insensitive which would make using straight Java names > awkward. You can do so by doing something like > (define-generic |isFooBar| (generic-java-procedure '|isFooBar|) > Note the || notation for case-sensitive symbols. Btw, this example also > makes the chaining explicit - the generic-java-procedure call retrieves > the generic procedure containing all methods isFooBar of all classes. Ahh yes. I had forgotten about case insensitivity. > >>> * constructors are generic procedures too. >> ?????????? >> Do you use chaining for selecting the appropriate constructor or >> method for a straight Java call? >> e.g. if there are five different constructors, does SISC select the >> one that best matches the arguments >> or the one that "first" matches the arguments (with respect to some >> ordering...) >> ?????????? > > Here's an example: > (define-constructor (<jstring> (next: next-method) > (<jchar> c)) > (next-method (->jarray (list c) <jchar>))) > (make <jstring>) ;calls Java method > (make <jstring> (->jchar #\o)) ;calls scheme method > > Handling constructors is actually somewhat complex. 'make' maintains a > table of generic procedures - one per class. The above example adds a > method to one of these, i.e. the generic procedure representing the > <jstring> constructors. The generic procedures are chained to generic > procedures holding all the Java constructors, again, on a per-class > basis. Constructor selection is based on looking up the generic > procedure for the constructors of the given class and then doing a > normal best-match selection on the methods. I understand. > >>> Note that at the moment SISC generic procedures can only operate on >>> Java objects, not Scheme objects (unless, of course, you use their >>> Java representation). That will change soon though with the >>> introduction of a SISC type system and object system. >> I look forward to seeing this, but it may be confusing having two type >> systems (Java and SISC) to consider. I think >> Jython has some experience dealing with these issues. > > The Java type system frankly isn't good enough for me :) > The two type systems will be integrated, i.e. it's going to be just one > type system of which the Java types are a part of. Hmmm. Could you make the Java part optional or switchable. There has been some interest from Microsoft in building .NET schemes. They might be interested in a SISC#. It seems that you are well on the way to defining a generic interface to OO languages that support reflection (e.g. SISC-java, SISC-C#, SISC-goo?, ...) > >>> 4) Many JScheme types map directly to standard Java types, making >>> type conversion unnecessary when objects cross the Scheme/Java >>> divide. In SISC explicit conversion is needed. >> Indeed, Jscheme is probably best thought of as a Scheme-skin for Java. >> It really is programming in Java, >> but the syntax is different and some higher order procedure patterns >> have been incorporated into the syntax. >> We're currentlly working on a syntax for implementing Java classes >> using Jscheme, which would complete this >> analogy. > > I see. I don't think SISC is going to go down the route of class > generation. There are obvious limitations to using only reflection, but > it fits in better with the SISC philosophy. > >>> * For some Scheme types, such as numbers, the mapping to Java types >>> is one-to-many, e.g. a Scheme number could be converted to a byte, >>> short, int, etc. This causes ambiguities when automatic conversion of >>> parameters is attempted. >> Makes sense (but couldn't a best fit mapping be made by default, i.e. >> choose the smallest applicable type ....) > > Yes, but when using generic procedures things start to get messy. See > the point further down my original list. > >>> * Some Java types have several corresponding Scheme types, e.g. a >>> Java array could be represented as Scheme list or vector - this >>> causes ambiguities when automatic conversion of results is attempted. >> The main problem is conversion from Scheme to Java (for procedure >> calls), i.e., what do Strings, Lists, >> and Vectors maps to. Converting back to Scheme could just do the >> reverse. > > The problem is that you start making arbitrary choices and thus taking > away choice from the user. > Whether I want an array returned "as is", as a list, or as a vector > depends on the context. Sure, if the call always returns a vector I can > convert things back into an array, or into a list, but a) I end up > doing two conversions instead of one, b) in the array->vector->array > conversion the object identity of the array is lost. This discussion is reminiscent of the AWT/Swing/SWT debate on the use of peers in building window systems. AWT uses peers exclusively (as in Jschemes use of Java types), Swing eschews the use of almost all peers (as in SISCs use of its own internal types), and SWT from IBM uses a mixture of both. > >> Conversion is indeed a tricky problem. It seems mandated by the need >> to have mutable Strings > > No. That's just one reason. All the other reasons I mentioned are much > more important. > >> Then you could just use a straight embedding of all >> other Scheme objects into Java >> by adding the Pair, Procedure, and Continuation classes to the public >> Java API for SISC.... >> Do you think this might work??? > > These classes already exist and you can pass unconverted instances to > Java by wrapping them, e.g. > (println (<jsystem> 'err) (java-wrap '(1 2 3))) > > I could have made the wrapping implicit, but at the moment it isn't. I > might still change my mind on that. > > Generally, I want to keep the Scheme types distinct from the Java > types. That's a different approach to JScheme, but is more suitable for > SISC. I see (and it seems like it might be portable to other Schemes, including those not written in Java, using the JNI....) > >> Anyway, I want to thank you for taking the time to write this >> explanation. > > You are welcome. I've learned a lot more about JScheme in the process. From my perspective SISC and Jscheme are not direct competitors anymore than Java and Scheme are. I really do view Jscheme as Java programming using a Scheme-like syntax and semantics, where SISC seems to be a high quality Scheme which happens to be implemented in Java. > >> It helps clarify the similarities and differences. I want to look at >> the >> way we handle define-method, perhaps we should allow it to be >> used over javadot names and to let it use the " . rest)" notation >> as SISC's define-method does... > > I'd encourage you to read the SISC manual and the code. The generic > procedure code is actually reasonably portable. I have downloaded it and started to read it, but I actually have had some trouble getting the java-interface to work (e.g. java-class seems to be undefined). I'm sure I'm just forgetting to load the right module or something equally silly, but I haven't had a lot of time to work on it yet. > >> I'm still interested in the possibility of adding javadot notation to >> SISC. > > It's possible. You are only saving one line of code per method name > though at the expense of having to use the uglier (IMHO ;) Java names. But thats one line for each "use" of a javadot symbol and when programming a big Java application with lots of library use each line of Jscheme can contain many many javadot symbols, e.g. the six lines of code after the imports contain 10 javadot symbols and this is pretty typical. (It is taken from an early email in this thread...) (import "java.util.zip.*") (import "java.io.*") (import "sisc.*") (import "sisc.data.*") ;; initialize SISC (define in (GZIPInputStream. (BufferedInputStream. (FileInputStream. (File. "sisc.heap"))))) (define ctx (AppContext.)) (Context.register "main" ctx) (define r (Context.enter "main")) (REPL.initializeInterpreter r (list->array String.class '()) in) (Context.exit) ;; The code above is an approximate Jscheme translation of the following java code from ;; sisc.contrib.applet.SISCApplet.java (but the sisc.heap is read from a File not a URL...) import sisc.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.util.zip.*; ....snip..... URL u=new URL(getDocumentBase(),"sisc.heap"); URLConnection conn=u.openConnection(); AppContext ctx = new AppContext(); Context.register("main", ctx); Interpreter r = Context.enter("main"); InputStream in=new GZIPInputStream(new BufferedInputStream(conn.getInputStream())); REPL.initializeInterpreter(r, new String[0], in); Context.exit(); ....snip.... On the otherhand, the SISC style probably encourages developers to develop Scheme libraries providing access to Java and hence make the resulting code more schemish. > >> I think Geoff's suggestions was to look into a way of finding a >> canonical >> method for converting SISC values into Scheme values (e.g. numbers >> go to ints if possible, the longs if possible, then doubles, the >> floats, then >> BigIntegers or BigDecimals, but inexacts always goto doubles, floats, >> and >> BigDecimals. > > The problem with conversion based on range is that if a Java method is > overloaded on, say, byte, int and long then you have no idea which one > is going to get called. Yes this does create a problem... > In many cases this won't matter, because the methods will usually all > do the same thing, but not always. > > Also, note that the numeric types are not sub-types of each other, e.g. > int is not a sub-type of long. Since selection of methods from a > generic procedure is based on types, automatic conversion to the > smallest type will result in failures to find appropriate methods. Java > gets around this by performing a widening conversion, which is > completely orthogonal to type-conversion (i.e. the implicit casting to > a base class) and not a concept I would want to introduce into SISC's > type system. Yes, we played with widening for a while, but have since removed it. > >> Thus, SISC could support a version of javadot with automatic >> conversion. >> It might even be possible to have javadot and the current SISC/java >> interface work concurrently... > > Yes. Anyone who wants to implement automatic conversion between Scheme > and Java types in SISC this is welcome to do so. I can certainly see > the attraction of the idea and perhaps some applications would indeed > benefit from it. However, in the general case I believe that it creates > more problems than it solves, which is why I decided against this > strategy. I think you made the right choice for SISC as the resulting system is truly a R5RS Scheme interface to Java and could easily be replaced with a similar interface to C# or other OO languages... My experience with Jscheme is leading me to believe that there is considerable latent power in principled, multilingual programming. Jscheme and SISC present two different approaches to this programming scheme. Cheers, ---Tim--- > > > Matthias. > |