Skip to content
Will Clinger edited this page Mar 6, 2015 · 5 revisions

This list is based upon the language changes noted on pages 77-80 of the R7RS small standard and errata.

Incompatibilities with R5RS

Larceny's case sensitivity, as implemented to support R6RS, is compatible with the draft R7RS, except #!fold-case and #!no-fold-case are treated as comments. Larceny has converted to the R7RS semantics for those flags.

The include-ci library declaration has been added (but only to R7RS-style libraries).

The underscore wildcard for syntax-rules was implemented for R6RS, as were the procedures inexact and exact.

The remaining incompatibilities omit R5RS features Larceny will retain for backward compatibility or has already dropped (transcript-on and transcript-off).

Other language changes since R5RS

R7RS libraries

R7RS libraries have been implemented on an equal basis with Larceny's support for R6RS libraries. Larceny's ERR5RS mode is retained because it's useful for Larceny development, but most R7RS programmers will use a new R7RS-compatible top level.

New syntaxes: include, include-ci, cond-expand

Implemented only for R7RS define-library, and only at top level.

Exceptions

R7RS exceptions are mostly compatible with Larceny's R6RS-compatible exceptions, but the error procedure is different. Some R7RS predicates were added to distinguish different kinds of exceptions.

SRFI 9 records

Trivial. Larceny extends define-record-type to allow ERR5RS and R6RS syntactic record syntax.

Parameter objects

R7RS make-parameter is not fully compatible with Larceny's v0.97 semantics. R7RS make-parameter has been extended to support Larceny's historical semantics insofar as possible. The conflicting case is resolved by using R7RS semantics.

Promises

SRFI 45 enhancements were added.

Bytevectors

The lexical syntax is different, and most of the procedures have different names. At least one procedure (bytevector-copy!) has the same name but takes its arguments in a different order.

Vectors

New procedure: read-line

New procedure: flush-output-port

These are compatible with the R6RS, then Larceny has nothing more to do here.

Ports

R7RS ports aren't the same as R6RS ports, thank goodness, but there don't seem to be any outright conflicts.

Whether textual and binary ports are disjoint is implementation-dependent. In Larceny, they're disjoint (for interoperability with R6RS) but some textual operations might be allowed on binary ports.

The new open-binary-input-file procedure conflicts with Larceny's existing procedure of the same name, because Larceny's procedure returns a textual port. In stdio.sch, the definition of that procedure and five others is preceded by a FIXME comment that says those six procedures should go away as soon as possible.

New procedures: open-binary-input-file, read-u8, peek-u8, u8-ready?, read-bytevector, read-bytevector!, write-shared, write-simple, write-u8, write-bytevector.

String ports

Bytevector ports

These are mostly compatible with Larceny's existing string and bytevector ports.

New and revised procedures: write, write-simple, and write-shared

The R7RS write procedure writes R7RS-specific syntax unless the output port allows only R6RS syntax. Even then, R7RS syntax will be used when no R6RS syntax applies (e.g. for circular objects).

eof-object

Already provided.

Syntax definitions

Syntax definitions are allowed wherever variable definitions are allowed, but the scope rules are slightly different from R6RS. Larceny will probably continue to use R6RS scope rules.

syntax-rules ellipsis

Not yet implemented. Might be tedious to implement.

syntax-error

Took some doing, but it's done.

letrec*

Already provided.

Multiple values

The define-values, let-values, and let*-values forms are already implemented.

case and =>

The => is now allowed in the else clause.

case-lambda

In its own library.

when and unless

Already provided.

eqv? on numbers

As in R6RS.

eq? and eqv? on procedures

Better than the R6RS: On procedure arguments, eqv? may return true even when eq? returns false.

New procedures: boolean=? and symbol=?

Already provided.

NaNs

Already provided.

log takes a second argument

Already provided.

map and for-each required to terminate on shortest argument list

Incompatible with R6RS, but this matters only for R6RS programs that violate R6RS semantics. The punishment mandated by R6RS will be administered only in R6RS batch mode. (And maybe not even then; if so, it's a bug so benign no one is likely to complain about it.)

member and assoc take optional third argument

Routine.

New procedures: finite?, infinite?, nan?, exact-integer?, square, exact-integer-sqrt

Already provided except for exact-integer? and square.

- and / take one or more arguments

Character and string comparison predicates take two or more arguments

Already provided except for the -ci versions, which were upgraded.

New procedures: make-list, list-copy, list-set!, string-map, string-for-each, string->vector, vector-append, vector-copy, vector-map, vector-for-each, vector->string, vector-copy!, string-copy

Already provided or routine, but some are incompatible with R6RS procedures. All incompatibilities were resolved by extending the R6RS procedure to use R7RS semantics.

Optional start and end arguments for some procedures

Routine.

Some list procedures defined on circular lists

Routine or already provided.

Unicode

Already provided except for digit-value, which was added. Some Unicode bugs were fixed during the upgrade to Unicode 7.0.0.

New comment syntaxes

Already provided.

Lexical syntax for data with shared structure

Straightforward.

New lexical syntaxes for strings and symbols

By default, Larceny allows both R7RS and R6RS lexical syntax except in R6RS batch mode.

Syntactic differences between R6RS and R7RS:

  • R7RS doesn't support square brackets.
  • R7RS uses #u8(...) instead of #vu8(...) for bytevectors.
  • R7RS doesn't support #', #`, #, #,@ .
  • R6RS doesn't treat vertical line as a delimiter, but R7RS does.
  • R6RS treats # and square brackets as delimiters, but R7RS doesn't.
  • R7RS says intraline whitespace is a <space or tab>, but doesn't define <space or tab>.
  • R6RS says any Zs, Zl, or Zp counts as whitespace.
  • R6RS allows <next line>, <carriage return> <next line>, and <line separator> as a <line ending>.
  • R7RS allows only three line endings, but meaning of <newline> isn't specified.
  • R6RS comments include #!r6rs.
  • R7RS allows #!fold-case and #!no-fold-case directives, which must be followed by a delimiter or end of file.
  • R7RS identifiers can be of the form <vertical line> <symbol element>* <vertical line>.
  • R7RS identifiers may include U+200C and U+200D.
  • R7RS allows identifiers with inline hex escapes only if the identifier is enclosed within vertical lines.
  • R7RS allows many peculiar identifiers that R6RS does not allow.
  • R6RS strings may contain the \v or \f mnemonic escapes.
  • R6RS allows <mantissa width> to follow <decimal R> in <ureal R>.
  • R6RS allows #', #`, #, #,@ abbreviations.
  • R7RS allows # <uinteger 10> = <datum> and # <uinteger 10> # syntaxes.
  • R7RS allows @ as a <special initial> (see erratum 7).

file-exists? and delete-file

Already provided.

System environment, command line, and process exit status

Apparently compatible with R6RS.

The emergency-exit procedure bypasses dynamic-wind protection.

Time

Routine.

Integer division

Routine.

load takes second argument

Turned out to be routine.

New procedure: call/cc

Already provided.

REPL syntax

Redefinition of procedures (but not syntax keywords) has retroactive effect. Should be routine.

Formal semantics for dynamic-wind

Okay.

Incompatibilities with R6RS

Library syntax is different

Routine.

include, include-ci, include-library-declarations, cond-expand

Routine.

Standard libraries are different

As with SRFI libraries, there are some conflicts with R6RS names. Where possible, Larceny extends conflicting procedures and syntaxes to make renaming unnecessary.

No identifier syntax

Okay.

Internal syntax definitions

Allowed but with more restrictions than in R6RS.

No condition types

Might as well continue to use R6RS condition system.

Full Unicode not required

Larceny supports full Unicode 7.0.0, including all four normalization forms.

Full numeric tower is optional

Procedures whose semantics differs between R6RS and R7RS: real?, rational?, integer?. (The R6RS semantics is available in R7RS via real-valued?, rational-valued?, and integer-valued?.) Larceny continues to use R6RS semantics, as the R7RS semantics is muddled and possibly self-contradictory.

R6RS procedures absent from R7RS: div, mod, div-and-mod, div0, mod0, div0-and-mod0.

Non-final expressions in body may return multiple values

Will thought the R6RS allowed this as well.

Incompatible semantics for map, for-each

Larceny uses R7RS semantics unless the program is running in R6RS batch mode.

Optional third argument for assoc and member

Routine.

Extensions to quasiquote

Two R6RS extensions weren't adopted by R7RS. Can probably just ignore this.

No mantissa width syntax

As specified by the R6RS, the R6RS mantissa width syntax had no meaningful semantics anyway.

String ports as in SRFI 6, not R6RS

Hooray.

Different lexical syntax for bytevectors

For interoperability, Larceny supports both syntaxes. The #!r6rs flag can be used to disable R7RS lexical syntax on input, and a parameter can tell Larceny not to use R7RS lexical syntax for newly opened output ports.

No specified value for when and unless expressions

Okay.


Major issues:

Interoperability between R6RS and R7RS

Lexical syntax

The R6RS doesn't allow any extensions to the lexical syntax other than #! flags. The R7RS apparently doesn't mind.

The only sensible thing for Larceny to do here is to extend R7RS lexical syntax enough to support R6RS lexical syntax as well.

It looks as though the only serious conflicts are:

  • #u8(...) versus #vu8(...)
  • whether # is a delimiter

Larceny will recognize both bytevector syntaxes, and will treat # as a delimiter. (Whether # counts as a delimiter could be mode-dependent, but we'll wait to see whether that's really necessary.)

The new write-simple and write-shared procedures will use R7RS lexical syntax for bytevectors. The write and display procedures exported by (rnrs io) and (scheme base) will consult the output port's syntax mode.

Larceny's native procedures will eventually be changed to use the R7RS lexical syntax, but there's no rush there.

Binding conflicts

If a program imports both R6RS and R7RS libraries, then some of the imported identifiers may have incompatible bindings.

Consider, for example, a program that imports both (rnrs) and (scheme base). Here's a partial list of identifiers that are likely to have conflicts:


assoc               (R7RS more general)
bytevector-copy     (R7RS more general)
bytevector-copy!    (incompatible when 5 arguments are passed)
define-syntax       (R6RS more general)
eqv?                (R7RS likely to be more traditional)
error               (see below)
for-each            (R7RS more general)
let-syntax
letrec-syntax
map                 (R7RS more general)
member              (R7RS more general)
string->utf8        (R7RS more general)
string-for-each     (R7RS more general)
unless              (R6RS implies R7RS requirements)
utf8->string        (R7RS more general)
vector-for-each     (R7RS more general)
vector-map          (R7RS more general)
when                (R6RS implies R7RS requirements)

Programs that import both (scheme base) and (rnrs bytevectors) will have to rename one version of bytevector-copy!.

For unless and when, an R6RS-conforming definition will satisfy the R7RS requirements.

For define-syntax, Will thinks an R6RS-conforming definition can satisfy the R7RS requirements.

For assoc, bytevector-copy, for-each, map, and other procedures that are more general in the R7RS than in the R6RS, an R7RS-conforming procedure will work wherever the R6RS semantics is expected, with one problematic exception: the R6RS allows programmers to write programs that depend on exceptions raised by the R6RS versions but not by the R7RS versions.

That brain damage can be limited by providing only legacy support for R6RS programs. We'll make it easy for R7RS programs to import R6RS libraries, but we won't jump through hoops to make it easier for R6RS programs to import R7RS libraries.

Larceny's low-level version of those procedures will use the R7RS semantics. The versions of those procedures exported by the (rnrs base), (rnrs), and (scheme base) libraries will consult the execution-mode available at run time via system-features. If the execution mode is dargo or spanky (implying R6RS), those procedures will delegate to R6RS-conforming versions that raise the exceptions mandated by the R6RS. Otherwise they will simply delegate to Larceny's low-level versions of those procedures.

The R6RS error procedure treats its first argument as "who". The R7RS error procedure has no "who", and requires its first argument to be a string.

Larceny's native error procedure already deals with that problem by using the execution mode, the arguments, and the installed exception handlers to decide whether to behave as specified by the R6RS or by the relevant SRFI. Some variation of that should be good enough.

With the R6RS, let-syntax and letrec-syntax bodies can be sequences of definitions, which are then treated as though they had appeared within a begin where the let-syntax or letrec-syntax had originally appeared. Although the R7RS apparently doesn't permit this, it's unlikely to do any harm.

Clone this wiki locally