>>>>But then we're back to the need to distinguish between expected and >>>>unexpected changes, right? (or better, unexpected changes that you can >>>>and cannot carry out)
>>>I'm not sure I understand what you mean, but you can never make it >>>"impossible" to introduce a change.
>>I mean, at runtime.
> There are changes that cannot be done at runtime even in Lisp. For > example, redefining a function as a macro. So this issue is orthogonal to > language. It is, as I said, a development environment issue.
Well, contrary to popular belief, I don't think that Common Lisp is the perfect language. I only think it's damn close. ;)
>>>The worst you can do is make it so >>>that introducing certain changes requires you to recompile the entire >>>system from scratch. (The problem with most static typing systems today >>>is that they seem to run in this mode by default.) And that can only >>>happen if you lied to the system when you promised to refrain from making >>>any more such changes in exchange for more compile-time safety assurances >>>and optimization.
>>...or you had the wrong idea which parts of the system are stable and >>which aren't.
> Isn't that the same thing?
Maybe. "if you lied" is a strong statement.
> Once again, the same thing can happen in > Lisp. One can (and often does) elect to deploy a system without the > ability to change code at run time. The only question is whether you have > to do extra work to make it possible to change things at run time, or > whether you have to do extra work to make it impossible. Neither option > is "better" in any absolute sense. There are circumstances where being > able to make changes at run time is desirable, and circumstances under > which it is not (e.g. in situations where security is important).
Sure. No objections here.
> IMO the best of all possible worlds would be an environment where I could > flip a switch to various settings, from "development" where things were > maximally flexible and dynamic to "secure" or "deployed" or something like > that, where things were maximally static. The only language I know that > even strives for this is Dylan.
Yes, Dylan's concept of sealing is a pretty good idea. And I think one can go even further in that direction.
The important point is that we both agree that no approach is "obviously" superior to the other, according to Gat's First Law. ;)
Pascal
-- Tyler: "How's that working out for you?" Jack: "Great." Tyler: "Keep it up, then."
Fergus Henderson <f...@cs.mu.oz.au> writes: >>so really, when you say that you are not interested in changing >>stuff at runtime, you are actually making a choice. you are >>limiting the applicability of your preferred language
> Perhaps, but not very much, because by designing my software > appropriately, I can ensure that all but a small kernel can be > upgraded without stopping the machine. This does not require the > ability to make unanticipated changes to the code of a running > program.
OK. except in my case:
(string= (translation-of "designing appropriately") "not engaging in compulsive static typing") ==> T
> > >>But then we're back to the need to distinguish between expected and > > >>unexpected changes, right? (or better, unexpected changes that you can > > >>and cannot carry out)
> > > I'm not sure I understand what you mean, but you can never make it > > > "impossible" to introduce a change.
> > I mean, at runtime.
> There are changes that cannot be done at runtime even in Lisp. For > example, redefining a function as a macro.
Actually, this is not true. I can portably redefine #'foo as a macro by doing the following:
Admittedly, it might be considered a hack, but precisely the kind of hack which makes Common Lisp so powerful.
> IMO the best of all possible worlds would be an environment where I could > flip a switch to various settings, from "development" where things were > maximally flexible and dynamic to "secure" or "deployed" or something like > that, where things were maximally static. The only language I know that > even strives for this is Dylan.
This is a good goal, and one which Common Lisp is not necessarily adverse to. A third switch setting that I think would be even more widely used is the setting where such static (but not quite maximally static) state comes with a hook, such that if conditions were changed (such as redefinitions, etc) that the hook would tug at a virtual string that runs through the state and pulls it apart, reverting it back some distance back toward dynamic operation until it is re-optimized in the pseudo-static way but incorporating the changes. This is essentially what happens in some cases in CLOS; for example, there are MAKE-INSTANCE calls which turn into very efficient calls to VECTOR, but any changes to the class or additional methods will snap the link and force at least the call to go through the dynamic path. If dependencies are known, then, those functions that call make-instance in this manner could then be recompiled and thus re-statified (this last part isn't done automatically in CL, but from what I understand, Screamer does precisely this kind of thing, so such a thing is at least possible).
In article <bpb6tk$39...@newsreader3.netcologne.de>, Pascal Costanza
<costa...@web.de> wrote: > > Isn't that the same thing?
> Maybe. "if you lied" is a strong statement.
There is a long tradition of hyperbole in computer science, e.g. "Global variables are evil." The word "evil" means something different in that context than it does in, say, the phrase "terrorism is evil." Likewise, lying to a machine doesn't have the same moral connotations that lying to a person does. At least, that was my intention.
> The important point is that we both agree that no approach is > "obviously" superior to the other, according to Gat's First Law. ;)
> > > >>But then we're back to the need to distinguish between expected and > > > >>unexpected changes, right? (or better, unexpected changes that you can > > > >>and cannot carry out)
> > > > I'm not sure I understand what you mean, but you can never make it > > > > "impossible" to introduce a change.
> > > I mean, at runtime.
> > There are changes that cannot be done at runtime even in Lisp. For > > example, redefining a function as a macro.
> Actually, this is not true. I can portably redefine #'foo as a macro > by doing the following:
> Error: #<Compiled-function BAZ Macroexpander #xFE6B0E> can't be
FUNCALLed or APPLYed.
> While executing: "Unknown" > Type Command-. to abort.
See the RestartsŠ menu item for further choices. 1 >
It's not enough to redefine BAZ, you also have to find all the funcitons that were compiled on the assumption that BAZ was a function and recompile them too.
> > IMO the best of all possible worlds would be an environment where I could > > flip a switch to various settings, from "development" where things were > > maximally flexible and dynamic to "secure" or "deployed" or something like > > that, where things were maximally static. The only language I know that > > even strives for this is Dylan.
> This is a good goal, and one which Common Lisp is not necessarily adverse > to. A third switch setting that I think would be even more widely used > is the setting where such static (but not quite maximally static) state > comes with a hook, such that if conditions were changed (such as redefinitions, > etc) that the hook would tug at a virtual string that runs through the > state and pulls it apart, reverting it back some distance back toward > dynamic operation until it is re-optimized in the pseudo-static way but > incorporating the changes. This is essentially what happens in some > cases in CLOS; for example, there are MAKE-INSTANCE calls which turn into > very efficient calls to VECTOR, but any changes to the class or additional > methods will snap the link and force at least the call to go through the > dynamic path. If dependencies are known, then, those functions that > call make-instance in this manner could then be recompiled and thus > re-statified (this last part isn't done automatically in CL, but from > what I understand, Screamer does precisely this kind of thing, so such > a thing is at least possible).
> (Glasgow Haskell's "Dynamic.cast" also almost fits into this category. > The reason I say "almost" is that it is not 100% safe; if you try > hard enough, you can abuse it to break run-time type safety.
I didn't believe it, but it's actually not that hard. Is the code below like what you had in mind, or do you have another way? (Seems like a good argument for always deriving Typeable.)
Jesse Tov <t...@eecs.harvREMOVEard.edu> wrote: > Fergus Henderson <f...@cs.mu.oz.au>: > > (Glasgow Haskell's "Dynamic.cast" also almost fits into this > > category. The reason I say "almost" is that it is not 100% safe; if > > you try hard enough, you can abuse it to break run-time type safety.
> I didn't believe it, but it's actually not that hard. Is the code > below like what you had in mind, or do you have another way? (Seems > like a good argument for always deriving Typeable.)
It's possible to implement Dynamics without using any unsafe features using Haskell 98 + existentials (or local rank-2 universals) as described in "A Lightweight Implementation of Generics and Dynamics". Presumably GHC doesn't use that technique for efficiency reasons (also, I'm pretty sure Dynamics were implemented before that paper was written). I believe Hugs uses the same code, but implicitly "derives Typeable" so this issue can't come up.
Paul Dietz <paul.f.di...@motorola.com> wrote: > I question the assertion that ones needs many additional tests to > test type correctness.
One key experience for me was, when reading about unit tests and TDD for the first time, I was completely puzzled by the nature of unit tests that were suggested. I couldn't get it in my head why such trivial tests should be of any use. Then, after some time I figured out that they *needed* those tests, because there was no static type checking to compensate.
For some first-hand experience of a dynamic typist, see for example <Xns9327E3738674Fmacdonaldrjworldn...@204.127.36.1>
And that's only with a good IDE with a lousy type system.
> Type incorrect programs will, in practice, very often fail on tests > that have been written for other purposes.
They may, or they may not. To be only *reasonably* sure that they fail you need quite a large amount of tests, and you have to control somehow the amount of code coverage your tests have.
Anything else just means crossing your fingers, and trusting luck.
Fergus Henderson <f...@cs.mu.oz.au> writes: > All [Lisp types] correspond to a single data representation which is the > tagged union of all of the different possibilities, i.e. a single "type" in > the sense mentioned above.
That's meaningless. If a function is defined on strings, and you pass it an integer, you'll get an error in Lisp. This is what ordinary programmers mean by data type. You're creating definitions that are almost deliberately designed to confuse. There is no interesting sense in which Lisp only has a "single" data type.
> Lisp's "type" specification sublanguage specifies subsets of values, > not data representations.
Incorrect. Yes, you can specify subsets, but you can also specify unions:
(I'll also note in passing that "square-matrix" now becomes a legitimate type in the Lisp program, but there is no built-in data tag in the implementation which indicates which data objects are members of this type, and which aren't.)
Unions, intersections, subsets, arbitrary computation, plus an extensive set of built-in types ... surely that's about all you could ask from any type definition system?
-- Don ___________________________________________________________________________ ____ Don Geddis http://don.geddis.org/ d...@geddis.org Stupidity: Quitters never win, winners never quit, but those who never win AND never quit are idiots. -- Despair.com
Dirk Thierbach <dthierb...@gmx.de> writes: > Paul Dietz <paul.f.di...@motorola.com> wrote: > > I question the assertion that ones needs many additional tests to > > test type correctness.
Agree.
> > Type incorrect programs will, in practice, very often fail on tests > > that have been written for other purposes.
That correlates to 3 9s in the logs on this stuff that I've kept.
> They may, or they may not. To be only *reasonably* sure that they fail > you need quite a large amount of tests, and you have to control somehow > the amount of code coverage your tests have.
> Anything else just means crossing your fingers, and trusting luck.
Don Geddis <d...@geddis.org> writes: > > Lisp's "type" specification sublanguage specifies subsets of values, > > not data representations.
> Incorrect. Yes, you can specify subsets, but you can also specify unions:
So the union of two subsets is not a subset then?
> Unions, intersections, subsets, arbitrary computation, plus an extensive set > of built-in types ... surely that's about all you could ask from any type > definition system?
No. This is definitely not all (and AFAIC not even nearly so).
Erann Gat wrote: > In article <bpb6tk$39...@newsreader3.netcologne.de>, Pascal Costanza > <costa...@web.de> wrote:
>>>Isn't that the same thing?
>>Maybe. "if you lied" is a strong statement.
> There is a long tradition of hyperbole in computer science, e.g. "Global > variables are evil." The word "evil" means something different in that > context than it does in, say, the phrase "terrorism is evil." Likewise, > lying to a machine doesn't have the same moral connotations that lying to > a person does. At least, that was my intention.
OK, problems of a non-native speaker... ;)
Pascal
-- Tyler: "How's that working out for you?" Jack: "Great." Tyler: "Keep it up, then."
Matthias Blume <f...@my.address.elsewhere> writes: > Don Geddis <d...@geddis.org> writes:
>> > Lisp's "type" specification sublanguage specifies subsets of values, >> > not data representations.
>> Incorrect. Yes, you can specify subsets, but you can also specify unions:
> So the union of two subsets is not a subset then?
If sa is a subset of A, and sb is a subset of B, where A and B are disjoint, and usasb is the union of sa and sb, usasb is not necessarily a subset of either A or B.
This is pretty clear, so you must have meant something else.
>> Unions, intersections, subsets, arbitrary computation, plus an extensive set >> of built-in types ... surely that's about all you could ask from any type >> definition system?
> No. This is definitely not all (and AFAIC not even nearly so).
Can I ask what else you might want? Can I ask how you expect to get it if you cannot compute it?
> >> > Lisp's "type" specification sublanguage specifies subsets of values, > >> > not data representations.
> >> Incorrect. Yes, you can specify subsets, but you can also specify unions:
> > So the union of two subsets is not a subset then?
> If sa is a subset of A, and sb is a subset of B, where A and B are > disjoint, and usasb is the union of sa and sb, usasb is not > necessarily a subset of either A or B.
> This is pretty clear, so you must have meant something else.
Indeed. Where did you get the idea that A and B be disjoint? In the case under consideration they are both equal to the set of all values (and therefore to each other). So the correct formal rendering is: if s \subseteq U and also s' \subseteq U, then (s \cup s') \subseteq U.
> >> Unions, intersections, subsets, arbitrary computation, plus an extensive set > >> of built-in types ... surely that's about all you could ask from any type > >> definition system?
> > No. This is definitely not all (and AFAIC not even nearly so).
> Can I ask what else you might want? Can I ask how you expect to get > it if you cannot compute it?
See Pierce's definition of "type system". *That* is what I want. "Arbitrary computation" is precisely the thing that kills it.
> Can I ask what else you might want? Can I ask how you expect to get > it if you cannot compute it?
I might want the type of all functions that, when given a number, also return a number. What kind of a predicate would compute whether a given value is such a function or not?
> > Static typing probably becomes more important when you program in > > a functional style -- HOFs, partial applications, and so on.
> This is also my impression (as an "outsider", so to speak ;).
> When you start to write functions that generate functions that > generate functions that generate functions, the benefits of a static > type system might become much more important. (and I hope you don't > get the impression that I am trying to poke fun at such a programming > style!)
> It seems to me that Clean has a good way to reconcile pure functional > programing with a limited form of imperative programming, without the > need to use monads.
Not really. You have to write your program in state passing style, which is just as bad (or even worse) than monadic style (of course, you can simply hide it and use monadic style, no language support is needed for that). The explicit state passing style can be worse because if you decide you need, say, continuations you have to go through and change all your code, whereas with monadic style it would require less or even no changes to your code.
Nevertheless, there are a lot of nice and cool things in Clean. Another language you may want to look at is O'Haskell/Timber.
> Can anyone of the static typers comment on this?
Don't you mean Clean and Haskell users? This is a purity issue.
In article <67im81-9o1....@ID-7776.user.dfncis.de>, Dirk Thierbach <dthierb...@gmx.de> wrote:
> No, it doesn't. That's a requirement that you adapt to the *language* > you are using. If I use Lisp, I have to think in Lisp.
If I program in lisp, I must think in lisp -lisp syntax, lisp functions, etc. If I program in Haskell, I must think in Haskell - Haskell syntax, Haskell functions, etc. *and* I must also think in the HM style type system. It is this *additional* requirement, that I see as pointless, because it buys me essentially nothing. Virtually all the errors that the type system catches will be caught by other required testing anyway.
You are selling a solution to a problem that I don't have. I have to test anyway - see Eran Gat's post entitled "Why I don't believe in static typing."
N.B. please realize that you've mixed quotes from both me and Christopher Stacy without noting which of us wrote what.
In article <3FB8FAF2.D7440...@motorola.com>, Paul Dietz <paul.f.di...@motorola.com> wrote:
> I question the assertion that ones needs many additional tests to > test type correctness. Type incorrect programs will, in practice, > very often fail on tests that have been written for other purposes.
> Paul
This was precisely my point, sorry if I didn't make it clear, and thank you for pointing this out. That's why I find static typing so useless as an automatic testing methodology - without writing any additional tests, I find essentially all the type errors the static type checker would have found anyway.
What it is useful for is optimization - i.e., allowing the compiler to produce better code. But there are lisp implementations that do type inference, and will tell you how declarations would allow better code generation ( I'm thinking of cmucl and sbcl here). So with lisp, I can have dynamic typing, and the optimization help of a smart, type infrencing compiler as well.
Michael Livshin <use...@cmm.kakpryg.net> writes: >Fergus Henderson <f...@cs.mu.oz.au> writes:
>>>so really, when you say that you are not interested in changing >>>stuff at runtime, you are actually making a choice. you are >>>limiting the applicability of your preferred language
>> Perhaps, but not very much, because by designing my software >> appropriately, I can ensure that all but a small kernel can be >> upgraded without stopping the machine. This does not require the >> ability to make unanticipated changes to the code of a running >> program.
>OK. except in my case:
>(string= (translation-of "designing appropriately") > "not engaging in compulsive static typing") > ==> T
>thanks for the clarification,
I agree that one should not engage in _compulsive_ static typing. Situations do occur in which one should make use of run-time checking rather than static typing.
But I have not found any really convincing arguments as to why you'd want to use dynamic typing by default. Support for dynamic code update has been proposed as one such reason, but as discussed above we can achieve that without giving up static typing by structuring the application into components of some kind, and replacing whole components at a time.
-- Fergus Henderson <f...@cs.mu.oz.au> | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
Jesse Tov <t...@eecs.harvREMOVEard.edu> writes: >Fergus Henderson <f...@cs.mu.oz.au>: >> (Glasgow Haskell's "Dynamic.cast" also almost fits into this category. >> The reason I say "almost" is that it is not 100% safe; if you try >> hard enough, you can abuse it to break run-time type safety.
>I didn't believe it, but it's actually not that hard. Is the code below >like what you had in mind
Yes, that's the kind of thing I had in mind.
-- Fergus Henderson <f...@cs.mu.oz.au> | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
Don Geddis <d...@geddis.org> writes: >Fergus Henderson <f...@cs.mu.oz.au> writes: >> All [Lisp types] correspond to a single data representation which is the >> tagged union of all of the different possibilities, i.e. a single "type" in >> the sense mentioned above.
>That's meaningless.
No, it's not.
>If a function is defined on strings, and you pass it an >integer, you'll get an error in Lisp. This is what ordinary programmers >mean by data type.
Not always. A data type has a set of values and also determines a representation for those values. Here you are talking about the set of values, but the representation is also important. For example, it affects performance in a number of ways (space usage, costs of conversions between different representations, efficiency of particular operations).
>You're creating definitions that are almost deliberately >designed to confuse.
No, I didn't create any definitions here. You did! I'm just applying _your_ definition to Lisp. Let me quote it:
| When programming people (in general) talk about types, | they're talking about data representation within computer programs.
I agree that people do often use the word in this sense. This sense is however different to the Lisp sense.
>> Lisp's "type" specification sublanguage specifies subsets of values, >> not data representations.
>Incorrect.
No, you just misunderstood what I meant. When I said "subsets of values", I meant subsets of the set of all lisp values.
>(I'll also note in passing that "square-matrix" now becomes a legitimate >type in the Lisp program, but there is no built-in data tag in the >implementation which indicates which data objects are members of this type, >and which aren't.)
It is a legitimate type in the Lisp sense.
But in the types as data representations sense, which _you_ introduced, it is not a distinct type in its own right; it is merely a subtype of the type of all Lisp terms.
This is an important notion, because it has some useful consequences. For example, it implies that converting a list of square matrices to a list of Lisp terms should be a no-op.
-- Fergus Henderson <f...@cs.mu.oz.au> | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
-- Fergus Henderson <f...@cs.mu.oz.au> | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
>>(I'll also note in passing that "square-matrix" now becomes a legitimate >>type in the Lisp program, but there is no built-in data tag in the >>implementation which indicates which data objects are members of this type, >>and which aren't.)
> It is a legitimate type in the Lisp sense.
> But in the types as data representations sense, which _you_ introduced, > it is not a distinct type in its own right; it is merely a subtype of > the type of all Lisp terms.
> This is an important notion, because it has some useful consequences. > For example, it implies that converting a list of square matrices > to a list of Lisp terms should be a no-op.
If you want this, then 'deftype' is the wrong way to define a new type; 'defclass' or 'defstruct' would be more appropriate.
(Its a similar situation to defining new types in SML; depending on how you do it, you'll either get a new type representation or you won't...)
Here's a quote. In article <m1islmlx6p....@tti5.uchicago.edu>, you,
(Matthias Blume) wrote: > Lisp has sets of values (as does every other programming language). > By abuse of terminology, some of these sets end up being called > "types".
The abuse of terminology is yours, since these entities have never been called "sets of values" in lisp. There is no "sets-of-values-error," nor "sets-of-values-of," nor "sets-of-values-p," nor "check-sets-of-values," nor "sets-of-values specifier" in the ANSI Common Lisp standard. No one has ever called Lisp a "dynamically sets-of-valued language." They have been called "types," and lisp and smalltalk have been called "dynamically typed languages" for decades.
You are attempting to appropriate the term "type" so that it only applies to statically typed languages, possibly so that it only applies to HM style type systems. It is this attempted appropriation of a commonly used programming term of long standing that others find both offensive and obtuse. If you feel the need to coin some new term with the exclusive meaning of "types in a HM style type system," feel free to do so. But do not appropriate a term that has been used for decades in discussions of programming languages, both academic publications, and in converstation among programmers.
This is precisely the same sort of narrow redefinition of terms you attempted in the discussion of abstraction, where you tried to redefine "abstraction" so narrowly that it only applied to your favorite language(s). In general, one can't take a term of long standing usage, attempt to narrowly restrict its meaning, and expect those who have used the term for decades to submit to a gratuitous amputation of an essential part of their vocabulary.
Pascal Costanza <costa...@web.de> writes: >Fergus Henderson wrote: >> But with Lisp + soft typing, if I understand the approach correctly there >> is no way to be sure that the code is free of run-time type errors.
>I would hope that a (probably future) soft typing approach is as >complete as other static type systems.
I find that very unlikely -- it goes against my understanding of what the "soft" in "soft typing" means.
>Some features in Lisp stand in >the way of doing complete static analysis, but it should be feasible to >restrict the language for, say, the code written in some module to make >it statically checkable.
In that case, you'd have a statically typed subset of Lisp.
I think that such a beast would most likely be pretty awful compared to languages which were designed with static type checking in mind.
-- Fergus Henderson <f...@cs.mu.oz.au> | "I have always known that the pursuit The University of Melbourne | of excellence is a lethal habit" WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.