Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

YA Scheme critique

12 views
Skip to first unread message

John Tobey

unread,
Jun 8, 2002, 12:59:40 PM6/8/02
to
This is Yet Another Scheme Critique: my thoughts on how to make Scheme
better for my kinds of programming.

I offer this as constructive criticism, not anti-Scheme advocacy. I
consider myself pro-Scheme, but a few seemingly minor issues keep me
from advocating its use where I work. Of course, what works for me
will not work for everybody, and I can not speak for everybody, but
perhaps someone will be interested in one programmer's perspective.

In some cases, Scheme implementations do a much better job than R5RS,
so I must state in advance that my recent investigations have been
with PLT (10x), Stalin, Chicken, SLIB, and Petrofsky's eiod. I looked
at, but have not used, Kawa and BRL. I have not taken enough time to
learn all of the tricks of these implementations, but I am reasonably
confident of what follows. I looked over the "final" SRFIs, but not
at any draft SRFIs.

My current job is in the financial services industry and involves
mostly data processing and job scheduling and monitoring. The favored
languages are C (for speed and database APIs), Perl (as a better shell
and for parsing) and RDBMS stored procedures, with here and there a
little Java. We are very conservative about everything, including our
use of software. When we upgrade a third-party system, the new
version is often not the newest available. We usually give it a
couple of years to prove itself in the world and on our test servers
before we install it to production. The platform is UNIX (Solaris).


WHY SCHEME
==========

Our C code is very hard to read because it constantly checks for and
propagates error codes from API functions. This might argue for C++
with exceptions, but then we would be implementing an API wrapper
similar to what we would need with Scheme. Few programmers know C++
well. Our C isn't very efficient, because a lot of it is generated by
a table-driven program and uses function calls for things like taking
the length of a constant string. Our C isn't as modular as I think
Scheme would be. To reuse code often means to copy, paste, change a
couple of constants or variable names, and watch the bugs evolve in
parallel.

Perl frightens me because it is not standardized. The Perl parser
resolves ambiguities by using heuristics where any other language
would throw an error, so it is hard to be sure of anything in Perl.
Perl's future is uncertain. The current implementation contains bugs
and is too complex to fix. The next version (Perl 6), if it is ever
completed, will likely not understand most existing Perl code. Perl
code is write-once-read-never, in that it is not susceptible to
automated processing. Perl lacks powerful macros.

Java lacks macros and first class functions. Java is overly verbose,
quasi-proprietary, and very inconvenient to experiment with from the
command line. I don't know how to debug Java code other than using
System.err.println.

Scheme is well defined and gives me good feelings about whether my
code will continue working.


WHY NOT SCHEME
==============

No way to run a Scheme program. SRFI 22 addresses this, but not all
Schemes support SRFI 22. Of course, every implementation has a way to
run programs, but some are inconvenient in a command-line environment.
Perl is the best in this regard.

No specified behavior for newlines in strings. Tab characters require
a literal tab in the source file, making it vulnerable to
reformatting. I don't understand why R5RS specifies \" and \\ in
strings but balks at mentioning \n \t #\tab and the rest.

Strings are fixed length. C's realloc() and Perl's .= (string
mutate-append) operator are really handy.

Vectors are fixed length. Again, C wins with realloc() and Perl
caters to everyday needs with push() pop() shift() unshift() and
splice().

set! is not general. Sorry Professors, I know there is a linguistic
difference between bindings and storage locations, but it is an
annoying and useless distinction in practice. I find it inexcusable
that Scheme requires a different assignment operator for each
containing structure. Think macros. Or even think code equals data.
Scheme is sweeping complexity under the carpet of programmers, to
paraphrase Larry Wall.

SLIB tends to smooth out these bumps, but SLIB is not trivial to use,
and it does not support every Scheme implementation. (This is not to
criticize SLIB, it is as easy as possible given the state of Scheme,
but that is still not trivial.)

No easy way to print diagnostics. Perl has a great operator called
"warn". It takes any number of arguments, prints them, and optionally
appends the source file name and line number. In any Scheme program
over 10 lines long, I find myself pasting in this code:

;; Emit an error or warning message.
(define (blurt args)
(display args (current-error-port))
(newline (current-error-port)))

;; Emit a warning.
(define (warn . args)
(blurt (cons "Warning:" args)))

but I don't know how to get a stack trace. Even C has __FILE__ and
__LINE__, clunky but effective. This warn function is for file-based
interactive development (an edit-save-run cycle). I usually remove
the "warn" calls from a section of code when I have finished working
on it. This must happen very quickly, thus the need for a simple
interface. "display" falls short because it takes only one argument
to be printed and does not print a newline. This kind of thing is
obviously easy to implement in a library; it should be mandatory
everywhere.

No exceptions. Of course, Scheme implementations generally have
exceptions. By my reading of R5RS and SRFI 23, those documents don't
even guarantee a way to halt execution. I have resorted to this in
the hope that it will always work:

(error msg)
(exit 1)
(let loop ((bla #f)) (loop (read-char)))

But I believe a conforming implementation could return from this after
reading eof. C has exit() and abort(), Perl has exit() and die(),
Java has System.exit(?) and throw new Error. Assembler has hlt; jmp
-1. With all of these, I feel confident that the next line of code
will not be reached. It's that simple.

Of course, robust applications must be able catch the exceptions that
they throw, another area where Scheme lags (as does C).

It is not enough that these features be implementable via
call-with-current-continuation or available with a little work. They
must be easy to use, well understood, and widely enough known to be in
every introductory Scheme book. (Not all books that introduce Scheme
are Scheme books, however.)


CONCLUSION
==========

Scheme is for people who like to prove concepts. While that's a nice
thing to do, there is more to life outside of academia, and Scheme
falls short as a general-purpose tool. I hope it will eventually
spawn or evolve into such a tool.

Best
-John

Feuer

unread,
Jun 8, 2002, 3:10:16 PM6/8/02
to
I have just a few comments.

John Tobey wrote:

> Our C isn't as modular as I think
> Scheme would be. To reuse code often means to copy, paste, change a
> couple of constants or variable names, and watch the bugs evolve in
> parallel.

Are you sure this is due to the choice of language and not to poor design?

> Perl frightens me because it is not standardized. The Perl parser

You can't actually do much at all in standard Scheme (the only language
I know of that does not have this problem is C, as there are numerous
IEEE standards for C. This situation does not seem likely to change
soon),
so I'm not sure how significant this really is. But Perl does seem to be
rather less stable than
most Schemes.

> command line. I don't know how to debug Java code other than using
> System.err.println.

There is at least one debugger for Java. I don't think it's stable, but
I'm not sure.

> Scheme is well defined and gives me good feelings about whether my
> code will continue working.

Well-defined depends whom you ask. R5RS is fairly limited. However, most
popular implementations
(including PLT, Bigloo, Chicken, and probably many more) have extensive
documentation.

> No way to run a Scheme program. SRFI 22 addresses this, but not all
> Schemes support SRFI 22. Of course, every implementation has a way to
> run programs, but some are inconvenient in a command-line environment.
> Perl is the best in this regard.

All popular Schemes I know of have convenient ways to run programs. The
compilers
of course are somewhat less convenient, but that's the price you pay for
efficiency in
any language. (some implementations including PLT and (I think) Chicken
are flexible in this regard).

> No specified behavior for newlines in strings. Tab characters require
> a literal tab in the source file, making it vulnerable to
> reformatting. I don't understand why R5RS specifies \" and \\ in
> strings but balks at mentioning \n \t #\tab and the rest.

This is rather annoying. I think this is at least in part because the
standard
did not want to go so far as to specify an encoding for text: RnRS is
very conservative, and text encoding is currently somewhat controversial.

> Strings are fixed length. C's realloc() and Perl's .= (string
> mutate-append) operator are really handy.

R5RS strings are indeed horribly limited. PLT and Bigloo
have somewhat more extensive string support (Bigloo seems to have
more than PLT), but I have not found all the functions I would hope to,
such as string->vector and vector->string.

> Vectors are fixed length. Again, C wins with realloc() and Perl
> caters to everyday needs with push() pop() shift() unshift() and
> splice().

How often do you really need realloc? realloc can only save time if
you're
lucky. Vectors in Scheme are likely to be implemented efficiently as
arrays.
To support Perl's vector operations efficiently would require a different
implementation, which would be slower for many purposes than Scheme
vectors.
If you need more flexible vectors, you can write your own using Scheme
vectors.

> set! is not general. Sorry Professors, I know there is a linguistic
> difference between bindings and storage locations, but it is an
> annoying and useless distinction in practice. I find it inexcusable
> that Scheme requires a different assignment operator for each
> containing structure. Think macros. Or even think code equals data.
> Scheme is sweeping complexity under the carpet of programmers, to
> paraphrase Larry Wall.

I think the purpose of this is to avoid the complexity of C-ish lvalues.
I haven't looked into any of the pattern-matching implementations,
but I wouldn't be surprised if they offered some of this sort of
simplification.
If they don't, they should.

> No easy way to print diagnostics. Perl has a great operator called
> "warn". It takes any number of arguments, prints them, and optionally
> appends the source file name and line number. In any Scheme program
> over 10 lines long, I find myself pasting in this code:
>
> ;; Emit an error or warning message.
> (define (blurt args)
> (display args (current-error-port))
> (newline (current-error-port)))
>
> ;; Emit a warning.
> (define (warn . args)
> (blurt (cons "Warning:" args)))

Some implementations surely support this, but I don't feel like checking.

> but I don't know how to get a stack trace. Even C has __FILE__ and
> __LINE__, clunky but effective. This warn function is for file-based
> interactive development (an edit-save-run cycle). I usually remove
> the "warn" calls from a section of code when I have finished working
> on it. This must happen very quickly, thus the need for a simple
> interface. "display" falls short because it takes only one argument
> to be printed and does not print a newline. This kind of thing is
> obviously easy to implement in a library; it should be mandatory
> everywhere.
>
> No exceptions. Of course, Scheme implementations generally have
> exceptions. By my reading of R5RS and SRFI 23, those documents don't
> even guarantee a way to halt execution. I have resorted to this in
> the hope that it will always work:

I think (error msg) will work in just about any real scheme system. Or
you can
be really silly and use (eval '() (scheme-report-environment 'a)). I
don't understand
why you insist so much on R5RS. Do your C programs restrict themselves to
standard
C?

> It is not enough that these features be implementable via
> call-with-current-continuation or available with a little work. They
> must be easy to use, well understood, and widely enough known to be in
> every introductory Scheme book. (Not all books that introduce Scheme
> are Scheme books, however.)

This is getting ridiculous.


David Rush

unread,
Jun 8, 2002, 3:44:22 PM6/8/02
to
Feuer <fe...@his.com> writes:
> John Tobey wrote:
>
> > Our C isn't as modular as I think
> > Scheme would be. To reuse code often means to copy, paste, change a
> > couple of constants or variable names, and watch the bugs evolve in
> > parallel.
>
> Are you sure this is due to the choice of language and not to poor design?

Because of Turing equivalence all maintenance problems are a matter of
bad design. Oddly enough, they do tend to show up rather more regularly
in some languages than in others.

> > Strings are fixed length. C's realloc() and Perl's .= (string
> > mutate-append) operator are really handy.

I suspect that you (Tobey) haven't really grokked the combinations
available with APPLY and STRING-APPEND.

> R5RS strings are indeed horribly limited.

Agreed. SRFIs 13 & 14 do a *lot* to remedy the situation. Perhaps too
much as it is difficult to really get a good grasp of everything
that's in that toolkit.

david rush
--
Einstein said that genius abhors consensus because when consensus is
reached, thinking stops. Stop nodding your head.
-- the Silicon Valley Tarot

David Rush

unread,
Jun 8, 2002, 4:28:32 PM6/8/02
to
"John Tobey" <jto...@john-edwin-tobey.org> writes:
> I offer this as constructive criticism, not anti-Scheme advocacy.

Just as long as you don't cross-post to c.l.lisp or mail to Erik
Naggum, you're grand.

> My current job is in the financial services industry and involves
> mostly data processing and job scheduling and monitoring. The favored
> languages are C (for speed and database APIs), Perl (as a better shell
> and for parsing) and RDBMS stored procedures, with here and there a
> little Java. We are very conservative about everything, including our
> use of software. When we upgrade a third-party system, the new
> version is often not the newest available. We usually give it a
> couple of years to prove itself in the world and on our test servers
> before we install it to production. The platform is UNIX (Solaris).

Been there. Done that. Bought the T-Shirt. We actually migrated to
Smalltalk in our company. It's probably the best all-round environment
for programming I have ever used. There are reasons (ranging from high
per-seat costs to changing problem domains) that I don't still hack
Smalltalk, but that would be fodder for another NG.

> No way to run a Scheme program.

Sorry, this is insane. It's a makefile issue, that's all. *And* it's
no different from the issues for any other programming language, be it
C Perl, Java, CL, Smalltalk, Ada, &cet. I've got projects where I can
build command-line executables from the same source tree to run under
6 different Schemes. You solve it once, it's solved forever.

> No specified behavior for newlines in strings. Tab characters require
> a literal tab in the source file, making it vulnerable to
> reformatting. I don't understand why R5RS specifies \" and \\ in
> strings but balks at mentioning \n \t #\tab and the rest.

This also annoys me, but R5RS doesn't prohibit C-style escapes
either. There *are* a lot of ways to deal with it, ranging from simply
typing the text in literally as you want to see it displayed (which is
not such a bad idea, really) to clever use of of the wide range of
denotable values in Scheme.

> Strings are fixed length. C's realloc() and Perl's .= (string
> mutate-append) operator are really handy.

I commented on this elsewhere. I don;t think you have grasped the
Scheme way of looking at things if this is a problem for you (And I've
been doing a *ton* of string-processing over the last 2 years).

> Vectors are fixed length. Again, C wins with realloc() and Perl
> caters to everyday needs with push() pop() shift() unshift() and
> splice().

There *are* big holes in the standard library. A SRFI-1 analogue for
vectors is sorely needed. In defense of RnRS, I will say that RnRS
generally does not hide performance costs from you. realloc() is a
dangerous primitive in a performance-intensive system.

> set! is not general.

SRFI-17. But it's still a bad idea.

> Sorry Professors, I know there is a linguistic
> difference between bindings and storage locations, but it is an
> annoying and useless distinction in practice.

Actually, it is an important *engineering* distinction. Mutation of a
data structure *may* involve rather more operations than the update of
a single storage location. Thinking otherwise is a bad C habit. And
please note: I am *not* an academic.

> No easy way to print diagnostics.

> but I don't know how to get a stack trace. Even C has __FILE__ and
> __LINE__, clunky but effective.

Error-handling is arguably one of the greatest failures of the R5RS
specification. It just isn't there.

> No exceptions.

So what? Exceptions are a generally bad intra-program communications
mechanism. I realize that I hold a fringe opinion on this issue.

Or are you conflating exceptions and error-handling?

> By my reading of R5RS and SRFI 23, those documents don't
> even guarantee a way to halt execution.

Nope. But in practice you can make any Scheme halt. You just wrap it
up in your local standard library and be done with it. SRFI-0 really
makes this sort of thing very easy.

> Of course, robust applications must be able catch the exceptions that
> they throw, another area where Scheme lags (as does C).

No Scheme does not lag. With call/cc you can implement any escaping
control mechanism you care to have. What Scheme doesn't have is
standardized error-handling. If you don't conflate these issues you'll
see that the problems are actually a lot smaller than they seem.

> It is not enough that these features be implementable via
> call-with-current-continuation or available with a little work. They
> must be easy to use, well understood, and widely enough known to be in
> every introductory Scheme book.

Are there introductory Scheme books that don't explain how to build a
throw/catch mechanism w/call-with-current-continuation? If there are
the authors should be shot, they're doing Scheme a great disservice.

> Scheme is for people who like to prove concepts.

s/prove concepts/write and reuse code quickly/

> While that's a nice thing to do, there is more to life outside of
> academia

I am a Principal Engineer in charge of server technology at a major
Internet Provider. I make quite a lot of use of Scheme in my day job
because I can prototype faster in Scheme than in any other language in
which I have worked. That said, Schem programming requires a
significant paradigm-shift from a mostly-imperative programming
style. I suspect that a number of your difficulties arise from this
cognitive dissonance. Certainly a lot of the people around me gaze on
in wonder at when I try to explain my code in their terms (C & Perl).

This is *not* to say that Scheme has arrived. Far from it, but I'm not
sure that you're complaints quite hit the mark.

david rush
--
Gnus is a fashion statement. Emacs is clothing. Everyone else is
running around naked.
-- Jonadab the Unsightly One (on gnu.emacs.gnus)

John Tobey

unread,
Jun 8, 2002, 4:00:46 PM6/8/02
to
On Sat, 08 Jun 2002 15:10:16 -0400, Feuer wrote:

> I have just a few comments.
>
> John Tobey wrote:
>
>> Our C isn't as modular as I think
>> Scheme would be. To reuse code often means to copy, paste, change a
>> couple of constants or variable names, and watch the bugs evolve in
>> parallel.
>
> Are you sure this is due to the choice of language and not to poor
> design?

It is most definitely a case of poor design (by my predecessors:)
combined with shifting requirements, time-to-market concern and employee
turnover. Such problems will be with us always. But I suspect that a
tidier language such as Scheme can help keep code smaller and easier to
grasp, thus slowing the buildup of mud.

>> Scheme is well defined and gives me good feelings about whether my code
>> will continue working.
>
> Well-defined depends whom you ask. R5RS is fairly limited.

Certainly, but it is better than nothing, and what it defines, it defines
well. C is well defined from the CPU's point of view. :-) Perl resists
definition.

> All popular Schemes I know of have convenient ways to run programs. The
> compilers
> of course are somewhat less convenient, but that's the price you pay for
> efficiency in
> any language. (some implementations including PLT and (I think) Chicken
> are flexible in this regard).

Well, perhaps its a case of my not reading enough, and maybe PLT's 200
series addresses this, but in a Debian distribution, I found myself
putting

#!/usr/lib/plt/.bin/i386-linux/mzscheme -r

at the top of my scripts, which seems somehow distasteful. Needless to
say, the first chapter of any Unix-oriented Perl book describes some of
the many ways of invoking perl.

>> Vectors are fixed length. Again, C wins with realloc() and Perl caters
>> to everyday needs with push() pop() shift() unshift() and splice().
>
> How often do you really need realloc? realloc can only save time if
> you're
> lucky. Vectors in Scheme are likely to be implemented efficiently as
> arrays.
> To support Perl's vector operations efficiently would require a
> different implementation, which would be slower for many purposes than
> Scheme vectors.
> If you need more flexible vectors, you can write your own using Scheme
> vectors.

Okay, it's not every day that I use realloc(). But my complaint is not
about efficiency or the inability to roll my own, it is about limitations
in the standard, default version. Rarely is efficiency more important
than simplicity and non-surpisingness among programmers of diverse
backgrounds.

Perl's push() and pop() do not necessarily reallocate the array, and
arrays and strings keep track of their allocated and filled length
transparently. Of course, fixed length can be implemented more
efficiently, so it's nice to have available. But in other areas, Scheme
specifications favor usability over ease of efficient implementation,
most notably numerics, tail recursion, and garbage collection. It's too
bad that philosophy didn't carry over into Scheme strings and vectors.
In the same way, it's too bad Perl and C applied it only to
strings/arrays and not to arithmetic or memory management.

>> ;; Emit a warning.
>> (define (warn . args)
>> (blurt (cons "Warning:" args)))
>
> Some implementations surely support this, but I don't feel like
> checking.

Then I would expect to see it used in examples and random Scheme snippets
from the Net. But they all use display and (newline) if anything.

> I think (error msg) will work in just about any real scheme system.

Well, I think so too, but the fact that it is never mentioned in RnRS or
SRFIs disturbs me. (Actually, I believe exit is in a SRFI, but not a
widely implemented one.)

> Or
> you can
> be really silly and use (eval '() (scheme-report-environment 'a)). I
> don't understand
> why you insist so much on R5RS. Do your C programs restrict themselves
> to standard
> C?

Inasmuch as reasonably possible, yes. Historically, there have been
massive, painful migrations. The good money says there will be others
yet to come. It's certainly not practical to stay within standards for
everything, but where the option exists, I take it. Understanding the
standards also helps me communicate in fora such as this.

>> It is not enough that these features be implementable via
>> call-with-current-continuation or available with a little work. They
>> must be easy to use, well understood, and widely enough known to be in
>> every introductory Scheme book. (Not all books that introduce Scheme
>> are Scheme books, however.)
>
> This is getting ridiculous.

No, just very practical in the situation of promoting the language amid
forces of resistance. I am not the only programmer where I work, nor am
I the only one who maintains my code. I don't want everybody else to
come to me with questions about my language support libraries or why I
never use the functions described in popular references. I don't want to
be writing language support libraries at all. (Not at my job, anyway.)
And if the libraries exist, they should be widely known so that people
learning them can easily find the information they need.

Thanks for the comments.
-John

Dennis Marti

unread,
Jun 8, 2002, 5:11:41 PM6/8/02
to
In article <pan.2002.06.08.1...@john-edwin-tobey.org>,
"John Tobey" <jto...@john-edwin-tobey.org> wrote:

> This is Yet Another Scheme Critique: my thoughts on how to make Scheme
> better for my kinds of programming.

[snip thoughts]

Did you consider Common Lisp? It sounds like that's what you want.

Dennis

(This article was not cross-posted or mailed to anyone.)

John Tobey

unread,
Jun 8, 2002, 5:42:50 PM6/8/02
to
On Sat, 08 Jun 2002 16:28:32 -0400, David Rush wrote:

> "John Tobey" <jto...@john-edwin-tobey.org> writes:
>> I offer this as constructive criticism, not anti-Scheme advocacy.
>
> Just as long as you don't cross-post to c.l.lisp or mail to Erik Naggum,
> you're grand.

OK, I promise I won't. :=)

> Been there. Done that. Bought the T-Shirt. We actually migrated to
> Smalltalk in our company. It's probably the best all-round environment
> for programming I have ever used.

I stand in awe. What do you do for database libraries?

>> Strings are fixed length. C's realloc() and Perl's .= (string
>> mutate-append) operator are really handy.
>
> I commented on this elsewhere. I don;t think you have grasped the Scheme
> way of looking at things if this is a problem for you (And I've been
> doing a *ton* of string-processing over the last 2 years).

It's not a really major complaint, just a rough edge.

apply + string-append = concat, so what? It's too many characters to
type/read. But you're probably right, I haven't found my groove yet.

> Actually, it is an important *engineering* distinction. Mutation of a
> data structure *may* involve rather more operations than the update of a
> single storage location. Thinking otherwise is a bad C habit. And please
> note: I am *not* an academic.

Well, but your IQ is probably higher than the average programmer's. Of
course, I do not claim that Scheme's quirks negate its charms. Lambda,
apply, and let are allocation primitives. Variables denote storage
locations, at least in the sense that pairs do. How a compiler
represents variables and pairs is up to the compiler. I don't think we
are going to persuade each other.

>> No exceptions.
>
> So what? Exceptions are a generally bad intra-program communications
> mechanism. I realize that I hold a fringe opinion on this issue.
>
> Or are you conflating exceptions and error-handling?

Yes, I mean error handling, especially the trapping of errors in primitives.
I agree about "exceptions" being susceptible to abuse. Anyway, Scheme does
somewhat support "exceptions", as I believe you use the term, via
call/cc.

>> Of course, robust applications must be able catch the exceptions that
>> they throw, another area where Scheme lags (as does C).
>
> No Scheme does not lag. With call/cc you can implement any escaping
> control mechanism you care to have. What Scheme doesn't have is
> standardized error-handling. If you don't conflate these issues you'll
> see that the problems are actually a lot smaller than they seem.

> Are there introductory Scheme books that don't explain how to build a


> throw/catch mechanism w/call-with-current-continuation? If there are the
> authors should be shot, they're doing Scheme a great disservice.

Well, I understand call/cc, but it took me a long time to do so. I know
it can be the basis of a more intuitive system, but I see no such system
emerging as even a de facto standard. Perhaps you have a favorite?

Perl's nonlocal returns, by contrast, are easy to understand, although
they have lots of gotchas relating to the use of a global variable.

> I am a Principal Engineer in charge of server technology at a major
> Internet Provider. I make quite a lot of use of Scheme in my day job
> because I can prototype faster in Scheme than in any other language in
> which I have worked. That said, Schem programming requires a significant
> paradigm-shift from a mostly-imperative programming style. I suspect
> that a number of your difficulties arise from this cognitive dissonance.
> Certainly a lot of the people around me gaze on in wonder at when I try
> to explain my code in their terms (C & Perl).

That's exactly what I hope to avoid! Do you write code for others to
maintain? Have you had any luck converting them to the
lexical-functional paradigm, or have you found an adequate supply of
talent in the market?

I appreciate your insights.

By the way, something I really like about Scheme is the ease of whipping
up portable libraries like SRFI-1 and eiod.scm that are (or at least
seem) amenable to later, probably implementation-specific, optimizations.
It would be great if a theorem system existed to guarantee the
equivalence of the optimized version, but I suppose that is beyond the
horizon.

-John

John Tobey

unread,
Jun 8, 2002, 5:48:49 PM6/8/02
to
On Sat, 08 Jun 2002 17:11:41 -0400, Dennis Marti wrote:

> In article <pan.2002.06.08.1...@john-edwin-tobey.org>,
> "John Tobey" <jto...@john-edwin-tobey.org> wrote:
>
>> This is Yet Another Scheme Critique: my thoughts on how to make Scheme
>> better for my kinds of programming.
>
> [snip thoughts]
>
> Did you consider Common Lisp? It sounds like that's what you want.

Maybe so. I haven't delved into Common Lisp yet, and of course Scheme
was quicker to start with. I do not know whether Lisp satisfies certain
practical requirements of my situation, namely (if I am to use it in
stored procedures) compilability to Java classes.

Thanks.

Joe Marshall

unread,
Jun 8, 2002, 5:15:02 PM6/8/02
to
You have to make the distinction between
`Scheme: the R5RS official conforming standard' and
Scheme *implementations*.

R5RS was never intended to be a complete language specification.
It was intended to solve the problem that very simple Scheme
programs didn't run on many implementations. Many times it was
simply that the name of a function differed among scheme
implementations, other times perhaps the arguments were taken
in a different order. These are trivially solvable problems
and it was felt that standardizing these things would benefit
the community without stifling innovation.

Pure R5RS scheme is not useful as deployment/delivery vehicle
for software. It *is* useful as a common denominator for sharing
code fragments and discussing basic scheme issues.

If you are looking for a stable deployment and delivery platform,
you should look at specific implementations and critique each of
them *individually* rather than critiquing only what is guaranteed
to be common amongst all of them.

> No way to run a Scheme program.

On a Mac (at least in the past) you had to double click to run a
program. This is problematic on a machine without a mouse, but
a command line is a problem on a Mac.

> No specified behavior for newlines in strings. Tab characters require
> a literal tab in the source file, making it vulnerable to
> reformatting. I don't understand why R5RS specifies \" and \\ in
> strings but balks at mentioning \n \t #\tab and the rest.

The meaning of newline isn't clear. Does it mean `whatever the standard
convention for line endings are' on the current OS, or does it mean
`ascii 10'? "\n" or "\tab" are names for characters (ascii newline
and ascii tab). What names ought to be canonized?

> Strings are fixed length. C's realloc() and Perl's .= (string
> mutate-append) operator are really handy.
>
> Vectors are fixed length. Again, C wins with realloc() and Perl
> caters to everyday needs with push() pop() shift() unshift() and
> splice().

There are some that believe that fully reallocatable and redirectable
arrays (ala common lisp) are the appropriate user API. Others note
that full generality is virtually never used and can be implemented
on top of the base. No consensus except that everyone agrees that
fixed-length vectors can be implemented on either kind of system.

> set! is not general. I find it inexcusable


> that Scheme requires a different assignment operator for each
> containing structure.

And how would you implement this? A hairy macro? Changes to the
interpreter to allow `eval for lvalue'? First-class `locatives'?
There have been various proposals and all seem to have problems.
Having a different assignment operator for each container is
primitive, but effective, and doesn't prevent a better mechanism
from being developed.

> SLIB tends to smooth out these bumps, but SLIB is not trivial to use,
> and it does not support every Scheme implementation.

True, but do you intend to deploy your software on every Scheme
implementation?

> No easy way to print diagnostics.

Not every Scheme has this, but most have some sort of mechanism.

> but I don't know how to get a stack trace.

Not every Scheme has a stack.

> By my reading of R5RS and SRFI 23, those documents don't
> even guarantee a way to halt execution.

Not every Scheme has a meaning to halting execution! You don't want
portable code halting your processor.

> Scheme is for people who like to prove concepts. While that's a nice
> thing to do, there is more to life outside of academia, and Scheme
> falls short as a general-purpose tool. I hope it will eventually
> spawn or evolve into such a tool.

Have you looked at Common Lisp?

"John Tobey" <jto...@john-edwin-tobey.org> wrote in message
news:pan.2002.06.08.1...@john-edwin-tobey.org...

Feuer

unread,
Jun 8, 2002, 10:53:15 PM6/8/02
to
John Tobey wrote:

> Well, perhaps its a case of my not reading enough, and maybe PLT's 200
> series addresses this, but in a Debian distribution, I found myself
> putting
>
> #!/usr/lib/plt/.bin/i386-linux/mzscheme -r
>
> at the top of my scripts, which seems somehow distasteful. Needless to
> say, the first chapter of any Unix-oriented Perl book describes some of
> the many ways of invoking perl.

This is easily fixed with a symbolic link. This is a silly complaint.

> >> Vectors are fixed length. Again, C wins with realloc() and Perl caters
> >> to everyday needs with push() pop() shift() unshift() and splice().
> >
> > How often do you really need realloc? realloc can only save time if
> > you're
> > lucky. Vectors in Scheme are likely to be implemented efficiently as
> > arrays.
> > To support Perl's vector operations efficiently would require a
> > different implementation, which would be slower for many purposes than
> > Scheme vectors.
> > If you need more flexible vectors, you can write your own using Scheme
> > vectors.
>
> Okay, it's not every day that I use realloc(). But my complaint is not
> about efficiency or the inability to roll my own, it is about limitations
> in the standard, default version. Rarely is efficiency more important
> than simplicity and non-surpisingness among programmers of diverse
> backgrounds.

I don't understand what you're saying... Programmers in most languages
(including off the top of my head C++, Java, Pascal, Haskell, Postscript,
and I certainly assume also Fortran and ML) do not expect to be able to
change the sizes of arrays. realloc in C provides no efficiency guarantees at
all, and
can be somewhat tricky to use correctly.

There are a number of different kinds of resizable arrays, and a number of
different kinds of arrays supporting things like push and pop. For example,
do you want ephemeral or persistent arrays? Do you want arrays with fast
concatenation? Do you need fast cons, snoc, first, and last?
Do you need an array with guaranteed O(1) reads? Or guaranteed
O(ln n) reads and writes? Do you need real-time bounds or will amortized
bounds do?
Certainly it would be nice to have a widely-available library of data
structures for
Scheme (I don't know if such a library exists or not). But to say that Scheme

vectors should be like Perl vectors without understanding the issues involved
in such decisions is foolish.

> Perl's push() and pop() do not necessarily reallocate the array, and
> arrays and strings keep track of their allocated and filled length
> transparently. Of course, fixed length can be implemented more
> efficiently, so it's nice to have available. But in other areas, Scheme
> specifications favor usability over ease of efficient implementation,
> most notably numerics, tail recursion, and garbage collection. It's too

Tail-call optimization is not hard. And Scheme without tail-call optimization

(for at least most tail-calls) is completely useless. Similarly, Scheme
without
GC would be impossibly difficult to use. Scheme numerics can be somewhat
slower (though implementations take pains to optimize the common cases),
but then again Scheme was never designed as a number-crunching system--
it was designed for symbolic manipulation.

> bad that philosophy didn't carry over into Scheme strings and vectors.
> In the same way, it's too bad Perl and C applied it only to
> strings/arrays and not to arithmetic or memory management.

Don't mess with vectors. But strings should definitely be improved. At a
bare
minimum, string->vector and vector->string should be required (though it would

be unreasonable to assume that (string->vector (vector->string s))=s ).

> Then I would expect to see it used in examples and random Scheme snippets
> from the Net. But they all use display and (newline) if anything.

Most random Scheme snippets on the net are written in pretty portable Scheme.
How to access line number info etc. is very impl-dependent, so they won't
include it.
Read the manual for whatever Scheme system you select.

> > I think (error msg) will work in just about any real scheme system.
>
> Well, I think so too, but the fact that it is never mentioned in RnRS or
> SRFIs disturbs me. (Actually, I believe exit is in a SRFI, but not a
> widely implemented one.)

I don't see why that matters. error is not going away any time soon. If
you use it and then switch to a scheme impl that for some bizarre reason
doesn't implement it you can surely do so yourself with whatever it provides.
This is a non-issue.

> Inasmuch as reasonably possible, yes. Historically, there have been
> massive, painful migrations. The good money says there will be others
> yet to come. It's certainly not practical to stay within standards for
> everything, but where the option exists, I take it. Understanding the
> standards also helps me communicate in fora such as this.

Scheme is probably not for you, then... It's not mature enough to be
standardized to that degree (because the community is very conservative,
not because the language is new or bad or anything). You can try Common
Lisp or Standard ML.

> >> It is not enough that these features be implementable via
> >> call-with-current-continuation or available with a little work. They
> >> must be easy to use, well understood, and widely enough known to be in
> >> every introductory Scheme book. (Not all books that introduce Scheme
> >> are Scheme books, however.)
> >
> > This is getting ridiculous.
>
> No, just very practical in the situation of promoting the language amid
> forces of resistance. I am not the only programmer where I work, nor am
> I the only one who maintains my code. I don't want everybody else to
> come to me with questions about my language support libraries or why I
> never use the functions described in popular references. I don't want to
> be writing language support libraries at all. (Not at my job, anyway.)
> And if the libraries exist, they should be widely known so that people
> learning them can easily find the information they need.

I was referring to your claim that they should be in every introductory
Scheme book. Programmers all over the place (including probably
your own company) use a great many C library routines not covered in
introductory C texts. I have never seen an intro C book that covered
signal handling (with sigaction), multithreading, shared memory, file
locking, pipes, sockets, etc., etc. That doesn't mean programmers shouldn't
be expected to be able to understand code using these features: the
ones that don't know already can be expected to learn. It's much easier
to learn the error-handling and exception systems for a Scheme impl than
to figure out how to open a pseudo-terminal in your favorite Unix.

Al Petrofsky

unread,
Jun 9, 2002, 1:27:58 AM6/9/02
to
Feuer <fe...@his.com> writes:

> Don't mess with vectors. But strings should definitely be improved.
> At a bare minimum, string->vector and vector->string should be
> required (though it would be unreasonable to assume that
> (string->vector (vector->string s))=s ).

It seems you think that there's some obvious optimization that a
system could make if it defined these as primitives, but I'm afraid I
don't see it. That's probably because I also don't see why you would
have much occasion to use these. What usage pattern and
implementation technique do you have in mind?

-al

Feuer

unread,
Jun 9, 2002, 2:18:57 AM6/9/02
to
Whether there is an obvious optimization technique is of course
implementation-dependent, which is why such a conversion
function should be provided. It also seems really silly to have
string<->list and list<->vector but not have string<->vector.
Implementation technique with obvious optimizations:
strings are represented as vectors, so string<->vector may be able
to use fast memory copying method or even use copy-on-write.
Of course, that is probably the wrong way to represent strings...

Why would you want to convert between strings and vectors?
I can't think of really good examples, but if the implementation
supports Unicode, you may need to convert a string to a vector to
fiddle it, then switch it back. I can far more easily imagine converting
between strings and vectors than the supported lists and vectors.

Feuer

unread,
Jun 9, 2002, 2:29:25 AM6/9/02
to

Feuer wrote:

> I can far more easily imagine converting

> between strings and vectors than the supported lists and vectors.

ehh... I meant of course between strings and lists.

Al Petrofsky

unread,
Jun 9, 2002, 3:08:49 AM6/9/02
to
Feuer <fe...@his.com> writes:

> Why would you want to convert between strings and vectors?
> I can't think of really good examples, but if the implementation
> supports Unicode, you may need to convert a string to a vector to
> fiddle it, then switch it back.

Unicode presents a whole slew of problems, and simply adding
string/vector conversion functions would not make a dent in addressing
those problems.

> I can far more easily imagine converting between strings and vectors
> than the supported lists and vectors.

A vector of characters is just a wasteful way to represent a string.
A list of characters, however, has some interesting properties
different from a string, such as the shared subsequences you can get
by using cdr, list-tail, and memv, which have no non-allocating
equivalents for strings. Also, there's the O(1) cons for extending a
list. I find it convenient to be able to switch to the list
representation sometimes for these things.

-al

New Scheme

unread,
Jun 9, 2002, 8:05:30 AM6/9/02
to
"John Tobey" <jto...@john-edwin-tobey.org> wrote in message >

> CONCLUSION


> ==========
>
> Scheme is for people who like to prove concepts. While that's a nice
> thing to do, there is more to life outside of academia, and Scheme
> falls short as a general-purpose tool. I hope it will eventually
> spawn or evolve into such a tool.

***************************************************************
Time for a Fresh Scheme Standard
And to Say Goodbye to the RnRS Relic
----------------------------------------------------

Is it time for a new scheme standard? Is it time to make a break from
the ossified RnRS document? Is it time to bring Scheme into the 21st
century?

Scheme has become very dated. The RnRS series of documents are a
relic of a more dynamic past but are now little more than a fossil
record of its ever slowing development. With each year that passes,
scheme becomes more irrelevant to the practical and academic software
development, education and research worlds.

So what should be done? Fix the uncertainties, clear up the undefined
areas. Don't be scared to admit weaknesses and mistakes in the
current standard. Solicit help from the Common Lisp community and
draw upon their extensive practical experience. Learn from the
Functional community and their many strong ideas. And ask the
compiler vendors about practicalities.

Its time for a fresh look at scheme. Its time to break away from the
RnRS and its brotherhood of old men in their isolated,
self-referential world. Its time to reinvigorate the language.

Its time for a new standard.

Scott G. Miller

unread,
Jun 9, 2002, 11:27:01 AM6/9/02
to

Oh well if thats a requirement for you, then you've basically limited
yourself to Kawa or Bigloo, both of which either have extensive
libraries or FFI to Java, which solves many of your complaints about
Scheme right away.

Scott

Benjamin Simon

unread,
Jun 9, 2002, 11:53:56 AM6/9/02
to
>>>>> "JT" == John Tobey <jto...@john-edwin-tobey.org> writes:

JT> This is Yet Another Scheme Critique: my thoughts on how to make Scheme
JT> better for my kinds of programming.
[...reasons to use scheme trimmed...]

JT> WHY NOT SCHEME
JT> ==============
[...reasons to not use scheme trimmed...]

I have gotten this question posted to me quite a few times. It seems to
come down to:

I'd love to use Scheme, but the standard provides no way to do
X. When are they going to update the standard!

where X is something like: file manipulation, exceptions, string
manipulation, threads, xml, etc.

I typically respond by saying that the goal, IMHO, of RnRS scheme is to
provide a very basic, extremely powerful core of a language. After all,
it is one of the few languages that I know of that allows you to add
things like syntax, threads, object orientation and control structures
easily to the language. But, it is only the *core* of the language.
To actually compare Scheme against another language, you really need to
be comparing an implementation of Scheme, not the standard.

For example, it is always going to be an unfair comparison between
coding a project in RnRS Scheme and say Perl. But, change that to scsh
vs perl and you have a very interesting argument -- and one where I
think Scheme can come out on top.

As another example, review the documentation for a Scheme like
DrScheme. Just one look at the reference manual here:
http://download.plt-scheme.org/doc/200alpha19/html/mzscheme/index.htm
And you can't help but think that Scheme is a contender for real life
projects.

If having to choose an actual implementation before you compare
languages makes you feel uncomfortable, then you may want to look at
Common Lisp. With Common Lisp, you can safely compare the standard to a
language like Perl. I think it is also fair to say that Common Lisp has
taken the exact opposite approach to Lisp that Scheme has: Common Lisp is
about providing the industrial strength standard, while Scheme is about
providing the smallest amount of standard to have a very powerful
language (why this is a good thing is a discussion for another time).

JT> CONCLUSION
JT> ==========
JT> Scheme is for people who like to prove concepts. While that's a
JT> nice thing to do, there is more to life outside of academia, and
JT> Scheme falls short as a general-purpose tool. I hope it will
JT> eventually spawn or evolve into such a tool.

Maybe you could make the above claim about RnRS scheme. But most
implementations go far beyond RnRS. Once you start looking at actual
language implementations I think you'll see that the above statement is
no longer true. For example, DrScheme provides features such as:
structures, threads, modules, exceptions, security, regular expressions,
advanced IO, weak boxes, integration with the OS, and many sophisticated
libraries. Those are not the features of a language to "prove
concepts", those are the features of a language to write sophisticated
software in.

-Ben

--
Ben Simon AmazingMedia Inc.
(703) 277-2442 (work) (703) 477-3372 (cell)

Ray Dillinger

unread,
Jun 9, 2002, 4:33:17 PM6/9/02
to
Feuer wrote:


>
> I think (error msg) will work in just about any real scheme system. Or
> you can
> be really silly and use (eval '() (scheme-report-environment 'a)). I
> don't understand
> why you insist so much on R5RS. Do your C programs restrict themselves to
> standard
> C?
>
>
>>It is not enough that these features be implementable via
>>call-with-current-continuation or available with a little work. They
>>must be easy to use, well understood, and widely enough known to be in
>>every introductory Scheme book. (Not all books that introduce Scheme
>>are Scheme books, however.)
>>
>
> This is getting ridiculous.


No, it is not at all ridiculous. R5RS represents a "common language",
one which reaches across many scheme implementations. The minute you
step outside R5RS, you can no longer be sure that the program you're
writing can be used with another compiler or on another platform. If
I write something on a nice compiler that happens to be available for
Linux, and six months later joe blow wants to use my program on Windows,
he's going to have to find another compiler. And he's going to be damned
glad if I stuck to R5RS. R5RS does not make sticking to it easy.

That means that it's extremely important what the language spec says.
What it says makes life harder for implementors. What it does not
say bites the users on the ass every time they turn around.

Remember the Pascal-vs-C religious wars of twenty years or so back?
C was a fscking ridiculous language compared to Pascal. It did not
protect you from anything at all, its syntax was percieved as arcane,
You didn't have any way of limiting scope as every procedure had to
be defined at top level, and on and on and on. But C won, and that's
because the Pascal spec had too many holes in it. Every implementor
extended Pascal in a different direction, and ultimately, despite its
better scope control, more consistent syntax, etc, there just wasn't
a portable standard for Pascal. Every Pascal program depended on
extensions found in just one or two implementations, and the lack of
migratable code effectively doomed it. So people wound up using C,
and kept hanging bags on the side and adding kludges -- to the standard --
to correct its many deficiencies, until it became a better language.

Now, for "Pascal" read "Scheme", and for "C" read "Common Lisp" and
it's happening again. The better language, once again, is less popular
because its standard is underspecified. And this is a pattern. When
people care about langauge design, the standards *do* develop very
slowly. But a standard in an underdeveloped state will kill a language
for use in the general world.

Bear


Ray Dillinger

unread,
Jun 9, 2002, 4:45:16 PM6/9/02
to
John Tobey wrote:


> set! is not general. Sorry Professors, I know there is a linguistic
> difference between bindings and storage locations, but it is an
> annoying and useless distinction in practice. I find it inexcusable
> that Scheme requires a different assignment operator for each
> containing structure. Think macros. Or even think code equals data.
> Scheme is sweeping complexity under the carpet of programmers, to
> paraphrase Larry Wall.


To quote directly from the source of something I am working on:

;;; SRFI-17, Generalized set! -- Bad Idea, will not implement.

Function calls return *VALUES*, not storage locations. To muddy
the distinction is to impede the programmer's ability to understand
the language. Set! is the mutator, and must apply to the thing it
is mutating -- a cons cell, or a vector, or whatever. Applying it
to a value is as semantically meaningless as saying

5=3;

in a C program.


Bear


Ben Goetter

unread,
Jun 9, 2002, 5:00:51 PM6/9/02
to
Quoth John Tobey:

> I don't understand why R5RS specifies \" and \\ in
> strings but balks at mentioning \n \t #\tab and the rest.

Scheme strings are Lisp strings. In Lisp, a backslash within a literal
string simply means that the next literal character appears within the
string. This differs from the C convention, where backslash introduces
an escape sequence encoding some character. Backslashes in Lisp strings
turn off magic; backslashes in C turn on magic.

If you want escape-sequence type behavior, use a procedure (e.g. Lisp
FORMAT) that interprets a string and generated the desired magic.
Defined as a procedure, one can easily extend or redefine the set of
embedded magical sequences. You can't do that if the magic is defined
at the lexical level.

> CONCLUSION

Take a look at Common Lisp. I think you'll like much of what it offers.

Ben Goetter

unread,
Jun 9, 2002, 5:16:59 PM6/9/02
to
Quoth Al Petrofsky:

> A vector of characters is just a wasteful way to represent a string.

A packed uniform vector of character codes, however, can be quite
efficient, especially if you can burn a little code space to be clever
with the packing.

Al Petrofsky

unread,
Jun 9, 2002, 5:47:47 PM6/9/02
to

I thought "a packed uniform vector of character codes" is exactly what
a string is. I don't see why string->vector and vector->string would
be useful.

-al

Feuer

unread,
Jun 9, 2002, 8:45:02 PM6/9/02
to
I don't know quite what you mean about a packed uniform vector
(though I'm guessing you mean a flat array), but there are certainly
a number of other representations that would make sense. Persistent
catenable lists, for example, could be nice for some applications.

Ben Goetter

unread,
Jun 10, 2002, 1:00:34 AM6/10/02
to
Quoth Al Petrofsky:

> I thought "a packed uniform vector of character codes" is exactly what
> a string is.

A string is a sequence of characters with a particular external literal
representation.

> I don't see why string->vector and vector->string would
> be useful.

Neither do I. u{8,16,32}vector->string, however, is useful if you're
performing I/O.

David Rush

unread,
Jun 10, 2002, 4:27:06 AM6/10/02
to
"John Tobey" <jto...@john-edwin-tobey.org> writes:
> On Sat, 08 Jun 2002 16:28:32 -0400, David Rush wrote:
> > Been there. Done that. Bought the T-Shirt. We actually migrated to
> > Smalltalk in our company. It's probably the best all-round environment
> > for programming I have ever used.
>
> I stand in awe. What do you do for database libraries?

At the time we were able to get bolt-on packages for interface to DB/2
and Sybase. Now virtually every commercial vendor supports ODBC. We
did need to roll-our-own object<->relational mapping layer, but it
wasn't that hard. (Actually, there were two versions...the hard to
write one kept glomming features from the easy to write one)

> > Actually, it is an important *engineering* distinction. Mutation of a
> > data structure *may* involve rather more operations than the update of a
> > single storage location. Thinking otherwise is a bad C habit. And please
> > note: I am *not* an academic.
>
> Well, but your IQ is probably higher than the average programmer's.

Flattery will get you nowhere. Around c.l.s I am an (opinionated)
lightweight.

> (re: generalized set!) I don't think we


> are going to persuade each other.

Probably not. However, have you considered the effect that data
structure mutation has lazy-initialization and derived object
attribute issues?

> > Are there introductory Scheme books that don't explain how to build a
> > throw/catch mechanism w/call-with-current-continuation? If there are the
> > authors should be shot, they're doing Scheme a great disservice.
>
> Well, I understand call/cc, but it took me a long time to do so. I know
> it can be the basis of a more intuitive system, but I see no such system
> emerging as even a de facto standard. Perhaps you have a favorite?

I had to make friends with this kind of usage of call/cc early on,
since Scheme doesn't even have a standardized exit function
(absolutely apalling, that one).

(define *k-exit* '())
(define (exit n) (*k-exit* n))

(define (main arg-list)
(call/cc
(lambda (k-exit)
(set! *k-exit* k-exit)
(begin
; your code here
(exit 0)
))))

(main (vector->list (argv)))

This is so simple that I don't think that anyone considers it worth
the time to standardize/library/macrologize it. FWIW, there are more
than a few people who think that some sort of explicit exception
system (much more general than exit magic I implemented above) needs
to be built, there's just not much agreement on how it should work
yet, probably because (IMO) the way you want it to work depends a
*lot* on your apllication domain.

> > Certainly a lot of the people around me gaze on in wonder at when I try
> > to explain my code in their terms (C & Perl).
>
> That's exactly what I hope to avoid! Do you write code for others to
> maintain?

Unfortunately not in Scheme, yet. See below for reasons.

> Have you had any luck converting them to the
> lexical-functional paradigm

No. AFAICT the quality of CS grads (or possibly there are too many
people getting hired as programmers in Ireland w/less than full CS
degrees) is declining. There are far too few people who understand
that there *is* a theoretical basis to computing; that there are
better paradigms of code re-use than cut-and-paste; that the fixed
amount of work theorem cannot be violated; ... <RANT>

> , or have you found an adequate supply of
> talent in the market?

No. C and it's derivatives rule the market. This is also one of the
reasons why my old company abandoned Smalltalk, too. From a corporate
POV the tradeoffs between programmer productivity and programmer
availability are not as clear as they are from an engineering
POV. This is one of the reasons I keep thinking I need to go into
management...

david rush
--
Compile-time is when *you* find the bug, run-time is when the
*customer* finds it.
-- Joe Marshall (on comp.lang.scheme)

David Rush

unread,
Jun 10, 2002, 4:34:17 AM6/10/02
to
Feuer <fe...@his.com> writes:
> John Tobey wrote:
> > > I think (error msg) will work in just about any real scheme system.
> >
> > Well, I think so too, but the fact that it is never mentioned in RnRS or
> > SRFIs disturbs me. (Actually, I believe exit is in a SRFI, but not a
> > widely implemented one.)
>
> I don't see why that matters. error is not going away any time soon. If
> you use it and then switch to a scheme impl that for some bizarre reason
> doesn't implement it you can surely do so yourself with whatever it provides.
> This is a non-issue.

It is an annoyance. SLIB does it differently from Bigloo, losing
information in the reporting of errors. For myself I use a complete
roll-my-own system based on an FFI implementation of exit().

david rush
--
MERE ACCUMULATION OF OBSERVATIONAL EVIDENCE IS NOT PROOF
-- Death, in _Hogfather_

David Rush

unread,
Jun 10, 2002, 4:42:30 AM6/10/02
to
news...@hotmail.com (New Scheme) writes:
> Time for a Fresh Scheme Standard
> And to Say Goodbye to the RnRS Relic

It's amazing really. My .sigmonster cam up with an apropriate reply
before I even started to type.

david rush
--
Get a job, goofy-tooth.
-- P. J. O'Rourke

Ray Dillinger

unread,
Jun 10, 2002, 11:34:40 AM6/10/02
to
Al Petrofsky wrote:


People who want these operations assume that the compiler or scheme
system isn't smart enough to produce immediate-representation vectors
(as opposed to more general pointer vectors) where possible, and thus
presume that uniform numeric vectors or strings are going to have more
efficient vector operations than ordinary vectors.

Bear

George Caswell

unread,
Jun 10, 2002, 11:39:02 AM6/10/02
to
On 9 Jun 2002, New Scheme wrote:

> Is it time for a new scheme standard? Is it time to make a break from
> the ossified RnRS document? Is it time to bring Scheme into the 21st
> century?
>

That's a loaded question.

> Its time for a fresh look at scheme. Its time to break away from the
> RnRS and its brotherhood of old men in their isolated,
> self-referential world. Its time to reinvigorate the language.
>

I'm suddenly reminded of that candidate for governor from "O Brother, Where
Art Thou?", who said, "Back to the flour mill, Pappy!" I am not familiar with
the brotherhood of old men to whom you refer.

I don't believe you actually addressed the issue of what you think is wrong
with Scheme - only that something is wrong with it and that you think it
should change.

I think the important question is, what is needed from Scheme? What should
Scheme be?

To me Scheme is a very nice language for experimentation. The interactive
environment makes working with code and data relatively easy without requiring
me to develop extensive interfacing code, and the data model supports
representation of various data types in sensible ways. Best of all, thanks to
the excellent work by Fred Bayer and others on LispMe, I've always got a
Scheme interpreter handy. The Scheme REPL is also my preferred method of
working with C code interactively (though binding C code to Scheme generally
isn't fun). I was very interested in Guile for a while, as a means of shell
scripting, program extension/scripting/configuration, etc., but these days I'm
not sure Guile (or even Scheme) are appropriate for that stuff.

Scheme isn't perfect, of course. Personally I'm sometimes bothered by the
fact that Scheme doesn't provide much support for modularizing (important for
scaling to larger projects), or for semantically-equivalent user-defined
datatypes ("length" wouldn't work on a user-defined sequence type). But
everyone has their own needs and their own interests - and if you have a good
idea for Scheme, implement it, learn the strengths and weaknesses of your
idea, and maybe if you can prove the merit of your idea you can get it
included in Scheme, either as part of RxRS or as an SRFI. If not, well,
there's room for a lot of different programming languages in the world, and it
seems to me as though operating environments are moving toward a state where
integration between different languages will be strongly encouraged.

---GEC
New projects page: http://home.attbi.com/~sieg_haro/
(M-x depeche-mode)
"Must... Finish... Zaku..."

George Caswell

unread,
Jun 10, 2002, 12:22:47 PM6/10/02
to
On Sat, 8 Jun 2002, Joe Marshall wrote:

> > Strings are fixed length. C's realloc() and Perl's .= (string
> > mutate-append) operator are really handy.
> >
> > Vectors are fixed length. Again, C wins with realloc() and Perl
> > caters to everyday needs with push() pop() shift() unshift() and
> > splice().
>
> There are some that believe that fully reallocatable and redirectable
> arrays (ala common lisp) are the appropriate user API. Others note

I realize that asking this instead of researching it myself is very lazy,
but could you please give me a description of the concept?

> > set! is not general. I find it inexcusable
> > that Scheme requires a different assignment operator for each
> > containing structure.
>
> And how would you implement this? A hairy macro? Changes to the
> interpreter to allow `eval for lvalue'? First-class `locatives'?
> There have been various proposals and all seem to have problems.
> Having a different assignment operator for each container is
> primitive, but effective, and doesn't prevent a better mechanism
> from being developed.
>

From my perspective this is one specific instance of a more general problem
in Scheme with regard to different kinds of scalability: that distinctions in
behavior cannot be (easily) decentralized without altering the semantics of
what you're trying to do. It's a naming problem, as much as anything - C++
addresses the problem with overloading (resolving multiple instances of a name
at compile-time) and with different kinds of name spaces ("namespaces" and
"classes"). The problem with Scheme is that if you want to implement method
"A" for datatypes X, Y, and Z, either a single implementation of "A" must be
written which recognizes all three datatypes, or the name "A" must be provided
somehow within the context of datatypes X, Y, and Z to work more or less like
an OO method (which is possible in Scheme, but not well-supported).

From my understanding of C# and Python both use an approach which is fairly
appealing to me: assignments to domain-specific "values" are semantically
translated: a[b] = x becomes a[b].set(x), and both languages provide very
straightforward mechanisms for making a[b] usable both as an lvalue or rvalue
with C-like semantics. (C++, on the other hand, requires either that a[b]
return a reference, or an object which acts like a reference) I don't know if
this approach would really fit Scheme's overall design, though.

(I am generally interested in learning about computer languages that can
provide me with new insight into various problems about language design. I
think Common Lisp may be my next study. Any other recommendations are
appreciated)

George Caswell

unread,
Jun 10, 2002, 12:34:53 PM6/10/02
to
On 9 Jun 2002, Al Petrofsky wrote:

> Feuer <fe...@his.com> writes:
>
> > Why would you want to convert between strings and vectors?
> > I can't think of really good examples, but if the implementation
> > supports Unicode, you may need to convert a string to a vector to
> > fiddle it, then switch it back.
>
> Unicode presents a whole slew of problems, and simply adding
> string/vector conversion functions would not make a dent in addressing
> those problems.
>

I know of the variable-character-size in the 8-bit representation of
Unicode (and with character set extensions, I suppose it probably exists in
the 16 bit representation as well) - could you explain to me what other
Unicode-related problems warrant consideration?

> A vector of characters is just a wasteful way to represent a string.

My feeling on the subject is that many of the string operations are exactly
the same as the corresponding vector operations, except that they are made
artificially distinct from vector operations by the more-or-less necessary
naming differences. I thought this might be a problem until I realized there
aren't a whole lot of algorithms generalized for vectors that I would want to
apply to characters within a string.

George Caswell

unread,
Jun 10, 2002, 4:46:43 PM6/10/02
to

> > Vectors are fixed length. Again, C wins with realloc() and Perl
> > caters to everyday needs with push() pop() shift() unshift() and
> > splice().
>
> How often do you really need realloc? realloc can only save time if
> you're
> lucky. Vectors in Scheme are likely to be implemented efficiently as
> arrays.

Vectors, in my experience, are almost invariably used in roles in which
they're expected to be mutable: from that perspective it doesn't make a lot of
sense to me that the system would support changing all aspects of a vector
apart from its size. At the very least being able to efficiently copy vector
elements to a larger vector would simplify efficient implementation of
programs for which resizable vectors would be the natural approach. However,
simply being able to resize the vector would bypass the need to clutter my
vector-using code with nonsense.

Actually the only time this has been a problem for me personally was when I
was implementing Heap-based priority queues in Scheme as an excercise.

> If you need more flexible vectors, you can write your own using Scheme
> vectors.
>

What would be your approach to such a problem? We can even assume that
vector-ref needn't work in constant time.

Thien-Thi Nguyen

unread,
Jun 10, 2002, 5:20:39 PM6/10/02
to
George Caswell <sieg...@attbi.com> writes:

> I was very interested in Guile for a while, as a means of shell scripting,
> program extension/scripting/configuration, etc., but these days I'm not sure
> Guile (or even Scheme) are appropriate for that stuff.

guile lost its POV; "extension" has two endpoints and guile got confused about
which one it wanted to support well (first) and how to go about that. perhaps
things will improve.

thi

Feuer

unread,
Jun 11, 2002, 12:56:36 AM6/11/02
to
Joe Marshall wrote:
>And how would you implement this? A hairy macro? Changes to the

> interpreter to allow `eval for lvalue'? First-class `locatives'?
> There have been various proposals and all seem to have problems.
> Having a different assignment operator for each container is
> primitive, but effective, and doesn't prevent a better mechanism
> from being developed.

Couldn't this be done with some kind of pattern-matching syntax?
Something like
(define mod (lst)
(set-pat! lst (cons a (cons b _)) 3 4))
where this would take a list, change the first element to 3, and change the
second element to 4.
I'm not proposing this exact syntax, but the general idea. (I also don't
know if this has already
been done).

Ray Dillinger

unread,
Jun 11, 2002, 12:57:05 AM6/11/02
to
George Caswell wrote:

>>>Vectors are fixed length. Again, C wins with realloc() and Perl
>>>caters to everyday needs with push() pop() shift() unshift() and
>>>splice().
>>>
>>How often do you really need realloc? realloc can only save time if
>>you're
>>lucky. Vectors in Scheme are likely to be implemented efficiently as
>>arrays.
>>
>
> Vectors, in my experience, are almost invariably used in roles in which
> they're expected to be mutable: from that perspective it doesn't make a lot of
> sense to me that the system would support changing all aspects of a vector
> apart from its size.


This is weird. I use vectors daily, and almost always use them
in linear-update style. MITScheme does a CPS tranform, so it
figures out that it can reuse the space for the new value and
make an efficient single (or double) update on it just fine.
Also I usually pass vectors as parameters and return them as
values, with the full expectation that their values will be
restored if I need to reinvoke the continuation. I barely ever
use vector-set! in real life.

As an example of how I usually use vectors, a lexer I built
recently has a lot of expressions like this:

;;; PSO is the parse-state object. nextchar is a reference to
;;; the character PSO is looking at, bound by a let clause.

(lexnum(acceptchar(set-first-expt(requiredigit PSO) nextchar)))

where lexnum is the recursive call that accepts a parse-state object,
acceptchar takes a parse-state object and returns a new parse-state
object that is looking one character further into input (or returns
#f if there is no more input), set-first-expt takes a parse-state object
and a character and returns a parse-state object which is similar but
has the exponent of the real (or magnitude) part of the number being
parsed set according to the character, and requiredigit takes a parse-
state object and returns the same parse-state object if the character
under consideration is a digit, or #f if it's not.

The basic design pattern is that the parse-state object is either a
vector containing all kinds of stuff about the parse, or the value #f.
If any of these gets #f for a parse-state object, it returns #f. This
allows backtracking parses just by using an or statement.

And five times out of six, assuming you do six things in an average
clause, it's pure linear-update where the continuation eats the last
reference to the new value, so the compiler can figure out that it
gets to use efficient single-cell vector updates just by transforming
to CPS and I don't have to worry about keeping track of the state
of "the" vector or restoring it if I need to backtrack.

The only project I remember where I actually implemented and used
resizable vectors was for a hash-table datatype that resized the
table if it got too big. Actually I was building Directed Graphs,
with a lot of branching, and there was a hash table at each node
to map inputs to the next state reachable by that input. Both the
hash tables and the DG states were function closures, with the
actual values of the hash table stored as vectors in their own scope,
so nobody using them ever saw a vector anyway.

They just had function calls like

;; stores the function returned by (DGstate 'Read12) in the table
;; for this state, with a link by the string "A" to it.
((table 'addlink!) "A" (DGstate 'Read12))

((table 'lookup) "A") ;; returns a link from the hash table
((table 'clearlink!) "A") ;; clears a link from the hash table
(table 'clear) ;; clears the hash table.


Bear


Shiro Kawai

unread,
Jun 11, 2002, 1:17:45 AM6/11/02
to
Handling strings can be very tricky. I write Scheme code
every day thatt process strings, and from my point of view,
the nature of string is very different from the vector's.

George Caswell <sieg...@attbi.com> wrote in message news:<Pine.LNX.3.96.102061...@adamant.attbi.com>...


> On 9 Jun 2002, Al Petrofsky wrote:
> > Unicode presents a whole slew of problems, and simply adding
> > string/vector conversion functions would not make a dent in addressing
> > those problems.
> >
> I know of the variable-character-size in the 8-bit representation of
> Unicode (and with character set extensions, I suppose it probably exists in
> the 16 bit representation as well) - could you explain to me what other
> Unicode-related problems warrant consideration?

Even if you use 31-bit representation, you can't avoid
processing variable-length characters; consider all those
combining characters.

For example, suppose I have a text written in JIS X 0213:2000,
and it contains a character 0x2477 (hiragana letter ka with
semi-voice mark). It doesn't have a corresponding character
in Unicode 3.2, so I need to use a Unicode combining character -
U+304B (hiragana letter ka), followed by
U+309A (combining katakana-hiragana semi-voiced sound mark).
Those two text should be the same except its encodings,
but naive Unicode representation counts the number of
characters differently.

I don't intend to start pro-Unicode vs con-Unicode debate
here. I think this is not a Unicode problem, but more
inherent problem within character/string handling.
The meaning of a character depends on its surrounding
context.

Consequently, I observe almost all meaningful text processing
deal with strings in either sequentially, or by using
some search primitives (substring search or regexp or
whatever). When you want to access string by indices,
usually those indices are obtained by some search operation.
It seems very different, at least for me, from the access
pattern of vectors, in which the indices usually have their
own meanings.

BTW, sequential string access can be handled efficiently by
string ports. It's in SRFI, and I think it is fairly portable
accross various Scheme implementations.

David Rush

unread,
Jun 11, 2002, 4:00:49 AM6/11/02
to
George Caswell <sieg...@attbi.com> writes:
> On Sat, 8 Jun 2002, Joe Marshall wrote:
> The problem with Scheme is that if you want to implement method
> "A" for datatypes X, Y, and Z, either a single implementation of "A" must be
> written which recognizes all three datatypes, or the name "A" must be provided
> somehow within the context of datatypes X, Y, and Z to work more or less like
> an OO method (which is possible in Scheme, but not well-supported).
...

> (I am generally interested in learning about computer languages that can
> provide me with new insight into various problems about language design. I
> think Common Lisp may be my next study. Any other recommendations are
> appreciated)

You really owe it to yourself to learn SML, but it takes a
while to make the paradigm shift from OO thinking to its functorial
approach. I think it's a better way of getting the re-use benefits
that OO strives to achieve. Of course, once you understand SML's
approach, implementing it in Scheme is a doddle. (I don't advocate
learning it in Scheme becaue SML has a lot of syntax and compiler
support to help you realize exactly what you're doing...)

david rush
--
Lambda calculus -- Call us a mad club.
-- James A Crippen (on comp.lang.scheme)

George Caswell

unread,
Jun 11, 2002, 12:41:21 PM6/11/02
to
On 10 Jun 2002, Shiro Kawai wrote:

> For example, suppose I have a text written in JIS X 0213:2000,
> and it contains a character 0x2477 (hiragana letter ka with
> semi-voice mark). It doesn't have a corresponding character
> in Unicode 3.2, so I need to use a Unicode combining character -
> U+304B (hiragana letter ka), followed by
> U+309A (combining katakana-hiragana semi-voiced sound mark).
> Those two text should be the same except its encodings,
> but naive Unicode representation counts the number of
> characters differently.
>

Wow, very enlightening. Thank you.

(Unfortunately I can't seem to remember a kana symbol described as
"semi-voice mark" - which symbol is that?)

> I don't intend to start pro-Unicode vs con-Unicode debate
> here. I think this is not a Unicode problem, but more
> inherent problem within character/string handling.
> The meaning of a character depends on its surrounding
> context.
>

Certainly relevant information w.r.t. my question, in any case.

> Consequently, I observe almost all meaningful text processing
> deal with strings in either sequentially, or by using
> some search primitives (substring search or regexp or
> whatever). When you want to access string by indices,
> usually those indices are obtained by some search operation.
> It seems very different, at least for me, from the access
> pattern of vectors, in which the indices usually have their
> own meanings.
>

I can certainly see your point there. I think my comment on vector/string
operations being the same was meaningful within the current Scheme string
model - the operations being performed and the functions used to do them are
very similar because the vector/string implementations are very similar - but
there's that artificial distinction introduced because of the way Scheme
handles names.

Ray Dillinger

unread,
Jun 11, 2002, 1:05:09 PM6/11/02
to

Why the hell wouldn't an optimizing compiler represent a vector of
characters as a packed uniform vector of character codes? This
sounds like you want to cruft up the language just because you're
assuming your compiler is stupid and won't optimize representations
otherwise.

Let's not clutter up the language with this stuff. The language
is for us to say what we mean to get done, not to specify on the
bits-and-bytes level how to do it. If you want to worry about
data representation bits-and-bytes, use assembly or C.

At the very most, use an XOF (explicit optimization form) that
wraps your normal vector operations; That way you can just define
the syntax as null on a system that doesn't support it and the
program will work anyway.

Bear

Feuer

unread,
Jun 11, 2002, 1:46:00 PM6/11/02
to

George Caswell wrote:

> > If you need more flexible vectors, you can write your own using Scheme
> > vectors.
>
> What would be your approach to such a problem? We can even assume that
> vector-ref needn't work in constant time.

I'm not sure what you're asking for here. There are a lot of different
vector-like
data structures out there. You can write any of them in Scheme. That's all I'm
saying. If you want vectors that can change size, you can use a boring copying
scheme
with scheme vectors. If you want vectors with O(1) cons, snoc, head, and last,
you
can do that too (getting O(lg n) vector-ref). The OP was proposing adding some
sort of flexible vector to the language; I was saying such belong in libraries.

George Caswell

unread,
Jun 11, 2002, 5:12:25 PM6/11/02
to
On Tue, 11 Jun 2002, Feuer wrote:

> George Caswell wrote:
>
> > > If you need more flexible vectors, you can write your own using Scheme
> > > vectors.
> >
> > What would be your approach to such a problem? We can even assume that
> > vector-ref needn't work in constant time.
>
> I'm not sure what you're asking for here. There are a lot of different

It seems like you're saying the answer to this question (of Scheme vectors
which, among other things, would be resizable) is trivial and obvious. If
that is the case then I'd like you to describe a solution.

In particular, I'm interested in resizable vectors, because I've been
frustrated in the past by their absence in Scheme and the implementation of a
resizable vector in Scheme does not seem obvious.

> vector-like
> data structures out there. You can write any of them in Scheme. That's all I'm
> saying. If you want vectors that can change size, you can use a boring copying
> scheme

That works, of course, but since Scheme doesn't provide a vector-copy
operation, the copying loop is interpreted code.

> with scheme vectors. If you want vectors with O(1) cons, snoc, head, and last,
> you
> can do that too (getting O(lg n) vector-ref). The OP was proposing adding some
> sort of flexible vector to the language; I was saying such belong in libraries.
>

I think resizing is a simple enough operation to support, and useful enough
for a container that it's worth implementing. Most importantly, its presence
(unlike other features which you've grouped under the notion of "flexible
vectors", like list/deque functionality) does not negatively affect other uses
of vectors...

Well, that's not quite true, I suppose. If a resize requires a relocation,
then making a vector's length a mutable part of its value means that the
actual location of the vector needs to be hidden behind a handle somewhere, so
that multiple references to a vector that's been resized will still be valid.
Of course, that's exactly how vectors are stored in LispMe already.

Maybe a vector-copy would be the better general solution, then:
implementations which store vector references as memory locations (rather than
some kind of handles to memory locations) won't need an extra level of
indirection to support resizing of vectors, and programmers who want to resize
a vector, or create a (larger) vector which includes values from another
vector will have an efficient way to do so within the boundaries of the
language.

On a side note, if I were to solve certain of these problems by
implementing a container type in Scheme, I think I would be frustrated by the
lack of facilities for integrating the new type into the Scheme environment:
no way to make the type identifiably distinct from any other program-defined
datatype, evaluating instances of the data type in the REPL would display the
data's implementational representation, not its most reasonable
interpretation, etc. If I defined a vector-like datatype, in the context of
Scheme data that datatype would have a very obvious (textual) representation:
a sequence, formatted similarly to (but distinct from) lists and vectors. For
that matter, it's not unreasonable to expect that code written to process
sequences would work with such a container (which has such a well-defined
sequential meaning) without modification. But I think I'd rather explore
those ideas in another language than suggest that Scheme should include them.

You've made a number of good points, thank you for your time and insight.

Thomas Bushnell, BSG

unread,
Jun 11, 2002, 5:42:05 PM6/11/02
to
George Caswell <sieg...@attbi.com> writes:

> In particular, I'm interested in resizable vectors, because I've been
> frustrated in the past by their absence in Scheme and the implementation of a
> resizable vector in Scheme does not seem obvious.

Why? I can't see any reason why it should be harder in Scheme than in
any other language.

Scott G. Miller

unread,
Jun 11, 2002, 5:58:22 PM6/11/02
to

The only hangup is that you can't resize a vector in place. You may
replace one vector with another in any datastructure you please. If you
can live with that, then the implementation is trivial (but O(n)):

(define (resize-vector v n)
(do ((new-vector (make-vector n) new-vector)
(i 0 (+ i 1)))
((or (= i (vector-length v))
(= i n)) new-vector
(vector-set! new-vector i (vector-ref v i))))

Scott G. Miller

unread,
Jun 11, 2002, 5:59:47 PM6/11/02
to
Scott G. Miller wrote:
> The only hangup is that you can't resize a vector in place. You may
> replace one vector with another in any datastructure you please. If you
> can live with that, then the implementation is trivial (but O(n)):
>

Well, maybe not so trivial, I left a paren out:

(define (resize-vector v n)
(do ((new-vector (make-vector n) new-vector)
(i 0 (+ i 1)))
((or (= i (vector-length v))

(= i n)) new-vector)

Thomas Bushnell, BSG

unread,
Jun 11, 2002, 6:49:54 PM6/11/02
to
"Scott G. Miller" <scgm...@freenetproject.org> writes:

> Thomas Bushnell, BSG wrote:
> > George Caswell <sieg...@attbi.com> writes:
> >
> >> In particular, I'm interested in resizable vectors, because I've been
> >>frustrated in the past by their absence in Scheme and the implementation of a
> >>resizable vector in Scheme does not seem obvious.
> > Why? I can't see any reason why it should be harder in Scheme than
> > in
> > any other language.
> >
>
> The only hangup is that you can't resize a vector in place.

Hrm. You aren't trying hard! What about representing a resizable
vector thus:

((vector . size))

Then we get:

(define (resize-vector v n)
(let ((real-vector (caar v))
(real-size (cdar v))
(new-vector (make-vector n)))
(.... initialize new-vector ...)
(set-car! v
(cons (new-vector n)))))


Thomas

Feuer

unread,
Jun 11, 2002, 7:12:07 PM6/11/02
to

George Caswell wrote:

> It seems like you're saying the answer to this question (of Scheme vectors
> which, among other things, would be resizable) is trivial and obvious. If
> that is the case then I'd like you to describe a solution.

Not trivial. Not obvious. Just doable.

> In particular, I'm interested in resizable vectors, because I've been
> frustrated in the past by their absence in Scheme and the implementation of a
> resizable vector in Scheme does not seem obvious.

Shouldn't be _that_ hard, though with R5RS you don't have any ADT guarantees
(at least without jumping through hoops).

> > vector-like
> > data structures out there. You can write any of them in Scheme. That's all I'm
> > saying. If you want vectors that can change size, you can use a boring copying
> > scheme
>
> That works, of course, but since Scheme doesn't provide a vector-copy
> operation, the copying loop is interpreted code.

Yes.

> > with scheme vectors. If you want vectors with O(1) cons, snoc, head, and last,
> > you
> > can do that too (getting O(lg n) vector-ref). The OP was proposing adding some
> > sort of flexible vector to the language; I was saying such belong in libraries.
> >
> I think resizing is a simple enough operation to support, and useful enough
> for a container that it's worth implementing. Most importantly, its presence
> (unlike other features which you've grouped under the notion of "flexible
> vectors", like list/deque functionality) does not negatively affect other uses
> of vectors...

> Well, that's not quite true, I suppose. If a resize requires a relocation,
> then making a vector's length a mutable part of its value means that the
> actual location of the vector needs to be hidden behind a handle somewhere, so
> that multiple references to a vector that's been resized will still be valid.
> Of course, that's exactly how vectors are stored in LispMe already.
>
> Maybe a vector-copy would be the better general solution, then:
> implementations which store vector references as memory locations (rather than
> some kind of handles to memory locations) won't need an extra level of
> indirection to support resizing of vectors, and programmers who want to resize
> a vector, or create a (larger) vector which includes values from another
> vector will have an efficient way to do so within the boundaries of the
> language.

Sure.

> On a side note, if I were to solve certain of these problems by
> implementing a container type in Scheme, I think I would be frustrated by the
> lack of facilities for integrating the new type into the Scheme environment:
> no way to make the type identifiably distinct from any other program-defined
> datatype, evaluating instances of the data type in the REPL would display the
> data's implementational representation, not its most reasonable
> interpretation, etc. If I defined a vector-like datatype, in the context of
> Scheme data that datatype would have a very obvious (textual) representation:
> a sequence, formatted similarly to (but distinct from) lists and vectors. For
> that matter, it's not unreasonable to expect that code written to process
> sequences would work with such a container (which has such a well-defined
> sequential meaning) without modification. But I think I'd rather explore
> those ideas in another language than suggest that Scheme should include them.

That is true. There are probably implementations supporting this sort of thing...

> You've made a number of good points, thank you for your time and insight.

Nothing special...

Jordan M. Johnson

unread,
Jun 11, 2002, 7:19:27 PM6/11/02
to
Thomas Bushnell, BSG <tb+u...@becket.net> wrote:
>Hrm. You aren't trying hard! What about representing a resizable
>vector thus:
>
>((vector . size))

I don't think you gain anything by storing the size, since it's already
accessible through vector-length.

Or are you suggesting it should be boxed and/or hidden behind an interface?
That could be added easily on top of Scott's code.

jmj

Thomas Bushnell, BSG

unread,
Jun 11, 2002, 7:33:55 PM6/11/02
to

Storing the size is not an important idea. My point is that boxing
solves the "problem" that Scott thought there was.

Scott G. Miller

unread,
Jun 11, 2002, 7:50:50 PM6/11/02
to
Thomas Bushnell, BSG wrote:
>
> Hrm. You aren't trying hard! What about representing a resizable
> vector thus:
>
> ((vector . size))
>
> Then we get:
>
> (define (resize-vector v n)
> (let ((real-vector (caar v))
> (real-size (cdar v))
> (new-vector (make-vector n)))
> (.... initialize new-vector ...)
> (set-car! v
> (cons (new-vector n)))))
>
>
Of course. I merely meant that you can't resize a pure Scheme vector in
place, which is the poster's argument in the first place.

Scott

Thomas Bushnell, BSG

unread,
Jun 11, 2002, 7:58:18 PM6/11/02
to
"Scott G. Miller" <scgm...@freenetproject.org> writes:

> Of course. I merely meant that you can't resize a pure Scheme vector
> in place, which is the poster's argument in the first place.

Um, ok. You said that you couldn't see how to implement resizable
vectors, which I took to be a different question.

Two things to note: if you want "ordinary vectors" to be resizable,
you can define resizable vectors, and then set! the names of the
standard procedures to your augmented ones. So if the objection is
that you want the "standard vector" type to support a resize
operation, you can indeed get it this way, since that type is defined
purely in terms of its procedural interface.

Second, and more important, in the terms now given, most programming
languages do not have resizable vectors; for example, neither C,
Pascal, nor Fortran do.

The original complaint said "Strings are fixed length. C's realloc
... [is] really handy."

But C's realloc does *not* resize memory regions in place, rather, it
returns a pointer to a new region, and copies as necessary.

Thomas

Scott G. Miller

unread,
Jun 11, 2002, 8:03:58 PM6/11/02
to
Thomas Bushnell, BSG wrote:
> "Scott G. Miller" <scgm...@freenetproject.org> writes:
>
>
>>Of course. I merely meant that you can't resize a pure Scheme vector
>>in place, which is the poster's argument in the first place.
>
>
> Um, ok. You said that you couldn't see how to implement resizable
> vectors, which I took to be a different question.
>
Oh no. Thats why I said:

"You may replace one vector with another in any datastructure you please."

...implying that boxing or sticking a vector in a cons cell would let
you pass around a structure in which you could replace the vector.


> Two things to note: if you want "ordinary vectors" to be resizable,
> you can define resizable vectors, and then set! the names of the
> standard procedures to your augmented ones. So if the objection is
> that you want the "standard vector" type to support a resize
> operation, you can indeed get it this way, since that type is defined
> purely in terms of its procedural interface.

Excellent point.


>
> Second, and more important, in the terms now given, most programming
> languages do not have resizable vectors; for example, neither C,
> Pascal, nor Fortran do.
>
> The original complaint said "Strings are fixed length. C's realloc
> ... [is] really handy."
>
> But C's realloc does *not* resize memory regions in place, rather, it
> returns a pointer to a new region, and copies as necessary.

True. I'm definitely of the opinion that this is probably an
unnecessary requirement of the poster, possibly brought about by a lack
of knowledge as to how resizing/realloc actually occurs in other
languages (i.e. not very efficiently).

Scott

Boris Smilga

unread,
Jun 11, 2002, 8:06:49 PM6/11/02
to
George Caswell <sieg...@attbi.com> writes:

> On 10 Jun 2002, Shiro Kawai wrote:

> > For example, suppose I have a text written in JIS X 0213:2000,
> > and it contains a character 0x2477 (hiragana letter ka with
> > semi-voice mark). It doesn't have a corresponding character
> > in Unicode 3.2, so I need to use a Unicode combining character -
> > U+304B (hiragana letter ka), followed by
> > U+309A (combining katakana-hiragana semi-voiced sound mark).

> (Unfortunately I can't seem to remember a kana symbol described as


> "semi-voice mark" - which symbol is that?)

I guess, it's the hannigori mark, which looks like a small circle
drawn above and to the right of a kana character (see the relevant
Unicode charts). But I thought they were only being used with h-/f-
syllables (changing the initial to [p]), not with k- syllables. What
would a ka + hannigori sound like, Shiro-san?

Yours,
B.Smilga.

George Caswell

unread,
Jun 11, 2002, 8:37:21 PM6/11/02
to
On 11 Jun 2002, Thomas Bushnell, BSG wrote:

> Two things to note: if you want "ordinary vectors" to be resizable,
> you can define resizable vectors, and then set! the names of the
> standard procedures to your augmented ones. So if the objection is
> that you want the "standard vector" type to support a resize
> operation, you can indeed get it this way, since that type is defined
> purely in terms of its procedural interface.
>

And its syntax: A function may include vectors specified by their
syntactic constructor #(). Not a show-stopper but certainly a pain if you're
thinking of actually doing this.

> Second, and more important, in the terms now given, most programming
> languages do not have resizable vectors; for example, neither C,
> Pascal, nor Fortran do.
>

That is entirely a matter of perspective.

Array types whose size is specified, I suppose, represent the notion of
"vectors" in C. But such arrays are considered equivalent in a lot of
contexts to buffers, whose size is not generally known, but (for certain
buffers) is alterable through realloc().

> But C's realloc does *not* resize memory regions in place, rather, it
> returns a pointer to a new region, and copies as necessary.
>

realloc() can potentially resize-in-place. And if the first realloc() is
unlikely to resize-in-place, the second is probably more likely to do so,
since the block will have been reallocated. And shrinking in place, of
course, is pretty easy.

It's also worth considering that not all platforms use the traditional
system calls. In PalmOS, for instance, pretty much all data is stored in
device RAM, and resizing is generally assumed to work - and when it doesn't,
allocated chunks can be relocated to make room.

Having thought about it I'd say requiring Scheme vectors to be resizable
might not be such a hot idea - mainly because if a vector can wind up
relocated, that means either a level of indirection is required between
references to the vector in Scheme data (which may not be sensible in all
interpreter designs). But I do think there ought to be mechanisms in
place (efficient vector copying by index ranges) so the "reallocate and copy"
approach can be done efficiently.

George Caswell

unread,
Jun 11, 2002, 8:47:03 PM6/11/02
to
On 11 Jun 2002, Thomas Bushnell, BSG wrote:

Because other languages support resizable vectors, therefore you have a
sensible primitive with which to (pretty trivially) implement resizable
vectors.

realloc() doesn't always resize in-place, but it doesn't always relocate,
either. Creating a new vector and copying values in works, you're just
guaranteed to get that performance penalty every time.

George Caswell

unread,
Jun 11, 2002, 8:53:40 PM6/11/02
to
On 11 Jun 2002, David Rush wrote:

> > (I am generally interested in learning about computer languages that can
> > provide me with new insight into various problems about language design. I
> > think Common Lisp may be my next study. Any other recommendations are
> > appreciated)
>
> You really owe it to yourself to learn SML, but it takes a
> while to make the paradigm shift from OO thinking to its functorial
> approach. I think it's a better way of getting the re-use benefits
> that OO strives to achieve. Of course, once you understand SML's
> approach, implementing it in Scheme is a doddle. (I don't advocate
> learning it in Scheme becaue SML has a lot of syntax and compiler
> support to help you realize exactly what you're doing...)
>

Hi,

The ML book at my local computer bookstore ("The Little MLer") didn't seem
too enlightening. I know some Haskell, and I'm trying to determine if it's
still worthwhile to learn ML as well.

Thomas Bushnell, BSG

unread,
Jun 11, 2002, 9:05:36 PM6/11/02
to
George Caswell <sieg...@attbi.com> writes:

> And its syntax: A function may include vectors specified by their
> syntactic constructor #(). Not a show-stopper but certainly a pain if you're
> thinking of actually doing this.

Ah yes, indeed. Anyway, this kind of redefinition of standard
functions--while a feature of certain SRFI's, is really not a good
general technique, for this and other reasons.

> Array types whose size is specified, I suppose, represent the notion of
> "vectors" in C. But such arrays are considered equivalent in a lot of
> contexts to buffers, whose size is not generally known, but (for certain
> buffers) is alterable through realloc().

No, a buffer's size cannot be changed through realloc. Realloc does
not change the size of anything (at least, not reliably). It might
return a pointer with the same value, but that's at best a happy
accident. In terms of the actual interface, it doesn't resize
anything. (As indicated by its name, as well--it reallocates.)

> realloc() can potentially resize-in-place. And if the first realloc() is
> unlikely to resize-in-place, the second is probably more likely to do so,
> since the block will have been reallocated. And shrinking in place, of
> course, is pretty easy.

That's pointless. We're talking interface, not efficiency. The
interface returns a new object, not in place.

Now, if you're worried about efficiency, then note that a Scheme
system might well recognize vector copy-and-reallocate sequences and
be way more efficient about them. Nothing about the interface of
realloc somehow guarantees efficiency, nor does the Scheme interface
somehow preclude it.

> It's also worth considering that not all platforms use the traditional
> system calls. In PalmOS, for instance, pretty much all data is stored in
> device RAM, and resizing is generally assumed to work - and when it doesn't,
> allocated chunks can be relocated to make room.

When I speak of C, I mean the standard interface (malloc, free,
realloc). The "traditional system calls" are, I assume, brk and
sbrk. I don't know what that has to do with it, however.

> Having thought about it I'd say requiring Scheme vectors to be resizable
> might not be such a hot idea - mainly because if a vector can wind up
> relocated, that means either a level of indirection is required between
> references to the vector in Scheme data (which may not be sensible in all
> interpreter designs). But I do think there ought to be mechanisms in
> place (efficient vector copying by index ranges) so the "reallocate and copy"
> approach can be done efficiently.

And there are some. You are assuming that compilers will be stupid.

Thomas Bushnell, BSG

unread,
Jun 11, 2002, 9:07:43 PM6/11/02
to
George Caswell <sieg...@attbi.com> writes:

> Because other languages support resizable vectors, therefore you have a
> sensible primitive with which to (pretty trivially) implement resizable
> vectors.

Neither C, Fortan, nor Pascal support resizeable vectors.

> realloc() doesn't always resize in-place, but it doesn't always relocate,
> either. Creating a new vector and copying values in works, you're just
> guaranteed to get that performance penalty every time.

1) C does not guarantee you anything about whether realloc will or
will not resize in place. Realloc might well always reallocate,
and when considering the time complexity of algorithms, you should
assume it always does.

2) Scheme does not guarantee that you will get a performance penalty,
because the compiler is perfectly free to optimize the case, just
as you think a realloc implementation will do.

Thomas

George Caswell

unread,
Jun 11, 2002, 11:04:02 PM6/11/02
to
On 11 Jun 2002, Thomas Bushnell, BSG wrote:

> George Caswell <sieg...@attbi.com> writes:
>
> > Because other languages support resizable vectors, therefore you have a
> > sensible primitive with which to (pretty trivially) implement resizable
> > vectors.
>
> Neither C, Fortan, nor Pascal support resizeable vectors.
>

C supports realloc(). It supports resizable vectors in the same sense that
it supports vectors at all.

> > realloc() doesn't always resize in-place, but it doesn't always relocate,
> > either. Creating a new vector and copying values in works, you're just
> > guaranteed to get that performance penalty every time.
>
> 1) C does not guarantee you anything about whether realloc will or
> will not resize in place. Realloc might well always reallocate,
> and when considering the time complexity of algorithms, you should
> assume it always does.
>

If you feel this is the case, please provide me with a C program which
demonstrates just how frequently realloc() moves a chunk. My experiments
haven't supported your conclusions.

> 2) Scheme does not guarantee that you will get a performance penalty,
> because the compiler is perfectly free to optimize the case, just
> as you think a realloc implementation will do.
>

I think it's unrealistic to expect this optimization would be common.

Scott G. Miller

unread,
Jun 11, 2002, 11:37:57 PM6/11/02
to
George Caswell wrote:
> On 11 Jun 2002, Thomas Bushnell, BSG wrote:
>>
>>1) C does not guarantee you anything about whether realloc will or
>> will not resize in place. Realloc might well always reallocate,
>> and when considering the time complexity of algorithms, you should
>> assume it always does.

Thomas: I think this assumption is somewhat unnecessary. The realloc
call will try to resize when possible. A programmer can probably
reasonably make assumptions about how often this happens if she knows
the strategy realloc is taking and how she has and will allocate memory
(see below).

>>
>
> If you feel this is the case, please provide me with a C program which
> demonstrates just how frequently realloc() moves a chunk. My experiments
> haven't supported your conclusions.

I can say nothing about the frequency with which this will happen, but
the efficiency of realloc in the standard C library on Linux is largely
related to your allocation strategy. The following trivial program
demonstrates the canonical case where realloc will fail to expand a
buffer. This example demonstrates what is likely to occur if you aren't
careful with your allocation and your buffers are similarly surrounded
by earlier and later allocations.

#include <stdlib.h>

int main(int argc, char** argv)
{
void *x=malloc(100);
void *y=malloc(100);
void *z=malloc(100);

printf("%x\n", (int)y);
y=realloc(y, 200);
printf("%x\n", (int)y);
}

Results in:
[20:35:33] scgmille:/tmp$ ./test
80496e8
80497b8


>
>
>>2) Scheme does not guarantee that you will get a performance penalty,
>> because the compiler is perfectly free to optimize the case, just
>> as you think a realloc implementation will do.
>>
>
> I think it's unrealistic to expect this optimization would be common.

I think the point is that neither C nor Scheme guarantee this happens at
all, its just that C provides a call that encourages this sort of
optimization.

Scott

Ben Goetter

unread,
Jun 11, 2002, 11:54:36 PM6/11/02
to
Quoth Ray Dillinger:
> [...] you want to cruft up the language just because you're
> assuming your compiler is stupid and won't optimize representations
> otherwise.

Ah, the proverbial sufficiently smart compiler.

> Let's not clutter up the language with this stuff.

Clutter/cruft up the language? It was a digression on the
representation of Scheme's string datatype. What are you talking about?

Thomas Bushnell, BSG

unread,
Jun 12, 2002, 12:24:31 AM6/12/02
to
George Caswell <sieg...@attbi.com> writes:

> > 1) C does not guarantee you anything about whether realloc will or
> > will not resize in place. Realloc might well always reallocate,
> > and when considering the time complexity of algorithms, you should
> > assume it always does.
> >
> If you feel this is the case, please provide me with a C program which
> demonstrates just how frequently realloc() moves a chunk. My experiments
> haven't supported your conclusions.

Huh? Your experiments don't say anything about what the C standard
does and does not guarantee.

I've seen perfectly respectable real-world systems that implemented
realloc this way:

void *
realloc (void *ptr, size_t size)
{
void *newptr;

if (size)
{
newptr = malloc (size);
if (ptr)
{
size_t oldsize;
oldsize = MAGIC (ptr); /* this depends on the details of malloc */
memcpy (newptr, ptr, oldsize);
}
}
else
newptr = 0;
free (ptr);
return newptr;
}

(My apologies for posting in such an ugly language to c.l.s.)

> > 2) Scheme does not guarantee that you will get a performance penalty,
> > because the compiler is perfectly free to optimize the case, just
> > as you think a realloc implementation will do.
> >
> I think it's unrealistic to expect this optimization would be common.

I think it's unrealistic to assume anything about the internals of
realloc too.

Thomas

Thomas Bushnell, BSG

unread,
Jun 12, 2002, 12:25:51 AM6/12/02
to
"Scott G. Miller" <scgm...@freenetproject.org> writes:

> Thomas: I think this assumption is somewhat unnecessary. The realloc
> call will try to resize when possible.

Where does the C standard say this?

> A programmer can probably
> reasonably make assumptions about how often this happens if she knows
> the strategy realloc is taking and how she has and will allocate
> memory (see below).

This is not true; I can easily show you a pair of allocators, both
rational, such that a pattern of usage designed to optimize reallocs
of one will hose the other, and vice versa, under fairly ordinary
conditions.

Jeffrey M. Vinocur

unread,
Jun 12, 2002, 12:37:48 AM6/12/02
to
In article <Pine.LNX.3.96.102061...@adamant.attbi.com>,

George Caswell <tets...@users.sourceforge.net> wrote:
>
> The ML book at my local computer bookstore ("The Little MLer") didn't seem
>too enlightening.

Mmm. I don't mean to disparage anyone, but there are no great
SML textbooks. (We teach our third-semester programming course
in SML, and we don't the students purchase any text. Paulson's
"ML for the Working Programmer" does a decent job of what the
title indicates, getting the syntax and concepts across to
someone with a programming background, if that is the sort of
text you like.) You can grab the notes we put up for CS 312 off
the web, but they're intended to teach general programming stuff,
SML specifics, and datastructures/algorithms all at once, which
is probably not what you're looking for.


>I know some Haskell, and I'm trying to determine if it's
>still worthwhile to learn ML as well.

Is there ever anything not worth learning? (I'm serious here.)

But yes, I think it is worthwhile. It's affected the way I think
(and the way I program in C, interestingly).

--
Jeffrey M. Vinocur * jm...@cornell.edu
http://www.people.cornell.edu/pages/jmv16/

Scott G. Miller

unread,
Jun 12, 2002, 12:42:13 AM6/12/02
to

Of course you can. I only claim that if the programmer has good
knowledge of the reallocator (and, your right, the allocator too), she
needn't assume the worst all the time. If she doesn't, then she
probably should. If it were me, I would probably code assuming that I
could get the worst case behavior, but may not, since the call certainly
allows for optimization.

Scheme does not have a vector related call that suggests such
optimization is possible. Yes, a compiler may recognize behavior that
is similar to realloc and optimize it, but its going to be much more
difficult (and thus probably more rare) than a call who's semantics
allow for it. The latter requires a much less intelligent compiler.

Scott

Scott G. Miller

unread,
Jun 12, 2002, 12:44:40 AM6/12/02
to
Thomas Bushnell, BSG wrote:
> "Scott G. Miller" <scgm...@freenetproject.org> writes:
>
>
>>Thomas: I think this assumption is somewhat unnecessary. The realloc
>>call will try to resize when possible.
>
>
> Where does the C standard say this?
>
I don't know it well enough to comment. I'm basing my information off
the man page for realloc, which on Linux states:

realloc() changes the size of the memory block pointed to
by ptr to size bytes. The contents will be unchanged to
the minimum of the old and new sizes; newly allocated mem­
ory will be uninitialized. If ptr is NULL, the call is
equivalent to malloc(size); if size is equal to zero, the
call is equivalent to free(ptr). Unless ptr is NULL, it
must have been returned by an earlier call to malloc(),
calloc() or realloc().

Its not terribly clear, but 'changes the size of the memory block' at
least implies a resize rather than a fresh allocation.

Scott

Thomas Bushnell, BSG

unread,
Jun 12, 2002, 12:56:05 AM6/12/02
to
"Scott G. Miller" <scgm...@freenetproject.org> writes:

> Its not terribly clear, but 'changes the size of the memory block' at
> least implies a resize rather than a fresh allocation.

Right. Nothing here however says that resizing will be done "when
possible", or even that it's ever possible (as indeed, for some
allocators, it isn't).

Thomas

George Caswell

unread,
Jun 12, 2002, 1:03:39 AM6/12/02
to
On Wed, 12 Jun 2002, Jeffrey M. Vinocur wrote:

> >I know some Haskell, and I'm trying to determine if it's
> >still worthwhile to learn ML as well.
>
> Is there ever anything not worth learning? (I'm serious here.)
>

Good point, particularly in the context of what I'm trying to accomplish.
Though on the other hand I think if I knew only C and Scheme, learning Haskell
or ML as a third language would be a lot more enlightening than, say, Java or
Common Lisp.

Actually the reason I asked was in reading about ML (in the Seasoned MLer
book, which was too elementary for my purposes) I was hoping to find out what
I could learn from ML which Haskell hadn't already taught me. Each example
seemed very similar in expression and the basic rules of what could be done
and how to Haskell, and it reached the point where I wasn't quite sure what
important conceptual differences might exist between the two. Being ever-lazy
I was hoping someone could answer that for me. :)

Scott G. Miller

unread,
Jun 12, 2002, 1:11:53 AM6/12/02
to

You're right. A good parallel is the Java System.arraycopy function,
whose API description does not mention any efficiency gains. For all
the programmer knows, its just copying one array to another in a loop.
However, the function has no other reason for existing than to allow JVM
implementors to perform an array copy efficiently. So a programmer will
use System.arraycopy with the understanding that it *might* be more
efficient than the obvious solution. I believe realloc is similar.

It probably doesn't make sense for Scheme to have a resize vector API
function, because it doesn't fit well into the memory model or the
current API for vectors, but you can see that in other less concise
languages some API calls exist for the sole purpose of providing strong
hints or opportunities for greater efficiency over what the programmer
is otherwise able to do on his/her own.

Scott

Shiro Kawai

unread,
Jun 12, 2002, 2:11:28 AM6/12/02
to
Boris Smilga <bo...@bhasha.com> wrote in message news:<87u1o9e...@ganglion.bhasha.com>...

> I guess, it's the hannigori mark, which looks like a small circle
> drawn above and to the right of a kana character (see the relevant
> Unicode charts). But I thought they were only being used with h-/f-
> syllables (changing the initial to [p]), not with k- syllables.

Right.

> What would a ka + hannigori sound like, Shiro-san?

K-syllable + hannigori is not in the standard notation
system, but has been used in limited situations
to describe the sound [ng]. Although both [nga] and [ga]
are represented by Ka + nigori mark in the standard notation,
japanese speakers differentiate the pronunciation by the
context. K-syllable + hannigori character is used when you
want to emphasize [ng] pronunciation; for example, voice
training textbooks, or notation of dialects.

The character is added to the JIS character set fairly
recently (2000), so that's why it's not in Unicode, I guess.

I raised the example from the top of my head because I was
writing the conversion routine at that time. The character
is not used in ordinaly Japanese text and is rarely a problem.
But I imagine there are such cases in other languages
as well.

Rob Warnock

unread,
Jun 12, 2002, 6:50:36 AM6/12/02
to
Thomas Bushnell, BSG <tb+u...@becket.net> wrote:
+---------------

| George Caswell <sieg...@attbi.com> writes:
| > Because other languages support resizable vectors, therefore you have a
| > sensible primitive with which to (pretty trivially) implement resizable
| > vectors.
|
| Neither C, Fortan, nor Pascal support resizeable vectors.
+---------------

Their loss. But Common Lisp does, see <URL:http://www.xanalys.com/
software_tools/reference/HyperSpec/Body/15_aacaa.htm> "Fill Pointers"
for "adjustable arrays", and the links to MAKE-ARRAY and ADJUST-ARRAY.

CL also has "displaced-to" arrays, which are a convenient way to do
sharing of subsets of an array.


-Rob

-----
Rob Warnock, 30-3-510 <rp...@sgi.com>
SGI Network Engineering <http://www.rpw3.org/>
1600 Amphitheatre Pkwy. Phone: 650-933-1673
Mountain View, CA 94043 PP-ASEL-IA

[Note: aaan...@sgi.com and zedw...@sgi.com aren't for humans ]

ozan s yigit

unread,
Jun 12, 2002, 10:42:38 AM6/12/02
to
Thomas Bushnell:

> You are assuming that compilers will be stupid.

that is the proper working assumption for scheme, as per
the standard!

oz
--
bang go the blobs. -- ponder stibbons

David Rush

unread,
Jun 12, 2002, 10:56:41 AM6/12/02
to
George Caswell <sieg...@attbi.com> writes:
> On Wed, 12 Jun 2002, Jeffrey M. Vinocur wrote:
> > George Caswell wrote:
> > >I know some Haskell, and I'm trying to determine if it's
> > >still worthwhile to learn ML as well.

> Actually the reason I asked was in reading about ML (in the Seasoned MLer


> book, which was too elementary for my purposes) I was hoping to find out what
> I could learn from ML which Haskell hadn't already taught me.

Well, IMO the SML method of re-use (through the module system) is
significantly different from anything in Haskell. I have to admit that
I haven't kept up with Haskell over the years, though, but I haven't
even heard hints of the SML module system leaking back into any other
functional languages *except* Scheme (where the bulk of the
in-production module systems take their inspiration from it).

david rush
--
By loudly denouncing all bad things - war and hunger and date
rape - liberals testify to their own terrific goodness.
-- P. J. O'Rourke

David Rush

unread,
Jun 12, 2002, 11:02:19 AM6/12/02
to
George Caswell <sieg...@attbi.com> writes:
> On Tue, 11 Jun 2002, Feuer wrote:
> > vector-like
> > data structures out there. You can write any of them in Scheme. That's all I'm
> > saying. If you want vectors that can change size, you can use a boring copying
> > scheme
>
> That works, of course, but since Scheme doesn't provide a vector-copy
> operation, the copying loop is interpreted code.

No it's not. Code is code. Some implementations use a byte-code
interpreter. Some interpret the S-expressions directly. Some translate
them to machine instructions and let the silicon interpret
*that*. Some of those machine-code translators produce code of
equivalent performance to anything in a library (since almost all of
the library was compiled by the compiler in the first place).

david rush
--
X-Windows: It was hard to write; it should be hard to use.
-- Jamie Zawinski

David Rush

unread,
Jun 12, 2002, 11:09:36 AM6/12/02
to
George Caswell <sieg...@attbi.com> writes:
> On Tue, 11 Jun 2002, Feuer wrote:
> > vector-like
> > data structures out there. You can write any of them in Scheme. That's all I'm
> > saying. If you want vectors that can change size, you can use a boring copying
> > scheme
>
> That works, of course, but since Scheme doesn't provide a vector-copy
> operation, the copying loop is interpreted code.
>
> > with scheme vectors. If you want vectors with O(1) cons, snoc, head, and last,
> > you
> > can do that too (getting O(lg n) vector-ref). The OP was proposing adding some
> > sort of flexible vector to the language; I was saying such belong in libraries.

> Maybe a vector-copy would be the better general solution, then:

And how hard is that to write?

(define (vector-copy! dest src)
(let ((dest-length (vector-length dest))
(src-length (vector-length src)))
(let copy ((i 0))
(if (or (>= i dest-length)
(>= i src-length))
dest
(begin
(vector-set! dest i (vector-ref src i))
(copy (+ i 1)))
))))


> On a side note, if I were to solve certain of these problems by
> implementing a container type in Scheme, I think I would be frustrated by the
> lack of facilities for integrating the new type into the Scheme environment:

SRFI-9. And yes, it's inexcusable that it is not part of the standard.

david rush
--
Property is theft.
-- What is Property? (Pierre-Joseph Proudhon)

David Rush

unread,
Jun 12, 2002, 11:12:04 AM6/12/02
to
"Scott G. Miller" <scgm...@freenetproject.org> writes:
> Thomas Bushnell, BSG wrote:
> > George Caswell <sieg...@attbi.com> writes:
> >> In particular, I'm interested in resizable vectors, because I've been
> >>frustrated in the past by their absence in Scheme and the implementation of a
> >>resizable vector in Scheme does not seem obvious.

> The only hangup is that you can't resize a vector in place. You may
> replace one vector with another in any datastructure you please. If
> you can live with that, then the implementation is trivial (but O(n)):

But you can't do it in C, either! I realize the Caswell is looking at
other options, but I got the impression that realloc() was his
baseline functionality.

david rush
--
Christianity has not been tried and found wanting; it has been found
difficult and not tried.
-- G.K. Chesterton

David Rush

unread,
Jun 12, 2002, 11:20:41 AM6/12/02
to
"Scott G. Miller" <scgm...@freenetproject.org> writes:
> Scheme does not have a vector related call that suggests (realloc-style)
> optimization is possible.

No and I was thinking you had a good point until I though about
copying GC. The chances of actually having a memory map that allows
reallocation are actually very small. If you know that you want O(1)
access and update but don't know the size, you;re far better off
coding your data-structure because you're going to want to control the
amount of space dedicated to the realloc optimization.

david rush
--
Scheme: Because closures are cool.
-- Anton van Straaten (the Scheme Marketing Dept from c.l.s)

ozan s yigit

unread,
Jun 12, 2002, 11:03:03 AM6/12/02
to
Scott G. Miller:

> Its not terribly clear, but 'changes the size of the memory block' at
> least implies a resize rather than a fresh allocation.

when in doubt, you have to consult the international standard, which
makes absolutely no mention of a resize. see ISO/IEC 9899:1999, that
is the C9X standard, or have harbison/steele at hand.

"the realloc function deallocates the old object pointed to
by ptr and returns a new pointer to a new object that has the
size specified by size" [and so on about content, see C9X]

there is no room for misinterpretation here.

Scott G. Miller

unread,
Jun 12, 2002, 12:42:14 PM6/12/02
to
David Rush wrote:
> "Scott G. Miller" <scgm...@freenetproject.org> writes:
>
>>Scheme does not have a vector related call that suggests (realloc-style)
>>optimization is possible.
>
>
> No and I was thinking you had a good point until I though about
> copying GC. The chances of actually having a memory map that allows
> reallocation are actually very small. If you know that you want O(1)
> access and update but don't know the size, you;re far better off
> coding your data-structure because you're going to want to control the
> amount of space dedicated to the realloc optimization.
>
Yeah, there are a dozen reasons why this is a bad idea in Scheme. They
don't necessarily apply to C since you have explicit memory control.
You can even specify your own allocator in some circumstances. But as
Ozan pointed out, the C standard even says that realloc doesn't resize
(though I still believe some implementations do under some
circumstances, however rare they may be).

Scott

Feuer

unread,
Jun 12, 2002, 12:55:55 PM6/12/02
to
The standard doesn't say that either.

Jeffrey Siegal

unread,
Jun 12, 2002, 1:12:02 PM6/12/02
to

Nothing in that definition prohibits returning a "new object" that
happens to be located in the same place as the "old object."


Ray Dillinger

unread,
Jun 12, 2002, 1:21:13 PM6/12/02
to

David Rush wrote:
>
> > On a side note, if I were to solve certain of these problems by
> > implementing a container type in Scheme, I think I would be frustrated by the
> > lack of facilities for integrating the new type into the Scheme environment:
>
> SRFI-9. And yes, it's inexcusable that it is not part of the standard.

I'm not entirely sure that's true. For example, consider
all the routines that are supposed to take values of any
type, especially if they are routines that have to recursively
access the fields of aggregating types. (as an example, a
routine that produces a hash-table index for storing the
datum).

As long as you know what all of the allowed kinds of
values ("types") are, you can write such routines. Once
you start dealing with user-defined types, or SRFI's that
introduce types in an undisciplined way generally, you no
longer have the guarantees you need to do that.

Someone introducing a new "disjoint type" can, if they're
very conscientious, go and modify all of the reference
routines so that they deal with his new "disjoint type"
appropriately. But if you want to use standard library
code, the additional types may screw you over. For example,
if you want to use my library for hash tables in such a system,
the first time you pass it a value that returns #f for all
type predicates known to R5RS, it will print an error message
telling you to extend (hash) for the unknown type, and halt.
If I'd just assumed R5RS compliance in disjoint types, it
would do an undefined thing - probably crash with an error
when #f, from the last type predicate in the cond statement,
got passed to a continuation expecting an exact integer and
used as a vector index. Either way, it works flawlessly in
systems where values legal in R5RS are used, and dies the
minute someone creates a new disjoint type. And SRFI-9
provides the machinery needed to break it, but not the
machinery needed to fix it.

I would say that if you're going to produce new types, you
need to do better than SRFI-9 to make it possible for library
code to deal with them.

I'm much happier when all my records are just syntax or
routines for vector accesses -- that way it doesn't screw
up any libraries or built-in code.

Bear

Thomas Bushnell, BSG

unread,
Jun 12, 2002, 1:27:10 PM6/12/02
to
rp...@rigden.engr.sgi.com (Rob Warnock) writes:

> Their loss. But Common Lisp does, see <URL:http://www.xanalys.com/
> software_tools/reference/HyperSpec/Body/15_aacaa.htm> "Fill Pointers"
> for "adjustable arrays", and the links to MAKE-ARRAY and ADJUST-ARRAY.

Quite right. Ironically, so does Smalltalk, and a variety of other
more high-level languages. It might be thought to be a shame that
Scheme is in the company of C, Fortran, and Pascal on this, instead of
in the company of Smalltalk and Common Lisp.

I don't even thing resizable arrays are all that common an extension
among Scheme systems.

Maybe we need a srfi?

George Caswell

unread,
Jun 12, 2002, 1:48:18 PM6/12/02
to
On 12 Jun 2002, David Rush wrote:

> > Maybe a vector-copy would be the better general solution, then:
>
> And how hard is that to write?
>

Not hard at all. But it would be more efficient if it were implemented as
part of the interpreter itself. (Assuming a Scheme runtime other than the
"sufficiently smart optimizing compiler")

> > On a side note, if I were to solve certain of these problems by
> > implementing a container type in Scheme, I think I would be frustrated by the
> > lack of facilities for integrating the new type into the Scheme environment:
>
> SRFI-9. And yes, it's inexcusable that it is not part of the standard.
>

I'll have to read SRFI-9, then, and decide for myself.

Jordan M. Johnson

unread,
Jun 12, 2002, 3:04:43 PM6/12/02
to
George Caswell <tets...@users.sourceforge.net> wrote:
>> > Maybe a vector-copy would be the better general solution, then:
>>
>> And how hard is that to write?
>>
> Not hard at all. But it would be more efficient if it were implemented as
>part of the interpreter itself. (Assuming a Scheme runtime other than the
>"sufficiently smart optimizing compiler")

Maybe, maybe not. As Mr. Rush has pointed out, there are substantial
differences in how Schemes interpret/compile/execute code; compiling and
optimizing the code as it's entered by the user can make a similarly vast
difference.

jmj

Matthias Blume

unread,
Jun 12, 2002, 5:02:47 PM6/12/02
to
Jeffrey Siegal <j...@quiotix.com> writes:

So what? Ozan's point is that the standard does nothing to guarantee
such behavior. (And it does not even encourage anyone to expect it).

C programmers who use realloc must not assume that the pointer they
pass to the function will be valid afterwards. (There is not even
a portable way of finding out after the fact whether or not the result
is still in the same place as the argument.)

-Matthias

Jeffrey Siegal

unread,
Jun 12, 2002, 5:25:30 PM6/12/02
to
Matthias Blume wrote:

>>Nothing in that definition prohibits returning a "new object" that
>>happens to be located in the same place as the "old object."
>>
>>
>So what? Ozan's point is that the standard does nothing to guarantee
>such behavior. (And it does not even encourage anyone to expect it).
>
>C programmers who use realloc must not assume that the pointer they
>pass to the function will be valid afterwards. (There is not even
>a portable way of finding out after the fact whether or not the result
>is still in the same place as the argument.)
>
>

That's obvious from any definition of realloc, including those that say
it may resize the object.

felix

unread,
Jun 12, 2002, 5:53:45 PM6/12/02
to

Thomas Bushnell, BSG wrote in message <87y9dk7...@becket.becket.net>...

>rp...@rigden.engr.sgi.com (Rob Warnock) writes:
>
>> Their loss. But Common Lisp does, see <URL:http://www.xanalys.com/
>> software_tools/reference/HyperSpec/Body/15_aacaa.htm> "Fill Pointers"
>> for "adjustable arrays", and the links to MAKE-ARRAY and ADJUST-ARRAY.
>
>Quite right. Ironically, so does Smalltalk,[...]

Smalltalk has `become:', which is orders of magnitude more powerful
and general than fill-pointers...


cheers,
felix


Matthias Blume

unread,
Jun 12, 2002, 10:27:36 PM6/12/02
to
Jeffrey Siegal <j...@quiotix.com> writes:

Right. So what's the fuzz all about?

--
-Matthias

Jeffrey Siegal

unread,
Jun 13, 2002, 2:29:24 AM6/13/02
to
Matthias Blume wrote:

Mystery to me. Someone suggested that Scheme should have a
resize-vector operation, I think.

MJ Ray

unread,
Jun 12, 2002, 3:36:14 PM6/12/02
to
John Tobey <jto...@john-edwin-tobey.org> wrote:
> #!/usr/lib/plt/.bin/i386-linux/mzscheme -r
> at the top of my scripts, which seems somehow distasteful. Needless to
> say, the first chapter of any Unix-oriented Perl book describes some of
> the many ways of invoking perl.

Install a link to mzscheme in a better location, then. On my (Debian)
system, it appears to be in /usr/bin (but I use v200 packages).

The "popular" book for PLT-scheme "How To Use Scheme" has a whole chapter on
the many ways to run scripts. It's still being written as yet, though. I'm
sort of interested in developing a "Popular Scheme" reference site which is
more like the Perl books in style, to complement the excellent more academic
Scheme texts. Would people help develop it?

[...]
> Well, I think so too, but the fact that it is never mentioned in RnRS or
> SRFIs disturbs me. (Actually, I believe exit is in a SRFI, but not a
> widely implemented one.)

Why not request its implementation? ;-)

There are more SRFIs that I would like to see, though. Maybe one day I'll
get time to do some of them.

>>> It is not enough that these features be implementable via
>>> call-with-current-continuation or available with a little work. They
[...]
>> This is getting ridiculous.
>
> No, just very practical in the situation of promoting the language amid
> forces of resistance. I am not the only programmer where I work, nor am

In some (many?) cases, it seems that exceptions are abused to provide a
goto-style spaghetti programming for the OO generation. It's not always
good to have the sharp tools being the popular ones and there are sometimes
more elegant ways to write equivalent functionality.

> Thanks for the comments.

You too, but let's do something productive with them, please?

MJ Ray

unread,
Jun 12, 2002, 3:41:50 PM6/12/02
to
Ray Dillinger <be...@sonic.net> wrote:
> Now, for "Pascal" read "Scheme", and for "C" read "Common Lisp" and
> it's happening again. The better language, once again, is less popular
> because its standard is underspecified. And this is a pattern. When
> people care about langauge design, the standards *do* develop very
> slowly. But a standard in an underdeveloped state will kill a language
> for use in the general world.

I think the basic standard is in a good state, but it probably is
"underspecified" for many sorts of "general world" work. So let's do
something about it: if you know a particular field well, consider preparing
a SRFI for that field. We have a process there to make Scheme the
most elegant language for real work while keeping portability. I know that
a lot of useful tools are in the implementations' and contributors'
libraries: let's apply survival of the fittest and wrap the rest?

MJ Ray

unread,
Jun 12, 2002, 3:57:49 PM6/12/02
to
Joe Marshall <prunes...@attbi.com> wrote:
[...]
> Have you looked at Common Lisp?

And another one! Since when did this become comp.lang.lisp.common.advocacy?
Most Schemes are more than fine for most of the things mentioned, at least
as much as CL. Let's make it even better, not abandon it.

And don't top-post either.

George Caswell

unread,
Jun 13, 2002, 12:06:56 PM6/13/02
to

I don't think the Common Lisp suggestion was at all out-of-line. The
poster (IIRC) was replying to someone asking for features in
Scheme which aren't there, and maybe don't even belong there - but are in
Common Lisp. I see it as being the same as if I had said Scheme should have
infix operators, pattern-matching declarations, strict typing, lazy evaluation
by default, etc. and someone suggested I check out Haskell. Suggesting that
someone check out another language is perfectly reasonable, particularly if
they could learn something from it.

It's not necessary to abandon one language to learn another, and the fact
that there are other languages out there which are better for certain tasks
doesn't make Scheme's value any less.

Rob Warnock

unread,
Jun 14, 2002, 4:34:43 AM6/14/02
to
felix <felixu...@freenet.de> wrote:
+---------------
| >> [CL] "adjustable arrays", and the links to MAKE-ARRAY and ADJUST-ARRAY.

| >
| >Quite right. Ironically, so does Smalltalk,[...]
|
| Smalltalk has `become:', which is orders of magnitude more powerful
| and general than fill-pointers...
+---------------

Indeed. Similarly, Common Lisp provides dynamic redefinition of
classes, wherein all existing instances of the class get automatically
converted to the new class definition (which can be customized
with UPDATE-INSTANCE-FOR-REDEFINED-CLASS), as well as CHANGE-CLASS
(dynamically change the class of a specific instance, which can
be customized with UPDATE-INSTANCE-FOR-DIFFERENT-CLASS).

These changes can cause slots to be added or deleted, or be completely
redefined while the program is running. E.g., there's an example at
<URL:http://www.xanalys.com/software_tools/reference/HyperSpec/Body/
f_upda_1.htm> of defining a class "X-Y-POSITION" in rectangular
coordinates, running the program for a while (instantiating a number
of instances), then noticing that:

;;; It turns out polar coordinates are used more than Cartesian
;;; coordinates, so the representation is altered and some new
;;; accessor methods are added.

By defining a method for UPDATE-INSTANCE-FOR-REDEFINED-CLASS which
is specialized for class X-Y-POSITION before the redefinition, the
existing instances can be automatically converted from rectangular
coordinates to polar.

Two points (pardon the pun!) that may be of interest from "4.3.6
Redefining Classes" <URL:http://www.xanalys.com/software_tools/
reference/HyperSpec/Body/04_cf.htm>:

When the class C is redefined, changes are propagated to its
instances and to instances of any of its subclasses. Updating
such an instance occurs at an implementation-dependent time,
but no later than the next time a slot of that instance is
read or written.

That is, the implementation is permitted to call UPDATE-INSTANCE-FOR-
REDEFINED-CLASS on instances lazily, as needed, thus spreading out
the computational load of the conversion (or deferring it altogether
for instances that are never accessed after the redefinition). And:

Updating an instance does not change its identity as defined by
the function EQ. The updating process may change the slots of
that particular instance, but it does not create a new instance.

This almost (but not quite) mandates a level of indirection between
an "instance" and the internal storage for the instance. [I say "not
quite" because that indirection need not occur for classes which are
never redefined... though I don't know if any existing implementations
actually make use of that flexibility.]

David Rush

unread,
Jun 14, 2002, 5:59:30 AM6/14/02
to
Ray Dillinger <be...@sonic.net> writes:
> David Rush wrote:
> > > On a side note, if I were to solve certain of these problems by
> > > implementing a container type in Scheme, I think I would be frustrated by the
> > > lack of facilities for integrating the new type into the Scheme environment:
> >
> > SRFI-9. And yes, it's inexcusable that it is not part of the standard.
>
> I'm not entirely sure that's true. For example, consider
> all the routines that are supposed to take values of any
> type, especially if they are routines that have to recursively
> access the fields of aggregating types. (as an example, a
> routine that produces a hash-table index for storing the
> datum).

Not a problem, IMO. The run-time still knows about all of the base
types in the system. Any user defined aggregates must, by definition,
be built out of those. The only problem is structural traversal, and
since everything in Scheme can be built out of atomic types and
vectors, I don't see the problem.

Now if you want to consider space-optimized structures that work like
C structs you've got a problem, but Scheme doesn't really begin to
address the issues there. At that, the same solutions that work for
the collector in SML should work in Scheme. Reflecting the type system
back into the user's hands is an even better idea. Certainly it was
one of the best things about Smalltalk.

> I would say that if you're going to produce new types, you
> need to do better than SRFI-9 to make it possible for library
> code to deal with them.

That's part of why I consider it mandatory to roll SRFI-9 into the
standard. I don;t actually mean the SRFI-9 implementation, here. I do
mean a SRFI-9-like mechanism (probably, though not necessarily
expanded). There are issues which seem easier to solve from an
integrated standpoint rather than as a layer (e.g. reflection).

> I'm much happier when all my records are just syntax or
> routines for vector accesses -- that way it doesn't screw
> up any libraries or built-in code.

Well, I've never been happy with the Scheme "redefine everything in
order to introduce a new type" approach. If it's properly integrated
into the run-time it *won't* screw up library code. A simple macrotic
implentation of SRFI-9 doesn't really satisfy anything except cleaning
up (some of) the source code.

david rush
--
Compile-time is when *you* find the bug, run-time is when the
*customer* finds it.
-- Joe Marshall (on comp.lang.scheme)

Joe Marshall

unread,
Jun 14, 2002, 6:17:45 PM6/14/02
to

"MJ Ray" <markj...@cloaked.freeserve.co.uk> wrote in message
news:slrnagf9tt.5...@cloaked.freeserve.co.uk...

It is true that there are many versions of Scheme that contain extensions
that do as much if not more than the original poster requested.

However, the extensions are not portable among different implementations,
and that was one of the things that the original poster requested.

Many of the things that the original poster requested are addressed by
Common Lisp and are portable among different systems. I think that Scheme
and Common Lisp address two different audiences.

>
> And don't top-post either.

Yes, Sir!

MJ Ray

unread,
Jun 14, 2002, 5:46:26 AM6/14/02
to
George Caswell <sieg...@attbi.com> wrote:
> It's not necessary to abandon one language to learn another, and the fact
> that there are other languages out there which are better for certain tasks
> doesn't make Scheme's value any less.

It certainly sounds like it values it less than the POV of Scheme being
either the best language for any non-trivial task or capable of extension to
be the best to do it.

MJ Ray

unread,
Jun 14, 2002, 5:46:26 AM6/14/02
to

George Caswell <sieg...@attbi.com> wrote:
> It's not necessary to abandon one language to learn another, and the fact
> that there are other languages out there which are better for certain tasks
> doesn't make Scheme's value any less.

It certainly sounds like it values it less than the POV of Scheme being

Andreas Eder

unread,
Jun 16, 2002, 4:45:42 AM6/16/02
to
I think you should look into Common Lisp.
In most respects it is like an industrial grade scheme.

'Andreas
--
Wherever I lay my .emacs, thereć„€ my $HOME.

MJ Ray

unread,
Jun 15, 2002, 1:08:35 PM6/15/02
to
Joe Marshall <prunes...@attbi.com> wrote:
> However, the extensions are not portable among different implementations,
> and that was one of the things that the original poster requested.

That is why we should use the SRFI process more, IMO. Some things are
portable because of SRFIs and some are becoming de facto standard (eg SSAX).

> Many of the things that the original poster requested are addressed by
> Common Lisp and are portable among different systems. I think that Scheme
> and Common Lisp address two different audiences.

I don't. And I thought CL had its own portability problems... things
required for today's work, eg UncommonSQL claim to have been ported to
different CL environments.

It is loading more messages.
0 new messages