Re: What is a type error? [correction]

2006-07-18 Thread Darren New
David Hopwood wrote:
 Darren New wrote:
 
David Hopwood wrote:


public class LoopInitTest {
public static String getString() { return foo; }

public static void main(String[] args) {
String line = getString();
boolean is_last = false;

while (!is_last) {
if (line.charAt(0) == 'q') {
is_last = true;
}

// insert line into inputs (not important for analysis)

if (!is_last) {
line = getString();
}
}
}
}

which compiles without error, because is_last is definitely initialized.

At what point do you think is_last or line would seem to not be
initialized? They're both set at the start of the function, and (given
that it's Java) nothing can unset them.

At the start of the while loop, it's initialized. At the end of the
while loop, it's initialized. So the merge point of the while loop has
it marked as initialized.
 
 
 Apparently, Hermes (at least the version of it described in that paper)
 essentially forgets that is_last has been initialized at the top of the
 loop, and so when it does the merge, it is merging 'not necessarily 
 initialized'
 with 'initialized'.


No, it's not that it forgets. It's that the insert line into inputs 
unitializes line. Hence, line is only conditionally set at the 
bottom of the loop, so it's only conditionally set at the top of the loop.

 This sounds like a pretty easy thing to fix to me (and maybe it was fixed
 later, since there are other papers on Hermes' typestate checking that I
 haven't read yet).

You simply misunderstand the insert line into inputs semantics. Had 
that line actually been commented out in the Hermes code, the loop would 
have compiled without a problem.

That said, in my experience, finding this sort of typestate error 
invariably led me to writing clearer code.

boolean found_ending = false;
while (!found_ending) {
   string line = getString();
   if (line.charAt(0) == 'q')
 found_ending = true;
   else
 insert line into inputs;
}

It seems that's much clearer to me than the contorted version presented 
as the example. If you want it to work like the Java code, where you can 
still access the line variable after the loop, the rearrangement is 
trivial and transparent as well.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-17 Thread Darren New
Chris Smith wrote:

 Darren New [EMAIL PROTECTED] wrote:
 
I'm not sure what linear or uniqueness typing is. It's typestate, and if 
I remember correctly the papers I read 10 years ago, the folks at 
TJWatson that invented Hermes also invented the concept of typestate. 
They at least claim to have coined the term.
 
 Coining the term is one thing, but I feel pretty confident that the idea 
 was not invented in 1986 with the Hermes language, but rather far 
 earlier.

Yes. However, the guys who invented Hermes didn't come up with it out of 
the blue. It was around (in NIL - Network Implementation Language) for 
years beforehand. I read papers about these things in graduate school, 
but I don't know where my photocopies are.

NIL was apparently quite successful, but a niche language, designed by 
IBM for programming IBM routers. Hermes was an attempt years later to 
take the same successful formula and turn it into a general-purpose 
programming system, which failed (I believe) for the same reason that a 
general purpose operating system that can't run C programs will fail.

 Perhaps they may have invented the concept of considering it 
 any different from other applications of types, though.  

 From what I can determine, the authors seem to imply that typestate is 
dataflow analysis modified in (at least) two ways:

1) When control flow joins, the new typestate is the intersection of 
typestates coming into the join, where as dataflow analysis doesn't 
guarantee that. (They imply they think dataflow analysis is allowed to 
say the variable might or might not be initialized here, while 
typestate would ensure the variable is uninitialized.)

2) The user has control over the typestate, so the user can (for 
exmaple) assert a variable is uninitialized at some point, and by doing 
so, make it so.

How this differs from theoretical lambda types and all I couldn't say.

 What is being named here is the overcoming of a limitation that 
 programming language designers imposed upon themselves, whether from not 
 understanding the theoretical research or not believing it important, I 
 don't know.

I believe there's also a certain level of common-senseness needed to 
make a language even marginally popular. :-)  While it's possible that 
there's really no difference between type and typestate at the 
theoretical level, I think most practical programmers would have trouble 
wrapping their head around that, just as programming in an entirely 
recursive pattern when one is used to looping can be disorienting.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-17 Thread Darren New
Joachim Durchholz wrote:
 of no assertion language that can express such temporal relationships, 
 and even if there is (I'm pretty sure there is), I'm rather sceptical 
 that programmers would be able to write correct assertions, or correctly 
 interpret them - temporal logic offers several traps for the unwary. 

FWIW, this is exactly the area to which LOTOS (Language Of Temporal 
Orderering Specifications) is targetted at. It's essentially based on 
CSP, but somewhat extended. It's pretty straightforward to learn and 
understand, too.  Some have even added realtime constraints to it.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-17 Thread Darren New
Marshall wrote:
 I would propose that variables have identity, and values do not.
 In part this is via the supplied definition of identity, in which, when
 you change one thing, if something else changes as well, they
 share identity.

Maybe you gave a better definition the first time, but this one doesn't 
really hold up.

 of equality here is too narrow; it is only necessary to show that
 two things both change, not that they change in the same way.)

If I change X, then Y[X] changes also. I don't think X is identical to Y 
or Y[X], nor is it an alias of either.  I think that's where the 
equality comes into it.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error? [correction]

2006-07-17 Thread Darren New
David Hopwood wrote:
 
 public class LoopInitTest {
 public static String getString() { return foo; }
 
 public static void main(String[] args) {
 String line = getString();
 boolean is_last = false;
 
 while (!is_last) {
 if (line.charAt(0) == 'q') {
 is_last = true;
 }
 
 // insert line into inputs (not important for analysis)
 
 if (!is_last) {
 line = getString();
 }
 }
 }
 }
 
 which compiles without error, because is_last is definitely initialized.

At what point do you think is_last or line would seem to not be 
initialized? They're both set at the start of the function, and (given 
that it's Java) nothing can unset them.

At the start of the while loop, it's initialized. At the end of the 
while loop, it's initialized. So the merge point of the while loop has 
it marked as initialized.

Now, if the insert line into inputs actually unset line, then yes, 
you're right, Hermes would complain about this.

Alternately, if you say
if (x) v = 1;
if (x) v += 1;
then Hermes would complain when it wouldn't need to. However, that's 
more a limitation of the typestate checking algorithms than the concept 
itself; that is to say, clearly the typestate checker could be made 
sufficiently intelligent to track most simple versions of this problem 
and not complain, by carrying around conditionals in the typestate 
description.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error? [correction]

2006-07-17 Thread Darren New
Darren New wrote:
 Now, if the insert line into inputs actually unset line, then yes, 
 you're right, Hermes would complain about this.

Oh, I see. You translated from Hermes into Java, and Java doesn't have 
the insert into statement. Indeed, the line you commented out is 
*exactly* what's important for analysis, as it unsets line.

Had it been
   insert copy of line into inputs
then you would not have gotten any complaint from Hermes, as it would 
not have unset line there.

In this case, it's equivalent to
if (!is_line) line = getString();
if (!is_line) use line for something...
except the second test is at the top of the loop instead of the bottom.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-14 Thread Darren New
Andreas Rossberg wrote:
 OK, this is interesting. I don't know Hermes, is this sort of like a 
 dynamically checked equivalent of linear or uniqueness typing?

I'm not sure what linear or uniqueness typing is. It's typestate, and if 
I remember correctly the papers I read 10 years ago, the folks at 
TJWatson that invented Hermes also invented the concept of typestate. 
They at least claim to have coined the term.

It's essentially a dataflow analysis that allows you to do the same 
sorts of things that don't read variables that may not yet have been 
assigned to, except that you could annotate that variables change to 
the state of uninitialized after they've already been initialized.

 Mh, but if I understand correctly, this seems to require performing a 
 deep copy - which is well-known to be problematic, and particularly 
 breaks all kinds of abstractions.

Um, no, because there are no aliases. There's only one name for any 
given value, so there's no deep copy problems. A deep copy and a 
shallow copy are the same thing. And there are types of values you can 
assign but not copy, such as callmessages (which are problematic to copy 
for the same reason a stack frame would be problematic to copy).

I believe, internally, that there were cases where the copy was deep 
and cases where it was shallow, depending on the surrounding code. 
Making a copy of a table and passing it to another process had to be a 
deep copy (given that a column could contain another table, for 
example). Making a copy of a table and using it for read-only purposes 
in the same process would likely make a shallow copy of the table. 
Iterating over a table and making changes during the iteration made a 
copy-on-write subtable, then merged it back into the original table when 
it was done the loop, since the high-level semantic definition of 
looping over a table is that you iterate over a copy of the table.

The only thing close to aliases are references to some other process's 
input ports (i.e., multiple client-side sockets connected to a 
server-side socket). If you want to share data (such as a file system or 
program library), you put the data in a table in a process, and you hand 
out client-side connections to the process. Mostly, you'd define such 
connections as accepting a data value (for the file contents) with the 
parameter being undefined upon return from the call, and the file name 
as being read-only, for example. If you wanted to store the file, you 
could just pass a pointer to its data (in the implementation). If you 
wanted a copy of it, you would either copy it and pass the pointer, or 
you'd pass the pointer with a flag indicating it's copy-on-write, or you 
could pass the pointer and have the caller copy it at some point before 
returning, depending on what the caller did with it. The semantics were 
high-level with the intent to allow the compiler lots of leeway in 
implementation, not unlike SQL.

 Not to mention the issue with 
 uninitialized variables that I would expect occuring all over the place. 

The typestate tracks this, and prevents you from using uninitialized 
variables. If you do a read (say, from a socket) and it throws an end 
of data exception, the compiler prevents you from using the buffer you 
just tried but failed to read.

Indeed, that's the very point of it all. By doing this, you can run 
untrusted code in the same address space as trusted code, and be 
assured that the compiler will prevent the untrusted code from messing 
up the trusted code. The predecessor of Hermes (NIL) was designed to let 
IBM's customers write efficient networking code and emulations and such 
that ran in IBM's routers, without the need for expensive (in 
performance or money) hardware yet with the safety that they couldn't 
screw up IBM's code and hence cause customer service problems.

 So unless I'm misunderstanding something, this feels like trading one 
 evil for an even greater one.

In truth, it was pretty annoying. But more because you wound up having 
to write extensive declarations and compile the declarations before 
compiling the code that implements them and such. That you didn't get to 
use uninitialized variables was a relatively minor thing, especially 
given that many languages nowadays complain about uninitialized 
variables, dead code, etc. But for lots of types of programs, it let you 
do all kinds of things with a good assurance that they'd work safely and 
efficiently. It was really a language for writing operating systems in, 
when you get right down to it.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-13 Thread Darren New
Andreas Rossberg wrote:
 Yes, technically you are right. But this makes a pretty weak notion of 
 mutability. All stateful data structures had to stay within their 
 lexical scope, and could never be passed to a function. 

Not really. The way Hermes handles this is with destructive assignment. 
Each variable holds a value, and you (almost) cannot have multiple 
variables referring to the same value.

If you want to assign Y to X, you use
X := Y
after which Y is considered to be uninitialized. If you want X and Y to 
have the same value, you use
X := copy of Y
after which X and Y have the same value but are otherwise unrelated, and 
changes to one don't affect the other.

(As almost an aside, the non-scalar data structures were very similar to 
SQL data tables.)

If you declare (the equivalent to) a function, you can indicate whether 
the paramters matching the arguments are passed destructively, or are 
read-only, or are copy-in-copy-out. So you could declare a function, for 
example, that you pass a table into, and if it's marked as a read-only 
parameter, the compiler ensures the callee does not modify the table and 
the compiler generates code to pass a pointer. One could also mark a 
variable (for example) as uninitialized on entry, intialized on return, 
and uninitalized on the throw of an exception, and this could be used 
(for example) for the read-a-line-from-a-socket routine.

The only value that came close to being shared is an outgoing connection 
to a procedure; the equivalent of the client side of a socket. For 
these, you could make copies, and each copy would point to the same 
receiver. The receiving process could change over time, by passing its 
end of the socket in a message to some other process (live code 
upgrading, for example).

Since everything could be passed as part of a message, including code, 
procedures, tables, and inports and outports (the ends of sockets), 
I don't see that it had any problems with first classness.

 OK, if you prefer: it is an aspect of first-class mutability - which is 
 present in almost all imperative languages I know. :-)

I disagree. It's entirely possible to make sophisticated imperitive 
languages with assignment and without aliasing.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-13 Thread Darren New
Chris Smith wrote:
 Unless I'm missing your point, I disagree with your disagreement.  
 Mutability only makes sense because of object identity (in the generic 
 sense; no OO going on here). 

Depends what you mean by object.

int x = 6; int y = 5; x = y;

I'd say x was mutable, with no identity problems involved?

Why is it problematic that variables have identity and are mutable? 
Certainly I can later find whatever value I put into x.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-12 Thread Darren New
Marshall wrote:
 So, what exactly separates a precondition from a postcondition
 from an invariant?

A precondition applies to a routine/method/function and states the 
conditions under which a function might be called. For example, a 
precondition on stack.pop might be not stack.empty, and 
socket.read might have a precondition of socket.is_open, and 
socket.open_a_new_connection might have a precondition of 
socket.is_closed.

A postcondition applies to a routine/method/function and states (at 
least part of) what that routine guarantees to be true when it returns, 
assuming it is called with true preconditions. So not stack.empty 
would be a postcondition of stack.push. If your postconditions are 
complete, they tell you what the routine does.

An invariant is something that applies to an entire object instance, any 
time after the constructor has completed and no routine within that 
instance is running (i.e., you're not in the middle of a call). There 
should probably be something in there about destructors, too. So an 
invariant might be stack.is_empty == (stack.size == 0) or perhaps 
socket.is_open implies (socket.buffer != null) or some such.

The first problem with many of these sorts of things are that in 
practice, there are lots of postconditions that are difficult to express 
in any machine-readable way. The postcondition of socket.read is that 
the buffer passed as the first argument has valid data in the first n 
bytes, where n is the return value from socket.read, unless 
socket.read returned -1.  What does valid mean there? It has to 
match the bytes sent by some other process, possibly on another machine, 
disregarding the bytes already read.

You can see how this can be hard to formalize in any particularly useful 
way, unless you wind up modelling the whole universe, which is what most 
of the really formalized network description techniques do.

Plus, of course, without having preconditions and postconditions for OS 
calls, it's difficult to do much formally with that sort of thing.

You can imagine all sorts of I/O that would be difficult to describe, 
even for things that are all in memory: what would be the postcondition 
for screen.draw_polygon? Any set of postconditions on that routine 
that don't mention that a polygon is now visible on the screen would be 
difficult to take seriously.

There are also problems with the complexity of things. Imagine a 
chess-playing game trying to describe the generate moves routine. 
Precondition: An input board with a valid configuration of chess pieces. 
Postcondition: An array of boards with possible next moves for the 
selected team.  Heck, if you could write those as assertions, you 
wouldn't need the code.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-12 Thread Darren New
Joachim Durchholz wrote:
 Actually, in a functional programming language (FPL), you write just the 
 postconditions and let the compiler generate the code for you.

Certainly. And my point is that the postcondition describing all valid 
chess boards reachable from this one is pretty much going to be as big 
as an implementation for generating it, yes? The postcondition will 
still have to contain all the rules of chess in it, for example. At best 
you've replaced loops with some sort of universal quanitifier with a 
such that phrase.

Anyway, I expect you could prove you can't do this in the general case. 
Otherwise, you could just write a postcondition that asserts the output 
of your function is machine code that when run generates the same 
outputs as the input string would. I.e., you'd have a compiler that can 
write other compilers, generated automatically from a description of the 
semantics of the input stream and the semantics of the machine the code 
is to run on. I'm pretty sure we're not there yet, and I'm pretty sure 
you start running into the limits of computability if you do that.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-11 Thread Darren New
Marshall wrote:
 Now, I'm not fully up to speed on DBC. The contract specifications,
 these are specified statically, but checked dynamically, is that
 right? 

Yes, but there's a bunch more to it than that. The handling of 
exceptions, an in particular exceptions caused by failed pre/post 
conditions, is an integral part of the process.

Plus, of course, pre/post condition checking is turned off while 
checking pre/post conditions. This does make sense if you think about it 
long enough, but it took me several months before I realized why it's 
necessary theoretically rather than just practically.

 Wouldn't it be possible to do them at compile time? 

For some particularly simple ones, yes. For others, like the chess 
pieces are in a position it is legal to get to from a standard opening 
set-up, it would be difficult. Anything to do with I/O is going to be 
almost impossible to write a checkable postcondition for, even at 
runtime. After this call, the reader at the other end of the socket 
will receive the bytes in argument 2 without change.

As far as I understand it, Eiffel compilers don't even make use of 
postconditions to optimize code or eliminate run-time checks (like null 
pointer testing).

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-11 Thread Darren New
Marcin 'Qrczak' Kowalczyk wrote:
 The assignment might be performed in a function called there, so it's
 not visible locally.

In Hermes, which actually does this sort of constraint propagation, you 
don't have the ability[1] to munge some other routine's[2] local 
variables, so that becomes a non-issue. You wind up with some strange 
constructs, tho, like an assignment statement that copies and a 
different assignment statement that puts the rvalue into the variable on 
the left while simultaneously destroying whatever variable held the rvalue.


[1] You do. Just not in a way visible to the programmer. The compiler 
manages to optimize out most places that different names consistantly 
refer to the same value.

[2] There aren't subroutines. Just processes, with their own address 
space, to which you send and receive messages.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-11 Thread Darren New
Chris Smith wrote:
 Specialized 
 language already exist that reliably (as in, all the time) move array 
 bounds checking to compile time; 

It sounds like this means the programmer has to code up what it means to 
index off an array, yes? Otherwise, I can't imagine how it would work.

x := read_integer_from_stdin();
write_to_stdout(myarray[x]);

What does the programmer have to do to implement this semantic in the 
sort of language you're talking about? Surely something somewhere along 
the line has to  fail (for some meaning of failure) at run-time, yes?

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-10 Thread Darren New
Chris Smith wrote:
 // Inside this block, a has type int{17..21} and b has type
 // int{18..22}

No what happens if right here you code
   b := 16;

Does that again change the type of b? Or is that an illegal 
instruction, because b has the local type of (18..22)?

 signContract(a); // error, because a might be 17
 signContract(b); // no error, because even though the declared
  // type of b is int{14..22}, it has a local
  // type of int{18..22}.


If the former (i.e., if reassigning to b changes the static type of 
b, then the term you're looking for is not type, but typestate.

In other words, this is the same sort of test that disallows using an 
unassigned variable in a value-returning expression.  When
   { int a; int b; b := a; }
returns a compile-time error because a is uninitialized at the 
assignment, that's not the type of a, but the typestate. Just FYI.

 Incidentally, I'm not saying that such a feature would be a good idea.  

It actually works quite well if the language takes advantage of it 
consistantly and allows you to designate your expected typestates and such.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-07-10 Thread Darren New
Chris Smith wrote:
 If you wish to say typestate to mean this, be my guest.  It is also 
 correct to say type.

Sure. I just wasn't sure everyone here was aware of the term, is all. It 
makes it easier to google if you have a more specific term.

 I'm not aware of a widely used language that implements stuff like this.  

I've only used Hermes with extensive support for this sort of thing. 
Hermes is process-oriented, rather than object-oriented, so it's a 
little easier to deal with the encapsulation part of the equation 
there. Sadly, Hermes went the way of the dodo.

-- 
   Darren New / San Diego, CA, USA (PST)
 This octopus isn't tasty. Too many
 tentacles, not enough chops.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-26 Thread Darren New
Joachim Durchholz wrote:
 That's actually not a design choice

It's certainly a choice you can get wrong, as you say. ;-)

I mean, if without runtime safety is a choice, I expect picking the 
wrong choice here can be. :-)

-- 
   Darren New / San Diego, CA, USA (PST)
 Native Americans used every part
 of the buffalo, including the wings.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-25 Thread Darren New
Marshall wrote:
 Also: has subtyping polymorphism or not, has parametric polymorphism or
 not.

And covariant or contravariant.

-- 
   Darren New / San Diego, CA, USA (PST)
 Native Americans used every part
 of the buffalo, including the wings.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: languages with full unicode support

2006-06-25 Thread Darren New
Xah Lee wrote:
 If you know a lang that does full unicode support, please let me know.

Tcl.  You may have to modify the source command to get it to default 
to something other than the system encoding, but this is trivial in Tcl.

-- 
   Darren New / San Diego, CA, USA (PST)
 Native Americans used every part
 of the buffalo, including the wings.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-25 Thread Darren New
Gabriel Dos Reis wrote:
 I would suggest you give more thoughts to the claims made in
   http://www.seas.upenn.edu/~sweirich/types/archive/1999-2003/msg00298.html

I'm not sure I understand this. Looking at Example 2, where C is 
claimed to be C-safe, he makes two points that I disagree with.

First, he says Unix misimplements the operations semantics of C. It 
seems more like Unix simply changes the transition system such that 
programs which access unmapped memory are terminal.

Second, he says that he hasn't seen a formal definition of C which 
provides precide operational semantics. However, the language standard 
itself specified numerous undefined results from operations such as 
accessing unallocated memory, or even pointing pointers to unallocated 
memory. So unless he wants to modify the C standard to indicate what 
should happen in such situations, I'm not sure why he thinks it's safe 
by his definition. There is no one q that a p goes to based on the 
language. He's confusing language with particular implementations. He 
seems to be saying C is safe, oh, except for all the parts of the 
language that are undefined and therefore unsafe. But if you just 
clearly defined every part of C, it would be safe.  It would also seem 
to be the case that one could not say that a program p is either 
terminal or not, as that would rely on input, right? gets() is safe as 
long as you don't read more than the buffer you allocated.

What's the difference between safe and well-defined semantics? 
(Ignoring for the moment things like two threads modifying the same 
memory at the same time and other such hard-to-define situations?)

-- 
   Darren New / San Diego, CA, USA (PST)
 Native Americans used every part
 of the buffalo, including the wings.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-23 Thread Darren New
Marshall wrote:
 I can't see how you'd call + on a and b if you think they might
 not be numbers. 

Now substitute  for + and see if you can make the same argument. :-)


-- 
   Darren New / San Diego, CA, USA (PST)
 Native Americans used every part
 of the buffalo, including the wings.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-06-23 Thread Darren New
Eliot Miranda wrote:
 classes do _not_ have to inherit from Object, 

I was unaware of this subtlety. Thanks!

-- 
   Darren New / San Diego, CA, USA (PST)
 Native Americans used every part
 of the buffalo, including the wings.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-23 Thread Darren New
Marshall wrote:
 point. My point was, I don't see why you'd be writing code using
 operators that you thought might not be applicable to the operands.

I see. I thought your point was that you might write code for which you 
didn't know the type of arguments. Unless you equate type with what 
smalltalk calls protocol (i.e., the type is the collection of 
operators applicable to values in the type), these are two different 
statements.

-- 
   Darren New / San Diego, CA, USA (PST)
 Native Americans used every part
 of the buffalo, including the wings.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-23 Thread Darren New
Dr.Ruud wrote:
 You can write self-modifying code in C,

No, by violating the standards and invoking undefined behavior, you can 
write self-modifying code. I wouldn't say you're still in C any more, tho.

-- 
   Darren New / San Diego, CA, USA (PST)
 Native Americans used every part
 of the buffalo, including the wings.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-22 Thread Darren New
[EMAIL PROTECTED] wrote:
 Are you sure that you aren't confusing *abstract* with *algebraic* data
 types? 

I've never heard of algebraic data types. It's always been abstract 
data types. Perhaps I stopped studying it, and the terminology changed 
when many people started to consider encapsulation as abstraction. I 
have any number of old textbooks and journals that refer to these as 
abstract data types, including texts that show an abstract data type 
and then explain how to program it as an encapsulated object class.

 No, the following compiles perfectly fine (using GNU Pascal):

That'll teach me to rely on 15-year-old memories. :-) Maybe I'm 
remembering the wishful thinking from when I used Pascal.

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-22 Thread Darren New
John W. Kennedy wrote:
 360-family assembler, yes. 8086-family assembler, not so much.

And Burroughs B-series, not at all. There was one ADD instruction, and 
it looked at the data in the addresses to determine whether to add ints 
or floats. :-)

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is a type error?

2006-06-22 Thread Darren New
Eliot Miranda wrote:
 can only actually carry-out operations on objects that implement them. 

Execpt that every operation is implemented by every object in Smalltalk. 
Unless you specify otherwise, the implementation of every method is to 
call the receiver with doesNotUnderstand.  (I don't recall whether the 
class of nil has a special rule for this or whether it implements 
doesNotUnderstand and invokes the appropriate don't send messages to 
nil method.)

There are a number of Smalltalk extensions, such as 
multiple-inheritance, that rely on implementing doesNotUnderstand.

-- 
   Darren New / San Diego, CA, USA (PST)
 Native Americans used every part
 of the buffalo, including the wings.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-21 Thread Darren New
Chris Uppal wrote:
 doesn't fit with my intuitions very well -- most noticeably in that the sets
 are generally unbounded

Errr, not in Ada.  Indeed, not in any machine I know of with a limited 
address space.

Andreas Rossberg wrote:
  Indeed, this view is much too narrow. In particular, it cannot explain
  abstract types, which is *the* central aspect of decent type systems.

Well, it's Ada's view. I didn't say it was right for theoretical 
languages or anything like that. As far as I know, LOTOS is the only 
language that *actually* uses abstract data types - you have to use the 
equivalent of #include to bring in the integers, for example. Everything 
else uses informal rules to say how types work.

But Ada's definition gives you a very nice way of talking about things 
like whether integers that overflow are the same type as integers that 
don't overflow, or whether an assignment of an integer to a positive is 
legal, or adding a CountOfApples to a CountOfOranges is legal, or 
whether passing a Dog object to an Animal function parameter makes 
sense in a particular context.

Indeed, the ability to declare a new type that has the exact same 
underlying representation and isomorphically identical operations but 
not be the same type is something I find myself often missing in 
languages. It's nice to be able to say this integer represents vertical 
pixel count, and that represents horizontal pixel count, and you don't 
get to add them together.

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-21 Thread Darren New
Andreas Rossberg wrote:
 Maybe I don't understand what you mean with ADT here, but all languages 
 with a decent module system support ADTs in the sense it is usually 
 understood, see ML for a primary example.

OK.  Maybe some things like ML and Haskell and such that I'm not 
intimately familiar with do, now that you mention it, yes.

 Classes in most OOPLs are essentially beefed-up ADTs as well.

Err, no. There's nothing really abstract about them. And their values 
are mutable. So while one can think about them as an ADT, one actually 
has to write code to (for example) calculate or keep track of how many 
entries are on a stack, if you want that information.

 Not counting C/C++, I don't know when I last worked with a typed 
 language that does *not* have this ability... (which is slightly 
 different from ADTs, btw)

Java? C#? Icon? Perl? (Hmmm... Pascal does, IIRC.) I guess you just work 
with better languages than I do. :-)

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-21 Thread Darren New
Andreas Rossberg wrote:
 AFAICT, ADT describes a type whose values can only be accessed by a 
 certain fixed set of operations. 

No. AFAIU, an ADT defines the type based on the operations. The stack 
holding the integers 1 and 2 is the value (push(2, push(1, empty(. 
There's no internal representation. The values and operations are 
defined by preconditions and postconditions.

Both a stack and a queue could be written in most languages as values 
that can only be accessed by a fixed set of operations having the same 
possible internal representations and the same function signatures. 
They're far from the same type, because they're not abstract. The part 
you can't see from outside the implementation is exactly the part that 
defines how it works.

Granted, it's a common mistake to write that some piece of C++ code 
implements a stack ADT.

For example, an actual ADT for a stack (and a set) is shown on
http://www.cs.unc.edu/~stotts/danish/web/userman/umadt.html
Note that the axia for the stack type completely define its operation 
and semantics. There is no other implementation involved. And in LOTOS 
(which uses ACT.1 or ACT.ONE (I forget which)) as its type, this is 
actually how you'd write the code for a stack, and then the compiler 
would crunch a while to figure out a corresponding implementation.

I suspect ADT is by now so corrupted that it's useful to use a 
different term, such as algebraic type or some such.

 Classes qualify for that, as long as they provide proper encapsulation.

Nope.

 OK, I admit that I exaggerated slightly. Although currently I'm indeed 
 able to mostly work with the more pleasant among languages. :-)

Yah. :-)

 (Btw, Pascal did not have it either, AFAIK)

I'm pretty sure in Pascal you could say

Type Apple = Integer; Orange = Integer;
and then vars of type apple and orange were not interchangable.

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-20 Thread Darren New
Rob Thorpe wrote:
 Yes, but the point is, as the other poster mentioned: values defined by
 a class.

A value can only represent one value, right? Or can a value have 
multiple values?

 For example, in lisp:
 xyz is a string, 

xyz cannot represent values from the class of strings. It can only 
represent one value.

I think that's what the others are getting at.

They all have - the whole purpose of a type system is to ensure that any
expression of type T always evaluates to a value of type T.
 
 But it only gaurantees this because the variables themselves have a
 type, the values themselves do not.  

Sure they do. 23.5e3 is a real in Pascal, and there's no variable there.

(hello % there) is illegal in most languages, because the modulo 
operator doesn't apply to strings. How could this be determined at 
compile time if hello and there don't have types?

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-20 Thread Darren New
Rob Thorpe wrote:
 The compiler
 relys entirely on the types of the variables to know how to correctly
 operate on the values.  The values themselves have no type information
 associated with them.

int x = (int) (20.5 / 3);

What machine code operations does the / there invoke? Integer 
division, or floating point division? How did the variables involved in 
the expression affect that?

Casting in C takes values of one type to values of another type.

 No it doesn't. Casting reinterprets a value of one type as a value of
 another type.

No it doesn't.
int x = (int) 20.5;
There's no point at which bits from the floating point representation 
appear in the variable x.

int * x = (int *) 0;
There's nothing that indicates all the bits of x are zero, and indeed 
in some hardware configurations they aren't.

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-20 Thread Darren New
Rob Thorpe wrote:
 Darren New wrote:
Rob Thorpe wrote:
The values themselves have no type information associated with them.
int x = (int) (20.5 / 3);
 In that case it knew because it could see at compile time.

Well, yes. That's the point of static typing.

  In general though it doesn't.

Sure it does. There are all kinds of formal rules about type promotions 
and operator version selection.

In deed, in *general* every value has a type associated with it (at 
compile time). Some values have a type associated with them due to the 
declaration of the variable supplying the value, but that's far from the 
general case.

Note that in
main() { char x = 'x'; foo(x); }
the value passed to foo is not even the same type as the declaration 
of x, so it's far from the general case that variables even determine 
the values they provide to the next part of the calculation.

 If I divide x / y it only knows which to use because of types declared
 for x and y.

Yes? So? All you're saying is that the value of the expression x is 
based on the declared type for the variable x in scope at that point. 
That doesn't mean values don't have types. It just means that *some* 
values' types are determined by the type of the variable the value is 
stored in. As soon as you do anything *else* with that value, such as 
passing it to an operator, a function, or a cast, the value potentially 
takes on a type different from that of the variable from which it came.

 I suppose some are conversions and some reinterpretations.  What I
 should have said it that there are cases where cast reinterprets.

There are cases where the cast is defined to return a value that has the 
same bit pattern as its argument, to the extent the hardware can support 
it.  However, this is obviously limited to the values for which C 
actually defines the bit patterns of its values, namely the scalar 
integers.

Again, you're taking a special case and treating all the rest (which are 
a majority) as aberations.  For the most part, casts do *not* return the 
same bit pattern as the value.  For the most part
union {T1 x; T2 y;};
can be used to do transformations that
T2 y; T1 x = (T1) y;
does not. Indeed, the only bit patterns that don't change are when 
casting from signed to unsigned versions of the same underlying scalar 
type and back. Everything else must change, except perhaps pointers, 
depending on your architecture. (I've worked on machines where char* had 
more bits than long*, for example.)

(Funny that comp.lang.c isn't on this thread. ;-)

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-20 Thread Darren New
Chris Uppal wrote:
 Personally, I would be quite happy to go there -- I dislike the idea that a
 value has a specific inherent type.

Interestingly, Ada defines a type as a collection of values. It works 
quite well, when one consistantly applies the definition. For example, 
it makes very clear the difference between a value of (type T) and a 
value of (type T or one of its subtypes).

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-16 Thread Darren New
Joachim Durchholz wrote:
 Give a heterogenous list that would to too awkward to live in a 
 statically-typed language.

Write a function that takes an arbitrary set of arguments and stores 
them into a structure allocated on the heap.

 Give a case of calling nonexistent functions that's useful.

See the Tcl unknown proc, used for interactive command expansion, 
dynamic loading of code on demand, etc.

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-16 Thread Darren New
Joachim Durchholz wrote:
 Give a heterogenous list that would to too awkward to live in a 
 statically-typed language.

Printf()?

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-16 Thread Darren New
Matthias Blume wrote:
 Very good statically typed versions of printf exist.  See, e.g.,
 Danvy's unparsing combinators.

That seems to ignore the fact that the pattern is a string, which means 
that printf's first argument in Danvy's mechanism has to be a literal. 
You can't read the printf format from a configuration file (for example) 
to support separate languages. It doesn't look like the version of 
printf that can print its arguments in an order different from the order 
provided in the argument list is supported either; something like %3$d 
or some such.

Second, what's the type of the argument that printf, sprintf, fprintf, 
kprintf, etc all pass to the subroutine that actually does the 
formatting? (Called vprintf, I think?)

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: What is Expressiveness in a Computer Language

2006-06-16 Thread Darren New
Matthias Blume wrote:
 In Danvy's solution, the format argument is not a string.

That's what I said, yes.

You can't read the printf format from a configuration file
(for example) to support separate languages.

 You don't need to do that if you want to support separate languages.

That's kind of irrelevant to the discussion. We're talking about 
collections of dynamically-typed objects, not the best mechanisms for 
supporting I18N.

 Moreover, reading the format string from external input is a good way
 of opening your program to security attacks, since ill-formed data on
 external media are then able to crash you program.

Still irrelevant to the point.

 I am sure one could adapt Danvy's solution to support such a thing.

I'm not. It's consuming arguments as it goes, from what I understood of 
the paper. It's translating, essentially, into a series of function 
calls in argument order.

 Obviously, a Danvy-style solution (see, e.g., the one in SML/NJ's
 library) is not necessarily structured that way.  I don't see the
 problem with typing, though.

You asked for an example of a heterogenous list that would be awkward in 
a statically strongly-typed language. The arguments to printf() count, 
methinks. What would the second argument to apply be if the first 
argument is printf (since I'm reading this in the LISP group)?

-- 
   Darren New / San Diego, CA, USA (PST)
 My Bath Fu is strong, as I have
 studied under the Showerin' Monks.
-- 
http://mail.python.org/mailman/listinfo/python-list