[comp.lang.scheme] standards

boley@cs.umn.edu (Daniel Boley) (05/30/91)

I respectfully agree with the spirit of the letter.  But as a practical
matter, if portability is desired, you will have to look at what is in the
actual implementations.  Many leave out certain "optional" constructs, like
reals, rationals, "case", bignums, ... (these are the ones I have run
across).  Almost all of these schemes make the claim that they adhere
strictly to the R?RS standard.  These optional constructs that are left out
can make it very difficult to port code.

The result is that I can develop code on my scheme that claims to be
"standard" using only "standard" constructs,  but then my friend can't run
the same code on his/her scheme.

One solution for all those optional things is that there be some scheme library
that can be loaded to add in the "optional" features.  Unfortunately,
adding many optional features via scheme source will require macros.  But if
portability is a real goal, there must be some **standard** way of adding
many of the optional features so that every scheme implementation can have a
common base, including most of the common optional features.  At the moment,
it is possible to leave out the most unexpected "optional" features, and
still "adhere" to the standard.

A related point: If you want the language to be used widely by many people
in many disciplines, you have no choice but to make the language big enough
to handle their needs.  The language does not have to be that big, but at a
minimum, it must have most (if not all) of the "optional" features
standard, and it must have the basic hooks that people really use.  From the
discussion here, those latter features include things like macros, multiple
return values, environments, etc.  For a vanilla standard, many of these
could be implemented with just a few additional hooks in the basic language,
together with a small scheme library of front-end functions.  Then compiler
writers would be free to "hardwire" some of those front-end functions.  But
the basic language could be kept small.

This follows the suggestion of a library.  There would be a basic standard
language, and there would be a standard set of loadable code to expand the
language to adhere to an agreed-upon wider standard, in case the
implementation does not have the corresponding features built in.

WIth the narrow standard that exists today (that is the standard with none
of the optional features), every implementor feels free to decide
how to expand the language to his/her own demands, and each one does it
differently.

- Dan Boley

Don't mind me, I'm just an intruder from the fortran world.

markf@zurich.ai.mit.edu (Mark Friedman) (05/31/91)

In article <1991May30.013756.21021@cs.umn.edu> boley@cs.umn.edu (Daniel Boley) writes:

   I respectfully agree with the spirit of the letter.  But as a practical
   matter, if portability is desired, you will have to look at what is in the
   actual implementations.  Many leave out certain "optional" constructs, like
   reals, rationals, "case", bignums, ... (these are the ones I have run
   across).

Case is not optional.

   The result is that I can develop code on my scheme that claims to be
   "standard" using only "standard" constructs,  but then my friend can't run
   the same code on his/her scheme.

I don't get it. The standard says that some things are not required.
It should be obvious that portable code should not depend on those
features.

   One solution for all those optional things is that there be some
   scheme library that can be loaded to add in the "optional"
   features.

As far as I know, the only optional things in the IEEE standard are
the numeric types, that is, implementations are not required to
implement the whole tower.  RnRS does have some non-essential syntax
and procedures, but they are clearly marked, and again, portable code
obviously should not depend on them.

   Unfortunately, adding many optional features via scheme
   source will require macros.  But if portability is a real goal,
   there must be some **standard** way of adding many of the optional
   features so that every scheme implementation can have a common
   base, including most of the common optional features.  At the
   moment, it is possible to leave out the most unexpected "optional"
   features, and still "adhere" to the standard.

I agree that we need macros for portability, but not for standard
adherence. 

   A related point: If you want the language to be used widely by many people
   in many disciplines, you have no choice but to make the language big enough
   to handle their needs. 

I disagree. Implementations may need to be big, but not the standard.
This has been a strong philosophical stance of the Scheme community
for a long time.

   This follows the suggestion of a library.  There would be a basic standard
   language, and there would be a standard set of loadable code to expand the
   language to adhere to an agreed-upon wider standard, in case the
   implementation does not have the corresponding features built in.

There has been Scheme libraries for quite a while. The problem has
been that until Ozan Yigit took over (de facto) none of the librarians
was particularly agressive in getting code and very few people
contributed any.  The lack of macros hinders the usefulness of
contributed code, because few people actually write portable code.
They exploit their "big" implementations. This might change in the
near future because there are more "small" implementations and
therefore more people who have to write portable code :-)

   With the narrow standard that exists today (that is the standard with none
   of the optional features), every implementor feels free to decide
   how to expand the language to his/her own demands, and each one does it
   differently.

That's exactly the point. Provide freedom to implementations while
allowing the developement of portable code.

-Mark
--

Mark Friedman
MIT Artificial Intelligence Lab
545 Technology Sq.
Cambridge, Ma. 02139

markf@zurich.ai.mit.edu

kers@hplb.hpl.hp.com (Chris Dollin) (05/31/91)

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].

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.

[*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.

--

Regards, Kers.      | "You're better off  not dreaming of  the things to come;
Caravan:            | Dreams  are always ending  far too soon."

carlton@husc8.harvard.edu (david carlton) (05/31/91)

In article <KERS.91May31095431@cdollin.hpl.hp.com> 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

jaffer@zurich.ai.mit.edu (Aubrey Jaffer) (06/01/91)

>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 ...

GOOD IDEA!  In my symbolic math system I have files for R4RS, IEEE,
scm2d, and common_lisp which all emulate the same functions.  But your
idea would give me finer control over features.

I also strongly suggest that we define:
 CHAR-CODE-LIMIT
 CHAR-CODE-LOWER-LIMIT
 MOST-POSITIVE-FIXNUM
 MOST-NEGATIVE-FIXNUM

The CHAR-CODE-LIMITs are needed for programs such as parsers that need
to dispatch on character codes.  The Scheme specs do not specify that
char->integer returns non-negative integers so we also need
CHAR-CODE-LOWER-LIMIT.

The FIXNUM variables are useful for programs which use monte-carlo or
modular methods.  These algorigthms are effecient only when the random
numbers used are large but do not require consing.  My benchmark
attempt (digits of pi) would also have had fewer mysteries if these
limits had been available.