3 ms·
Erlang (one of my favorite languages) is dynamically typed, yet did not (until the recent addition of maps) have dynamic heterogeneous structures. You cannot i
by colanderman 10y ago
Erlang (one of my favorite languages) is dynamically typed, yet did not (until the recent addition of maps) have dynamic heterogeneous structures. You cannot iterate over or resize tuples, and the static analyzer discourages heterogeneous lists. Both are immutable (functional).
I apologize that I have hopped between use and implementation a bit in my above post. Yes, the implementation of Python lists and tuples support iteration, but it would be nonsensical to write code which iterated over a list or tuple containing heterogeneous data. (What could you possibly do identically to each element, if they had nothing in common?) Hence my assertion that implementing a dynamic heterogeneous structure is inefficient, if it nonsensical to truly use it as such.
- markrages 10y ago> it would be nonsensical to write code which iterated over a list or tuple containing heterogeneous data. There are Python functions that take any type like repr() or id()
- colanderman 10y agoSee my other comment; it does make sense to have a list of objects which share some interface. In the case you suggest, it is a very trivial and not-very-useful interface, but an interface nonetheless. You can do this with objects even in strictly-typed languages like OCaml or Mercury; code which iterates over the list is simply restricted to use only those methods which all elements have in common. Of course in languages which don't support a universal "object" type (say OCaml or C) you cannot do this -- numbers and strings have no interface in common. Those languages take advantage of this by not storing type information in collections (e.g. OCaml's float arrays, or any array in C), thus resulting in more compact memory footprints. If they instead allowed heterogeneous collections, the memory footprint of such collections would double.
- aangjie 10y ago> There are Python functions that take any type like repr() or id() Umm.. I haven't had to use any of them on a list(or for that matter on an object) for code.. (except when I'm curious and poking at python internals) May be I'm stuck in a web application role? Is it actually useful to say call repr() on a list of objects? May be call id to see if there's references to same object twice? I'm finding it hard to imagine cases where it would be needed to implement a feature, that wouldn't be better served by alternate methods.
- davrosthedalek 10y agoOne could argue that for those, the semantic differences between the types are dropped. In OO lingo, they look at the properties of the common base class.
- pdonis 10y ago> it would be nonsensical to write code which iterated over a list or tuple containing heterogeneous data I agree such a use case would be rare, but that doesn't mean such a use case cannot exist.
- colanderman 10y agoAt that point it is an argument of taste, but my belief is that those rare cases are invariably code smells and can be rewritten more clearly without the necessary run-time type introspection (or inference from some other information). Better to restrict them entirely IMHO.
- jholman 10y agoI hope it is obvious that Python values are members of a single static-type, this massive sum-type that combines a type-tag with a value, summing together all of the possible types-in-the-python-sense. That is to say, from the perspective of static typing, dynamic languages are uni-typed. In languages with explicit static types and explicit Tagged Unions, it's not unreasonable to iterate across a homogeneous sequence of tagged unions, all of the same type. For example, Option<Int>. This is just a particular instance of the general pattern of iterating across a heterogeneous sequence, introspecting on whether a given value is of type Int or of type NoneType. Unless you want to allege that Null is a member of Integer (in a sane and healthy type system). The point of this is that I'm skeptical that these are "invariably code smells". For example, our Option<Int> values might come from a SQL field that is a nullable integer. It seems entirely fair to iterate across them.
- colanderman 10y agoMaybe it is not clear from my other comments but we are in violent agreement :) Tagged unions (and even more general RTTI) have a common interface and therefore are homogeneous: a well-written iteration always accesses such elements first through the tagged-union (or RTTI) interface. To me, code which acted on such elements without first consulting the common interface would be "smelly". e.g. code which assumes every other item is a string, or code which uses a list as an ad-hoc structure. There's almost always a better way to write such code. (As an aside, I find the explicit use of RTTI a smell in and of itself, but one unrelated to containers. Code which today does two different things to some input, based on whether it's an integer or string, likely tomorrow will need to do three different things, two of which involve an integer. Tagged unions are almost always preferable.)