Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!ccu.umanitoba.ca!herald.usask.ca!alberta!brazeau.ucs.ualberta.ca!unixg.ubc.ca!ubc-cs!uw-beaver!mit-eddie!xn.ll.mit.edu!hsdndev!husc6!carlton From: carlton@husc8.harvard.edu (david carlton) Newsgroups: comp.lang.scheme Subject: Re: standards Message-ID: Date: 31 May 91 15:36:50 GMT References: <1991May30.013756.21021@cs.umn.edu> Sender: news@husc6.harvard.edu Organization: Citizens for Boysenberry Jam Lines: 102 In-reply-to: kers@hplb.hpl.hp.com's message of 31 May 91 08:54:31 GMT In article kers@hplb.hpl.hp.com (Chris Dollin) writes: >In general, I am opposed to ``optional'' parts of standards. [I mean that I >would regard adding an optional part to a standard as something that required >strong justification - stronger than ``some implementations have it, some >don't, so we'll make it optional'' [*1].] > >This is because I think the standard is something the programmer refers to in >deciding what facilities are available for their programs. If they are not >interested in portability, then of course it doesn't matter if their local >implementation has oodles of extra features; *whether or not they're in the >Standard* they'll get used. > >If they *are* interested in portability, then they are obliged to use *no* >optional features - which means there's not much point in having them [*2]. Not really - you just have to realize that you are dealing with two closely related but different languages here. Let us call scheme-without-features "microscheme" and scheme-with-features "macroscheme". Then you can write perfectly portable programs which use features - you just have to be aware that you are programming in macroscheme instead of microscheme. Of course, programming in microscheme has the advantage that your programs will also work in macroscheme implementations, so you should try not to use features gratuitously; but in a situation where you need them, it should be clear whether or not your program will work on a given implementation. I personally use the optional features from standards quite regularly, and don't use the features of specific implementations unless there is no way to do things portably, and if that is the case (for error handling, say) I make sure that what I am doing is simple enough that it should work on many different implementations, and I make sure that the names that I choose for such functions are different from the ones used by the implementations. One thing that I would like to see is to have the various optional features grouped up into packages, so that it is easy to see just which features a given implementation supports, and so that I won't be stuck by having an implementation which supports lots of features but not one which happens to be crucial to what I am doing. A good example of doing things this way is the IEEE tower of numbers: they give various possible ways of supporting numbers in your Scheme implementation, and at each step they add several additional numbers and kinds of functions which should be supported, forming a nice coherent subset. I like that, and I think that that approach should be used more often. >Without some (Standard!) mechanism for a program to announce that it needs >optional parts X, Y, and Z, thank you, it's difficult for a reader (or a >compiler) to discover that what they're reading will use those options. I have a different but related problem: I want to be able to write programs which will run portably under lots of different Scheme implementations, in particular under both R3RS and R4RS implementations. This is (basically) impossible to do currently if you want to use functions such as number->string, which take different arguments under the two standards. What I am currently doing is providing a dialect-specific initialization file, which then defines some symbols telling what version of the standard is adhered to, etc., and also defines some other functions that are dialect-specific, such as the error functions; and then loads another file which takes care of (say) all of the R3RS defines. For example, my T dialect file looks like ; this file defines the dialect-specific bits for Yale T. (define *scheme:standard* 'r3rs) (define *scheme:dialect* 't) (define *scheme:lowercase* #f) (load "dialect.scm") (define perror error) ; more stuff deleted... and the file dialect.scm looks like (case *scheme:standard* ((r3rs) ...) ; R3RS initialization code ((r4rs) ...) ; R4RS initialization code where the dots contain code which define functions such as list? (for r3rs), n->s (which is a stripped down version of number->string that I use), and so forth. How do other people solve this problem? And what do people think about adding a variable to the Scheme standard which would be defined to be the name of whateverstandard is currently being followed? A bit kludgey, perhaps, and of course you couldn't expect it to work on versions of the standard before this variable was added, but you need something like that to allow people to write portable Scheme code, since the standards people seem (IMHO rightly) to value doing things properly above maintaining portability. >[*1] I am not claiming that that is how the Scheme standard was produced. >[*2] I agree that they can say ``if you provided so-and-so, you must provide it >like *this*'', which is half-useful. david carlton carlton@husc9.harvard.edu