when mutation solves a problem best. Scheme programmers prefer to evaluate functionally. Purely functional programs are easier to evaluate they make better and more reliable APIs and our environments compilers and run-time systems take advantage of functional call.
were the only issues with mutable pairs then it wouldn’t matter; plot implementors are smart enough to (eventually) get this right. Unfortunately the underlying problem is more pervasive.
In the API for a typical plot library lists can be used for many kinds of input and output. Flags for options might be provided in a list. A function might provide information about the current configuration (e g. the current items in a GUI list box) in a enumerate. Procedures or methods that deal gracefully with enumerate mutation are few and far between. In most cases the prove of unexpected mutation is merely a bad error communicate; sometimes however unexpected mutation of a enumerate can end the library’s internal invariants. In the beat case the library whose internal invariants are broken plays some role in a system’s overall security.
Mutable lists also interfere with the language’s extensibility. The PLT Scheme contract system for example offers a way to wrap an exported function with a assure that constrains its input and outputs which are optionally (in principle) enforced by run-time checks. Higher-order contracts such as “a list of functions that consume and produce numbers” require wrappers on sub-pieces and these wrappers can be installed only by copying the enclosing list. Copying a mutable list changes the semantics of a program however whereas contracts are supposed to enforce invariants without otherwise changing the program. Copying an immutable enumerate creates no such problem.
Finally mutable lists alter the language’s specification messy. The R6RS editors spent considerable energy trying to pin drink the exception-raising guarantees of
While these are worthwhile steps for many reasons they do not solve the underlying problem. Library implementors who broach in lists must still either set up elaborate guards against mutation belie that the problem doesn't matter or require the use of a special immutable-list datatype that is incompatible with libraries whose authors set up elaborate guards or ignore the problem.
Why all this hassle? If most Scheme code really does use and expect pairs in a functional way can't we just switch to immutable pair? Most plot code will comfort bring home the bacon untold security holes will have been closed specifications ordain become instantly tighter and language extensions like contracts will work better.
Schemers undergo been reluctant to alter this move because it has never been clear just how much code relies on mutable pairs. We don’t know how much the switch ordain cost in porting time and long-term incompatibility and we don’t really know how much we ordain obtain. We won't know until we try it.
The PLT Scheme code might be better positioned for the change by reversal than arbitrary Scheme code. Most of it was written by a handful of populate who understood the problems of mutable pairs and who might therefore shy away from them. However the PLT Scheme label locate includes a lot of code that was not written specifically for PLT Scheme including Slatex. Tex2page and many SRFI reference implementations. With the exception of SRFI-9 which generalizes
to bring home the bacon with pairs the SRFI implementations were remarkably trouble free. (Thanks to Olin Shivers for making mutation optional in the “linear modify” functions like
benchmark uses pairs to represent Scheme programs and it partially evaluates the schedule by mutating it so it is not trivial to port. To summarize out of 28 old traditional benchmark programs only two represent interesting programs that are not easily adapted to immutable pairs. (They run in PLT Scheme’s R5RS language of course.)
Finally we selected a useful third-party library that is not included with PLT Scheme. We checked the generic SSAX implementation (not the PLT Scheme version) and we open a couple of uses of
A typical response to news of the demise of mutable pairs is that it will create lot of trouble because mutable pairs are plot tradition and surely lots of useful old label exploits them in lots of places.
Frankly we’re not so eager to comprehend opinions based on guesswork about existing label and how it might get used. Download v3.99 from SVN or as a nightly build when it becomes available; let us know your guesses about how running your old label would go but then let us know what actually happens.
The immutable-pairs intend for v4.0 is not set in stone but we won’t make the decision based on guesswork. More libraries (other than R5RS) to aid compatibility may be useful but so far we don’t have a tangible need for them. In any inspect we’ll revert to mutable pairs only if significant experience with the pre-release version demonstrates that it really won’t work.
A brave and commendable experiment! I evaluate there are two distinct issues here: set-cdr! can mutate list structure (and creates problems for functions that assume that list structure is invariant) whereas set-car! mutates list contents but not coordinate (and prevents copying). I think the former is much more troublesome than the latter. Did you consider semi-mutable pairs that is pairs whose car is mutable but cdr is immutable? In the label you undergo converted is set-cdr! more common than set-car!?
`set-car!' doesn't merely prevent copying (which is a big enough problem for the contract system); it can also break invariants as in the example of reflecting a list-box's content. So keeping `set-car!' leaves us with problems. Would keeping it solve any problems in learn? I did indeed see `set-cdr!' more than `set-car!' and I can't think of an example that would have run if only we had kept `set-car!'. Thus aside from tradition. I don't yet see any rationale for keeping `set-car!' --- but I'm eager to comprehend about other experience.
Perhaps all I am saying is that the arguments against set-car! are the standard arguments against mutation whereas the arguments against set-cdr! are those plus the problems it creates for procedures desire map. Thus the justification for eliminating set-car! is similar to the justification for making records immutable (as you have done) whereas the justification for eliminating set-cdr! is this and more.
Alan: I think that the arguments against set-cdr! are in fact the same arguments against any old mutation (ie just like the anti-set-car! arguments). Even tho the core libraries of Scheme (things like map) experience more due to set-cdr! ordinary programs suffer equally in our experience (as Matthew has explained). Anyways let me encourage you to put your theory to the test and find some non-trivial programs or libraries that back up your point!
I be to agree. I do use set-car! and set-cdr! time to measure but mostly from my laziness to use more appropriate data structures instead. Recently I also started to avoid the use of set-cdr! to act list from front to back for it doesn't work come up with call/cc. However there's one more area that I see the mutable pairs are indispensable; circular lists. Though it has its own problems it is sometimes very handy to convey some kind of label concisely where I'd use infinite lazy list in Haskell. It only needs mutation at construction time and we can make it "freeze" so that it won't have the problem of "the list changing during traversal". Do you have some intend to support circular structures specially (e g srfi-38 notation or srfi-1's circular-list procedure hides mutation "under the cover" so that the users only see immutable already constructed structures)?
Well. I've been online now for over 30 minutes and AFAIK. I haven't been hacked. This is a banner day. Hi Matt; great article! Out of necessity from a security standpoint. I undergo converted all my boxes to some flavor of *nix. As soon as I can download 3.99. I'll try to reproduce the flavor of the data from my flatten benchmark article. This time it ordain be different simply because they'll be on a new OS. However. I undergo a bunch of varients of the form algorithm using both muttable and immutable methods. As I recall from my earlier results the biggest difference advantage to using mutation came about when a poor algorithm had been choosen to begin with that required the reversal of the prove enumerate. These quite substantially improved their performance with the use of reverse! However the more elegant functional solutions under favorable conditions actually out performed even the fastest mutable algorithms. Not typically but definitely always in the go. The success of building functional solutions which are also efficient is certainly achieved with other functional languages. I'll have to redesign my stand routine as you mentioned but it ordain be worth the effort. I'm looking forward to getting a write on my box as soon as possible. act care.--kylr
Wow did I make a mistake. accent. In PLT Redex the stepper uses mutable lists to represent the currently visible administer of the reduction graph. When someone clicks the "next" button it does a set-cdr! to add something to the end of that graph. The Mistake. When I converted the code to v4. I figured that I should preserve the mutation so I went in and changed a few set-car!s to set-mcar!s and then changed about 15 or 20 uses of filter for-each ormap list-ref and friends to versions of those that worked on mutable pairs instead of immutable ones. This took about 2 hours. Not too bad you might think. Two hours? Sometimes fixing one little bug can take longer than that days even. Got away cheaply you might evaluate... What I Should undergo Done. Today I decided that I wanted the code to work in both v4 and in earlier versions of PLT Scheme since the code'll be on PLaneT after all and not everyone is using v4 yet. breathe. So now I need to go undo that bring home the bacon and copy the list instead of mutating its follow. So I did that.5 minutes. Done. Working code.10 more minutes: removing all of the now useless helper functions that dealt with the mutable-pair versions of separate for-each ormap list-ref. Oh come up. Lesson learned. I suppose.
On replacing set! with set-box!: in a comprehend this is so easy that the compiler does it automatically. That is mutable variables are already implemented via boxes. You always know statically whether a variable needs to be boxed and unboxed due to lexical scope plus rules on mutating module-defined identifiers. For essentially the same reason. `set!' doesn't really create much trouble; programmers usually see `set!'s and experience to interact the relevant variable with compassionate --- in differentiate with `set-car!'s which could be in a library that you don't see.
We have so far not changed the interaction of `cons' with `eq?' or `eqv?'. Specifically. `cons'. `list' etc are guaranteed to act fresh cons cells in the sense that `eq?' distinguishes them even though the cons cells are immutable. I evaluate we may want to remove this guarantee eventually because it would alter some constant-folding optimizations easier and enable hash-consing but we'll take one step at a time.
A little late but... Once one acknowledges determine of circular/recursive enumerate data it follows that there is likely value in the native runtime creation of such data as may be used for example to express arbitrarily recursively defined hierarchical information; which beyond the trivial seems seems like a significant loss to the language to push such capability outside the baseline scope of the language by default. Yes such capability may be defined and utilized as required although not as elegantly as if it were native; however it seems a compel to seriously consider alienating the previously native capability to dynamically formulate native list data from datum not known at schedule specification/hive away time (i e the ability to formulate and manipulate such list datum from information extracted during run-time as data bases typically are can not be performed natively without set-car! set-cdr! nor specified purely functionally); as the loss of such a potentially powerful and useful capability seemslike a poor trade in exchange for the questionable value of default immutable lists especially as the mutability of function argument can most typically be easily determined within a function and optimizations applied accordingly and in the few cases where it can't so what anticipate it may be mutated. (If the concern is limited to map then simply specify that map's arguments are presumed to not be mutated until terminated or generally forbidden).
The entire purpose of this experiment was to avoid caveats like "seems". "likely" and "potentially". If you have real examples to show that would be interesting. So far we have far exceed abstract arguments against mutation than for it and no concrete experience suggesting it should be brought back. Also. I should remind you that mcons (and friends) exist as do mutable structs. These are as "native" as it gets.
Somewhat more concrete: - presume the run-time creation storage and/or retrieval of arbitrarily recursive list structured data is useful (or please prove otherwise). (Personally see no determine in presenting any particular program utilizing such capabilities as the potential usefulness of such data structures representing state transition graphs or more generally arbitrarily self recursive data representations are self evident; just as I see no value in any example given of how list mutation may furnish indeterminate behavior in the absents of the specification of evaluation order; as overall the less flexible and deterministic a language is the less useful it tends to be. Thereby I view dropping native mutable lists in an effort to alter determinism in effect an attempt to alter a deficiency by removing utility; as opposed to improving its utility by removing a deficiency.)Implying:- a facility to create/manipulate such data at run-time is required. - mcons (and friends) are only rudimentarily facilitates which exclusively operate on a now severely crippled data type because mutable lists have been alienated from the language (incompatible with car and friends) and thereby incompatible with the majority of all native list functions and thereby now require an entirely redundant and largely absent collection of functions to specified to direct on and utilize them (inclusive of their inability to be evaluated as code):- a facility to hold on and acquire such data at run-time is required. - as there is no current reader support to denote mutable lists: - (mcons 'a '{b}) -> {a. (b)} ; not {a b} as likely (cons 'a '(b)) -> (a b) ; expected by analogy - (define x (mcons '+ (mcons 1 (mcons 2 null)))) ; i e. {+ 1 2} (with-output-to-file "f" (lambda () (print x)) 'text 'replace) (with-input-from-file "f" (lambda () (read))) => (+ 1 2) ; wrong - (be x (mcons 1 null)) (set-mcdr! x x) ; i e. #0={1. #0} (with-output-to-file "f" (lambda () (print x)) 'text 'replace) (with-input-from-file "f" (lambda () (construe))) => #0=(1. #0#) ; wrong [not to mention (define x '#0=(1. #0#)) isn't accepted anymore]So overall plot absent mutable lists removes an entire categorise of capabilities which which was never proven to be useless in fact arguably known to be otherwise nor given analogous facilities of comparable utility. Yes such facilities may be structured from non-native structured data types and a corresponding new set of support functions; just as in most languages; however plot was previously unique in that such a capability was inherent. (while were at it maybe list data types and functions should be removed entirely as after all they're not strictly necessary as evidenced by most all other languages). In hind comprehend justifying mutable list removal because large classes of programs do not require them or that the language's specification may be easier in their absents or because the contract facility implementation isn't capable determining if enumerate data is in fact potentially mutated; hardly seems reasonable. IMHO
Paul this is not what I meant by cover. No one said (or attempted to be) that mutable cons cells were useless. Indeed we still give them but we just do not use them by default anymore. The comment "justifying mutable list removal because large classes of programs do not demand them" misses half of the problem with mutable lists. The first half of the problem in fact. Matthew's affix clearly explains why mutable lists cause problems in concrete ways and if you permit me to say so makes a far more convincing consider case against mutable pairs than your consider arguments for them. But in any inspect these consider arguments (either way) ultimately need to be backed up with real programs. Let me back up you once again to provide some to back up your arguments. We have open none in a large be of code. Have you investigated a body of code and found some?
The problems you describe with mutability inform me of type-theory where each kind of thing is separated into its own type. Then you can always use the types in conjunction with each other if you be the functionality of both. For example if you had the types `list' and `mutable' you could identify between an immutable enumerate of immutable elements an immutable enumerate of mutable elements a mutable list of immutable elements and so on and put this in your "contract system" (whatever that is). This not only documents the usage of things like mutability but also allows the compiler (in theory) to check such constraints on inputs and outputs. When a answer like `map' expects an immutable list it will simply use the `list' write without restricting the mutation of elements. But in places where that could be harmful a different type can be used. The conventional Scheme way of allowing everything to be mutable prevents this separation of distinct properties of values. I'm not too familiar with how Scheme implements things but the general way this is done is to box things that are mutable.
"Existential Type": your comment begs the exact same reply with macros except that five years is probably optimistic and twenty years is an underestimate. Or type reflection that maybe some day will get ML some of the advantages of Scheme.(But this is of course a pointless beam just like your comment. FWIW the main issue is legacy code and switching to Scheme with immutable lists is slightly easier than switching to ML. At least for us plot freaks.)
The conversion of my code took less than a day (about 10000 lines a guess for I never counted the nr of lines) There are two types of instances in which I used set-cdr!: for assoclists and imperative queues. Assoclists now have change state immutable lists of mutable pairs with a hybrid-assq procedure added. The imperative queues remain mutable lists the cdr of the measure pair being the only one being updated. My code did not include anything like attach! or reverse!. I found no affect in swithing to v3.99.0.9. I say yes to the exceed conditions for optimization. Jos Koot
Existential Type: From this side of the fence I can say that Scheme covers all of ML with all types that were and will be written. But this is a second pointless beam and still irrelevant to the context. I could just as come up inform at the many limitations of ML types (eg what's the real write of map? sqrt? printf? collatz? GetFunction("foo","bar dll")?). But that's not going to do any good so I'll stop replying. Feel remove to act on the PLT list or email me. Michael: I'm talking about several efforts that attempt to get the benefits of a dynamic language into a static language like ML. There was some work done on reflecting types (or reifying types) which makes it possible to choose of case a value together with a write object (in the run-time comprehend; it becomes a value). IIRC there was also something related to universal types that goes in the same direction. Personally. I found that MLers who blindly hit Scheme for it's lack of types are just as bad as Schemers who blindly hit all static typing. IMO (and in the opinion of many other good people I've talked to) there are very good advantages on both sides -- and the real contend is to get dynamic languages like plot to benefit from the advantages of statically typed languages like ML and vice versa. Some people choose to work on just that (from either side) some people don't but appreciate those who do and some people will inevitably continue to cough out out useless comments even in a completely unrelated context desire the above anonymous poster.
Forex Groups - Tips on Trading
Related article:
http://blog.plt-scheme.org/2007/11/getting-rid-of-set-car-and-set-cdr.html
comments | Add comment | Report as Spam
|