On Jun 14, David Rush wrote: > On 14 June 2010 06:56, Eli Barzilay <eli@barzilay.org> wrote: > > > The bottom line is that this: > > > > (define (map f l) > > (define (loop l) > > (if (null? l) '() (cons (f (car l)) (loop (cdr l))))) > > (if (list? l) > > (loop l) > > (error "poof!"))) > > > > can be proved as a correct implementation of map *assuming* no changes > > to the list ever occur in the call to `f', or more generally during > > the dynamic extent of the call to `map'. If you're one of these > > theoretical people, there's not much else to see here. > > > > The problem is on the side of the *working* programmer > > Your "*working*" programmer is either made of straw or demonstrably > incompetent in building semantically sound interfaces. If the list > structure is part of the invariants in the interface, then there > should be no other piece of code touching it. So ... you're suggesting that `map' is never used with 3rd party functions, or more generally, HOF and lists go together only as long as they're my functions? I guess that would be a solution too. It shows even better why this is a straitjacket. > > given only mutable pairs, the only way to guarantee that your own > > pair-related invariant (such as `list?'ness) is not broken is to copy > > it: > > > > (define (map f l) > > (define (loop f l) > > (if (null? l) '() (cons (f (car l)) (loop f (cdr l))))) > > (if (list? l) > > (loop f (loop values l)) > > (error "poof!"))) > > > > In almost two decades of reading and writing Scheme code, I have not > > seen this done even once. > > If this was *that* big of a problem, or worse - as big as the _goto_ > problem - I think we'd have seen a larger reaction before this, > hmmm? SET-CAR! and SET-CDR! and their predecessors RPLACA and > RPLACD have been around a lot longer than two decades even. Sure, and the bugs were (and are) still there. > > To put this differently: Schemes (and Lispers) have been dreaming > > for a really long time about Scheme/Lisp operating systems and > > other large scale systems. > > And, interestingly enough, they are still almost entirely written in > C, assembly, and other *even less safe* languages. So what does that > tell us, hmm? It tells us that it's possible, which I've never disputed. The question is the amount of pain suffered on writing such a thing. And I agree that it's "less pain than C and assembly" -- but that bar was not that high to begin with. > [...] > > The bottom line is that mutation is harder than it first looks. Yes, exactly. > The bottom line is that every example thus far has been more full of > design flaws than an undergrad senior project. If you want Haskell, > go program in it. Please show me your definition of `map'. (But if the above is correct and you never use it with any functions except your own then it doesn't matter -- but then what's the point of using scheme.) > > Bugs involving state will almost always be found in some code that > > is syntactically unrelated to the buggy code. I've spent too many > > nights tracking such bugs to just let myself go with the "assuming > > no bad mutation" flow and hope for the best. > > My day job is about 80% debugging (read that as "reasoning about") > code written in dialects of C by other people, accumulated over the > course of 20 years, without documentation or even any institutional > memory or its original provenance. I assume *nothing* because nearly > every invariant has been smashed as this program evolved the *BIG* > ball of mud pattern all on its own. [...] (Yes, I'm sure everyone expects C to be more painful.) > It's a poor workman who doesn't know when to get better tools. And a > better saw won't help you measure the right length before you > cut. Mutable pairs is most emphatically *not* the problem here. (Same as above: show me your `map'. Or any robust code that uses pairs.) > > But *why* lump mutable data together with something as fundamental > > as pairs? Where's the "jewel-like"ness of that? > > Because Scheme allows mutability as a top-level entity without > reference to a state monad. Its a foundational part of the design > space. > [...] > Haskell is over -> there. You too failed to quote the part of my post where I explicitly said *explicitly* that I'm not advocating abolishing mutation. (Not only do I use mutation, I very often criticize Haskell for wrapping mutation-like code in a monad, only to write code that is as imperative as any other C code.) > > IMO, features that can be separated into N sub-features should > > always be separated > > So are you ready to take on the notion that all functions should > only have one argument and deal with the necessity of re-defining > the procedure call semantics in a way that is syntactically > consistent with legacy code, while supporting a proper decomposition > of the Scheme calling sequence, thus making CALL-WITH-VALUES > obsolete? No, I didn't think so. (Huh?) > > So the whole dilemma (if I had one, that is) boils down to the > > question of preserving legacy code. > > Specifically, it boils down to the ability to bring in code which > uses a-lists as a mutable lookup table. I can't do that with R6RS or > PLT anymore without (admittedly minor) surgical alterations. ^^^^^^^^^^^^^^^^ Yes. And in the next sentence (which you didn't quote) I said "At this point things become subjective". -- ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: http://barzilay.org/ Maze is Life! _______________________________________________ Scheme-reports mailing list Scheme-reports@scheme-reports.org http://lists.scheme-reports.org/cgi-bin/mailman/listinfo/scheme-reports