[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Scheme-reports] Just a load of.. well..

Dear Mr. Cowan,

Thanks a lot for your thoughtful reading of and reply to my message.  In fact, I wondered whether anyone would read it at all..  Of course my notes were never meant for anyone but myself.  Let me reply quickly, taking advantage of the burst of energy I am experiencing - but please:
- be warned: this is long;
- don't expect me to reply as quickly, or at all, in the general case.

>> (And I think "Schemest" would then be a one-syllable word.)

Ac respondisti
> introducing novel consonant clusters like /mst/ into it.

Or rather, reviving old ones.  I suppose verb forms such as "thou seemst" were pronounced that way.  But your point is taken.  This was not a prescriptive remark, but rather a musing - if there were an adjecive on -eme that took the gradus, how would its superlative be pronounced.

> (Sorry, but you pushed a button.)

Please don't apologise, I like such information!

>> (a micro Scheme might not even KNOW about, say, lower-case letters),

> the day of the PDP-8 and the ASR-33 Teletype is now over.

True, but one never knows what will turn up.  A chip with 2^256 really tiny processors?

>> * The asymmmetry between multiple inputs and multiple outputs for
>> procedures. (lambda (a b - result rem quot) (quotient+remainder a b -
>> quot rem) (* quot rem - result) (display result -))

> I don't think this is recognizable as Scheme any more,

I agree.  That's why that remark starts with "This is inherent in Scheme syntax".  I don't quite remember the context, but there was some discussion about dealing with multiple outputs, and in my remarks I tried to find for myself how much would be possible within the "feel" of Scheme, where the boundary was.

> It's just Prolog in S-expressions.

It was an attempt to decouple the machine and the syntax.  Prolog syntax that could drive a Scheme machine.  (The inverse is possible by having a symbol, say '$', indicate an output variable.  A Prolog predicate with one $ argument could then take the place of the companion variable of that elided output variable, as in
  threeappend(A, B, C, Z) :- append(B, C, X), append(A, X, Z). ;; Prolog style
  threeappend(A, B, C, Z) ;- append(A, append(B, C, $), Z) ;; Scheme style
The presence of the $ would also indicate to the compiler that the internal append is not a term but a call.

>> Barely possible is "splicing in" multiple results

> The idea of using splicing is interesting, though.

So it seems we come to the same conclusion as to where that boundary lies.

>> Maybe symbols should be decoupled from code text

> This can be provided by

My point was more fundamental than applied: I think they possibly ought to be decoupled.  Symbols are a combination of two orthogonal ideas, uniqueness and name - and I think it is always better to have one construct for one idea.  How this decoupling would pay off was the remainder.

>> syntax could be decoupled.

> I don't think, however, that it is ripe for standardization.

Here, too, is the same principle.  If code structure and surface form had never been coupled in the Lisp tradition, I am sure we would look down a bit on those poor languages that had irrevocably linked two completely different concepts as if they were one.  I am not proposing Scheme add more surface forms, just that it recognise the two concepts, and standardise one surface form, the current one.  Others could then provide other forms, without a standard, or with a different standard - that would not be the Scheme standard's business.
(In fact, as far as I am concerned even the standard for the current surface form could be moved out of the core into a library, as could the names of the procedures, keywords, etc. that the standard defines.  Let the core contain exactly that - the core.)

> In general, I'd say this of many of your points:
> they are a manifesto for an implementation, not for standardization,

I did not mean these ones that way.

>> This would lead to mutable first-class environments.

> WG1 went down this rathole in its earliest days.

Did it keep the identifiers hygienic too, as I want?  Otherwise you just get a mess, of course, when the underlying location of a variable can change or disappear.  But there is a subtlety for the garbage collector, because code can point to potential locations, the actual instance of which is not garbage collectable as long as that code is callable.

(define (test-builder x) ;; Build a location for x
   (do-lots-of-stuff-including-deleting-x) ;; Delete the location, but don't garbage collect it.
   (lambda () x) ) ;; ..because here it is still needed (lexical scoping).

> If you want completely dynamic languages,

Well, I don't, but I want to push the limit as far as I can without losing some important properties.  I think part of the Scheme spirit is about removing limits without seeing the baby go down the drain.

>> Oh, and environments shouldn't be different from other tables,
>> and should have a way to indicate where to find
>> a location that is not locally available.

> Self-modifying code provides immense power,
> but it's practically impossible to reason about,

I know.  While I fondly remember programming my first "while", by rplacd-ing the code into one of its own cond-clauses, I am not looking forward to going there again.  I do not propose changing the inheritance structure of a closure after it has been made - that would break lexical transparency.  But besides 'lambda', other closure-generating constructs might exist that use other inheritance schemes, and such constructs could be codable in Scheme without adding indirection or even interpreter levels. 

>> A common interface should govern all external resources

> A view of the user that doesn't distinguish them from a file
> is even more restrictive than TTY interaction.

I was thinking in the other direction.  A CD may have immutable data on it, but my OS still sees that as files, without therefore imposing immutability on all files.  the immutable ones are merely a degenerate case.
Likewise, a file is like the degenerately dumb form of a user.

>> Single pass with maximal deferment is the Scheme way: variables inside
>> lambdas don't need to be resolved yet, resolution can be deferred
>> until they are called.

> I think this is a very narrow exception to an essentially static design.

But one that is paramount in the notion of Schemeyness - to me, at least.  (I admit being a REPL fan.)  ML requires a letrec for each indirectly recursive function, which makes the language feel very different.  That goes well with the static typing, but wouldn't go well with Scheme.

>> Without very strong reasons, one should not request different behaviour
>> from syntax transformers. Ease of compilation, or speed of the
>> resulting system are no strong reasons.

> Reasoning about code,
> including your own code a month after you wrote it,
> is a very strong reason.

I think code that can be read roughly linearly is easier to understand.  Multi-pass means you can't understand your code on your first reading - if you could, so could the compiler.

>> A rewriter can be written in Scheme and then used in macro expansion -
>> great, but let the rewriter then be generally available (because it
>> has other possible uses),

> I agree, and have added this idea to WG2's input hopper
> to be voted on when WG2 reconvenes.

Thanks.  Or you you mean you already had done that independent of my mail? (Even then, thanks, of course.)

>> and be optional in writing syntax (because there are other ways
>> that sometimes may be better).

> I happen to think that going beyond `syntax-rules` is a mistake,

I definitely don't want another CL macro system, but I also think syntax-rules was a mistake.  Not bad in itself, but definitely not Scheme, so suddenly we had several constructs with restrictions on them - contrary to the Clinger manifest.
But more importantly, I think the language shouldn't prescribe how I write my macros, even if what it prescribes is the best way, as long as my way doesn't break important properties without me realising.  I know I break functionalness when I use a feature initially bound to a symbol with a name ending in an exclamation mark - but Scheme will let me do it anyway, having warned me.
If being able to break the properties has bad consequences for programs that don't - say compilation becomes impossible - then a reverse warning may be necessary: me flagging the system that I break the properties.  Without that warning the compiler can then do its efficient thing, and if I lied, shame on me.

>> Something else is lost here. Scheme was about the right thing,
>> but also about the minimal thing.

> there is nothing tiny or jewel-like about
> Scheme's standard procedure library, and never has been.

I think there is something t&j about it, at least.  Lisp didn't start out that way, of course - it had dynamic scoping, for one thing, and PROG with labels..  Heck, even 'lambda' came from a mis-typeset caret!  But Scheme has been about cleaning up, and approaching an ideal.  When the equivalence of actors and procedures was discovered, it was at least recognised as something worth preserving.  Call/cc is a procedure because it could be done that way, and it was tinier.  CL is more about grudgingly accepting the things Scheme had proven to be strong concepts and incorporating them into their ball of mud.

My hope was, and is again (it was lost during the R6RS debacle) that Scheme can remain a language striving in that direction - we already have enough languages striving in other directions.  I wish the Clinger manifest would be procedurally implemented in the sense that having more concepts, or having restrictions on concepts, would require a strong justification in a companion document to the standard - even if these things were taken over from previous standards.

> It has been patched together over time
> from a subset of what MacLisp provided.

I know, she started skinny and with acne all over her face - but she may grow up to be a beauty.  I may be wrong in many of the things I propose - wrong in the sense that adopting those would make Scheme less ideal - but at least I hope this vision is shared for small Scheme, and I'll gladly be shown wrong where I am wrong if that means Scheme will be more pristine!

> What is more, it's not clear that
> standardizing a facade
> and not its underlying layers
> is the Right Thing.

I am not sure what you are referring to here.  Which façade and which underlying layers do you distinguish in my text?

> WG2 will standardize TCP library routines, but ..
> The `error` procedure in R7RS may ..

I like such restraint, but miss the connection with the previous bit - which is not so strange, as I didn't understand that bit.

>> Having explicit mutable locations ..

*> cells would have been better than mutable variables,

> how much of Scheme's fundamentals are
> based on sheer contingency.

Agreed.  But I see it as a goal to remove such warts bit by bit and clean up the language.  Nowadays it is perfectly feasible to build a cell layer underneath the language, lambda's compiling into cell-layer code that happens to assign mutable cells to all variables.  A fraction more compilation time, the same resulting code, but the option to code directly in the cell layer and get more efficient code with less possibility of error.

Let's (disregarding my earlier remarks concerning case sensitivity) assume that 'lambda' builds closures using mutable cells with the behaviour we have come to expect, and 'Lambda' builds closures with immutable variables.  Likewise let/Let, et cetera.  It is trivial to define the lower case versions in terms of the upper case ones, so this is hardly a burden on the spec, and the lower case ones can be in a library.
The upper case ones are cleaner, requiring a smaller spec (e.g. set! becomes a procedure, set-car! and its ilk are no longer needed, (set! (car ..)) sufficing), so this is clearly a language clean-up that doesn't break existing programs but removes a restriction.  Fewer concepts + fewer restrictions --> Clinger-proof.  Clinger-proof + leading to faster code --> a Good Thing.

>> And other locations, such as the car and cdr of a pair, already excape,

> Well, why not provide both escaping and non-escaping locations?

Because (1) it is an extra concept with an extra restriction; (2) People routinely build structures around them that can escape in their entirety, which is more code, slower and more bug-prone; and (3) they only escape if you make them do so anyway.

>> some kind of locking will be necessary.
>> I think locations are the natural place for that:

> a single location is far too fine-grained for comprehensibility.
> Programmers are only human.

But compilers aren't.  The presence of locations doesn't preclude any of the existing approaches, but it allows a low-level approach by the compiler.  After all, it is the compiler that will write most parallel code, not the programmer.  Wherever (in-)variables are immutable, the compiler can parallise to its CPU's content, but when locations pop up that is a warning sign.  Whenever it can prove that no clash occurs, it can still write parallel code, and where it cannot prove it it can impose a locking mechanism (with priority to avoid deadlock: in case of doubt, evaluate left-to-right or whatever).  Whenever the programmer knows better, she can use higher-level constructs and relieve the compiler of its responsibilities.

>> Just reading or writing is no problem,
>> but writing a value that is computed from a read is.

> Alas, knowing whether a value to be written
> is computed from a value read is Turing-complete.

I know - that's why the 'whenevers' are in my previous paragraph.

>> the value of load would then be
>> the value of the last expression in the file loaded.

> it can't now be standardized.

May I ask why?

>> * Write/read invariance.

> across arbitrary Schemes
> running on arbitrarily different machines

I didn't mean that - even though I see fewer problems than you do (the code written/read could even be some flagged s-expression containing the required information, and every Scheme could interpret this in its own way - the way I can share a vector between systems).  I was rather thinking about e.g. dumping and reloading in a later session of the same Scheme (as in game saving/restoring), or of process sharing between running copies of the same Scheme.

> That serves some people's purposes,
> but definitely not everybody's.

It could be an optional feature.  I wrote many of these things before thinking in terms of small and large Scheme.

>> The principle of least surprise is already violated with macros. Macros
>> must be bound before use; there is no equivalent to anonymous lambdas.

> What's the point of that?

Have you never wanted to parametrise over, say, 'and' and 'or' without losing the short-circuit evaluation?  Of course, one can create higher-order functions around those macros and wrapping the arguments in chunks, but that is cumbersome, slow and ugly.  And that is only a very simple example.

Scheme currently suffers from macroitis: once something becomes a macro, other things may get infected.  Imagine Scheme only provided 2-argument logical macros, and I want to write a function that takes one of them and returns an arbitrary-arity version - a fold.  I am strongly pushed towards writing not a function, but a macro for that - possibly besides a fold function that folds functions.  Duplicating functionality (and wildly diverging code because one is in a rule language and the other in, well, Scheme) because some restriction was imposed on macros.

> If the rewrite rules stand next to the original code,

Ah, but normally they wouldn't - just as anonymous lambda's tend not to stand near the definition of a function that applies them, but near a call of that function.

>> Flushing an output port is the symmetric opposite
>> of peeking at an input port - or it ought to be.
>> Scheme could have a clean mathematical notion of ports

> There's an interesting idea,
> but I don't know what to do with it either.

I have lots of little bits of idea, but they don't build up to some whole yet.

>> * Time. Time is an elusive concept.

> What you describe here (snipped)
> is an interesting idea, but by no means core,
> to say nothing of jewel-like.

I basically meant to say: there is so much going on, let's just allow the user to define notions of time and how they relate, and allow for the fact that different notions may not be mappable (especially concerning the future, but also concerning much of the past).

I didn't even mention that most of the individual systems aren't even properly cyclic and dependent on future contingencies.  If we decide something will happen exactly five years from now, and a black hole passes at short distance of the sun and pulls it away from us - when is the instant we had decided on?  If we had decided on a span of five Muslim years and the black hole reversed the rotation direction of the moon, would that time never appear, but instead previous years be doubled?

> WG2 will have a date-time library
> that may owe something to these notions.

Thanks again.

>> Wouldn't a Schemish string be a sequence of character objects (soco),

> the IEEE restriction

Ah.  I didn't know there was such a thing.

> R7RS-small has classical strings,
> but allows implementations ..

Any chance of them allowing the user to build strings (without her building an interpreter for them, obviously)?

Well, I suppose by now you are very sorry you answered me..

Thanks again!

Scheme-reports mailing list