4 ms·
This is not only missing the point, it's easy to prove false: Python: `foo = '1' + 1` gives `TypeError: Can't convert 'int' object to str implicitly` C: `char
by devishard 10y ago
This is not only missing the point, it's easy to prove false:
Python: `foo = '1' + 1` gives `TypeError: Can't convert 'int' object to str implicitly`
C: `char bar[] = "1"; char* foo = bar + 1;` gives literally no error.
Good errors occur because of strong/weak typing, not because of static/dynamic typing.
- castratikron 10y agoYou always need to check array bounds in C, what else is new?
- devishard 10y agoApparently it's new to some people that C is a statically-typed, weakly-typed language.
- castratikron 10y agoIf you're talking about the cast from an int literal to a char pointer, that's not what's happening. That's common C shorthand for incrementing a pointer to point to the next element. For example, the char pointer increment compiles to: 4004fb: 48 83 c0 01 add $0x1,%rax While an int pointer increment compiles to: 40050c: 48 83 c0 04 add $0x4,%rax Because on my particular platform, an int is 4 bytes and a char is 1 byte and the memory is byte addressable.
- devishard 10y agoI'm aware of what's happening. It's definitely a norm in C and it produces desirable results in many cases (I've written similar structures myself many times). All I'm saying is that from a type perspective it's a bizarre choice to allow that.
- catnaroek 10y agoGood errors messages occur because you have enough information to craft said messages. Python has its fair share of utterly uninformative error messages, mostly due to the language's inability to comprehend the structure of user-defined types. Python programmers don't call these “type errors”, but a Haskell or ML programmer would.
- devishard 10y agoOkay, but how do you gather enough information to craft said messages? I posit that there's nothing stopping you from gathering that information at runtime; it just typically isn't done to the same extent in dynamic languages as in ML-family languages. A type system that gathers lots of type information is equivalent to a strongly-typed language IMHO, and a type system that gathers little type information is a weakly-typed language. Static languages can be strongly typed (Haskell, ML) or weakly typed (C) and dynamic languages can be strong(ish)ly typed (Python) or weakly typed (JavaScript).
- catnaroek 10y ago> Okay, but how do you gather enough information to craft said messages? There are two sources of such information: the static context (e.g., in Scheme, which variables are in scope) and the dynamic environment (e.g., again in Scheme, the type of an object, and, in Python, pretty much everything). The static context grows whenever you bind variables in the program text (e.g., when you define a procedure). The dynamic environment grows when the control flow reaches such binders (e.g., when it enters a called procedure). > I posit that there's nothing stopping you from gathering that information at runtime; it just typically isn't done to the same extent in dynamic languages as in ML-family languages. A fundamental limitation of dynamic analysis (that applies to any dynamic language, already invented or to be invented in the future) is its inability to “peek into the future”. For example, if you create an empty mutable list object, dynamic analysis can't tell you what its element type is supposed to be, until you actually start inserting elements into it. Static analysis, on the other hand, can determine what the element type is solely from inspection of the program text, e.g., if you make a procedure that inserts strings into the list, the list's element type must be a supertype of string, whether you actually call the procedure or not. Here's an example of a type error that Python couldn't possibly diagnose: http://ideone.com/0KUVVb http://ideone.com/0KUVVb > A type system that gathers lots of type information is equivalent to a strongly-typed language IMHO This isn't true. C++'s type system gathers a lot of type information, yet C++ isn't “strongly typed” (assuming that term means anything at all) by any stretch of the term. Rather than “strongly-typed”, a more useful term is “sound”. A type system is sound when it actually protects the language's basic abstractions. For example, Standard ML has a sound type system, and there's a formal proof of this fact. Java's type system is actually unsound, but it makes up for this deficiency by inserting runtime checks to turn wrong operations (e.g., invalid downcasts) into runtime exceptions (just like in Python!). C++'s type system is also unsound, and performing wrong operations is simply undefined behavior.
- milcron 10y agoStatic+strong typing is a nice combination, which is probably what hacker_9 meant to say. ML family is particularly nice -- with Hindley-Milner type inference, you get a lot of static guarantees with none of the verbosity of languages like Java.
- catnaroek 10y agoIt's not just type inference that makes programming in ML so nice. Also important are: (0) Parametricity: Type variables are never case-analyzed. As a result, types convey useful information about what functions may or may not do. Haskellers call this “free theorems”. Java's `instanceof`, C++'s `sizeof` and template specialization, and GHC's `TypeFamilies` are blatant violations of parametricity that make types less informative. (1) A clear distinction between data (sums of products) and operations (functions). In a general-purpose language, operations will always be somewhat ill-behaved: they may raise exceptions, fail to terminate, etc. Data tends to be better behaved, and algebraic laws can be stated about it, which hold even in the presence of effectful and/or non-terminating functions. This makes ML superior to Haskell, not to mention object-oriented languages. (2) A module system that enforces abstraction boundaries between subsystems of a larger system. ML's opaque signature ascription (which has no counterpart in Haskell or object-oriented languages) ensures that the internal representation of abstract types is only visible in the module where they're implemented. In a well architected ML program, trying to violate another module's internal invariants is a type error!
- devishard 10y ago> Static+strong typing is a nice combination, which is probably what hacker_9 meant to say. That's a rather generous interpretation, given that hacker_9 said nothing about strong types, and instead made a claim about static vs. dynamic languages. I do agree with your assertion, though; learning Haskell and OCaml prepared me for writing Python in ways that many of my peers in the Python community are unprepared. One big example is the difference between str and bytes in Python 3: a lot of Pythonistas find this distinction an annoyance, but I find it extremely useful, largely because I learned how to leverage such type differences to reduce errors from ML family languages.