This page is part of the web mail archives of SRFI 72 from before July 7th, 2015. The new archives for SRFI 72 contain all messages, not just those from before July 7th, 2015.
Michael Sperber wrote: > Just out of curiosity---from this statement, and more like it on > this list, I'm getting the vague impression that people regard using > lists to represent compound syntax as something new. (Of course, > Scheme macro systems have been doing that forever.) Am I > misunderstanding the vibes here? Well, I'm most familiar with the portable syntax case expander from Chez Scheme [http://scheme.com/csug/syntax.html] that SISC uses. After I was using the portable syntax case expander for some time, I became aware that compound syntax objects were represented by lists. However, as far as I knew this was simply an internal representation. It was never clear to me that using CAR, CDR, and CONS as a procedural interface with that macro system was at all supported. I might luck out, and have a macro work when I wrote it, but how was I to know that it would work tomorrow or in some other implementation of syntax-case? Of course, perhaps the procedural interface was always supported and in fact so obvious that the manual didn't need to mention it :-) As you asked, I'm reporting on my vibes here... Then I learned more about PLT Scheme's macro system. I noticed that PLT Scheme did not support CAR, CDR, and CONS with syntax objects directly. (Though of course I can use SYNTAX->LIST etc.) I also saw that PLT Scheme had useful source code location tracking capabilities that greatly enhanced the macro error reporting. So my *impression* as I saw the progression towards more more powerful macro systems with better error reporting was that we were going from a procedural interface being available but not supported to not being available. A necessary loss in order to support more sophisticated features. Michael Sperber wrote: > No, the problem is the loss of abstraction. A line of argument occurred to me this morning. Let me try it out... In Java, java.util.List is an interface. This is a powerful abstraction, because any methods that operate on lists can be used directly with any object that can usefully have a list abstraction. java.util.List is probably not a useful abstraction for a Java parse tree. However, it would be a useful abstraction for Scheme syntax. Suppose we consider CAR, CDR, and CONS as an abstract interface to an underlying representation. Being able to traverse Scheme syntax as if it were a list is useful abstraction and allows us to use directly use powerful list procedures such as SRFI-1. But what about CONS? CAR and CDR could in theory be, for example, generic procedures that have the ability operate on different types. But CONS returns a pair. I don't know if any language has a good solution to the issue of what to do when you want to construct new objects of your preferred type. In Java, you might have a procedure that you wished to be able to return a list of the type you desired. (Think of a Java implementation of FOLD, for example). You could pass to the procedure an instance of a factory class to create a new list of your desired type. However, as a practical matter, I find (in Java) is once I get to the point of creating factory classes and so on, I'm often creating more new code in the framework with the factory classes etc. then I'm able to take out by removing code duplication. The cure turns out to be worse than the disease. As an alternative, I may be able to return a particular implementation of java.util.List, which user code then simply uses as a list without being concerned with what class is implementing it. java.util.Collections.singletonList(Object) works in this way, for example. By analogy, CAR and CDR might be generic procedures that operate on any kind of pair, or object oriented procedures that can operate on pair subtypes, while CONS always returns a plain pair. As an interface, CAR, CDR, and CONS have some advantages and disadvantages compared to Java's java.util.List interface. In Java, for example, you can insert a new item at the beginning of a list. However, the list procedures available in Scheme through SRFI-1 and simple tail recursion are richer (and far easier to use) than are the procedures available in Java's java.util.Collections or in the Apache commons library. I'm not sure that this is just a matter of available libraries. What I find in programming in Scheme compared to other languages is that there is tremendous synergy in the recurring pattern of the list concept: procedure calls as a list of arguments, data as lists, programs as list, macros that operate on lists. Java's collections library is a modern, sophisticated specification. It directly supports powerful abstractions such as lists and sets as interfaces. And yet, as a practical matter, I find that for much of the work I do Scheme's synergy around the list concept turns out to be more powerful (I can write code with more features in less time) then Java's sophistication in this area. I look at the SRFI proposal, and I say, "wow, I get to use the procedural interface of CAR, CDR, and CONS with syntax objects and thus use libraries such as SRFI-1 directly without conversions? *And* I get source code location information? Neat!" When you say the issue is the loss of abstraction, correct me if I'm wrong, what I imagine is an argument that goes like this: most current Scheme implementations do not support CAR and CDR as generic procedures or object oriented methods. In these Scheme implementations, the only way to get an object that can be operated on by CAR and CDR is to return a pair. We are thus constraining the implementation to use lists made up of standard pairs. I think this is a valid argument. But let me ask. Suppose you are using a typical Scheme implementation in which CAR and CDR operate only on plain pairs. You are then constrained to implement compound syntax objects as lists. You have lost the ability to use some other abstraction. As a practical matter, what impact does that have on you? What would you like to be able to do with a syntax object abstraction that you'd not be able to do if you've lost that abstraction? Regards, Andrew