type

The type of a value refers to information that the system may use to efficiently store and manipulate the value. The type of a value may inform storage requirements and/or operational decisions. Tcl is expressly oblivious to the type of a value, and defers all such functionality to the individual commands themselves.

Description

There is some concept of type at every level of machine instruction. At the assembly level, assemblers deal explicitly with the manipulation of groups of bits/bytes, so the types of operands it understands are strictly related to the physical characteristics of memory and of CPU registers, namely the size of the operand in bits/bytes. Programming languages at each successive layer attempt to provide data types that are more abstracted from the strict characteristics of the underlying machine and closer to the logical data types than humans think in terms of. At the next level up, for example, languages such as C provide numeric types and operators that are closer to the mathematics that humans practice, but that are still somewhat defined in terms of the size they occupy in machine memory. C also provides a struct type, instances of which are composed from user-specified sequences of the other physical types including the struct type itself. Moving up yet another layer, languages like C++ provide facilities to create purely logical data types, along with facilities for giving operators semantics that make sense for the logical types that users define. At yet another layer, scripting Languages attempt to dispense with much of the verbiage of explicitly declaring types, relying instead on either how the value was created or how it is used to determine the logical type of the value. Scripting languages are also generally more dynamic, such that this type resolution can only happen at the point that the particular function/command/statement/expression is executed. Regardless of how far toward logical data types a language leans, internally it must ultimately map these logical types and their operations onto the lower-level physical types that CPU instruction sets accept. Higher-level languages spend a good deal of their processing time working out the details of this mapping, and research into reducing this overhead is a hot topic.

Some languages such as Smalltalk present more novel approaches to data types. In Smalltalk there is only one data type: "object", and there are no operators - only messages between objectw, which are expected to know internally what the messages intended for them mean and how to react to them. Tcl represents another novel approach that bears some similarity to Smalltalk. There are no objects, just values which are all strings, and commands. Each command is a system unto itself, may be implemented in C or some other language, and may use any type strategy it chooses. The only constraint it has is that it must accept Tcl values, and return a Tcl value.

Type Inference

Some languages such as C require the programmer to declare the type of each variable and each argument to each function. Other languages such as ML infer the type of a value or expression by inspecting its syntax and context. In Tcl, at the script level, every value is already a string, so there is no need to try to determine its type. Each command though, can use any strategy it chooses to process values. Many built-in commands such as lappend specify what type they will interpret each of their arguments as. A third-party command might actually be implemented in ML, and would therefore have the full facilities of that language available to process its inputs.

One key difference in Tcl is that because each value is a string, the question is not "what type is this value ?", but "what type can this value be interpreted as?".

DKF: Except this section is intensely misleading. Tcl's values can convey types, and EIAS only in that the string type is the most general type of all value types (i.e., all other types in Tcl are subtypes of string). Where two commands are such that one produces values of some more defined type (e.g., a floating point number) and the other wishes to consume that type, they can conspire to use that other type for the values between them. This is the basis of how the typing systems of both Tcl_Objs and tclquadcode work.

Note that my statement about other types being subtypes of string is true, but can confuse some who think that types tell you everything about representations. The relationship between two types doesn't tell you about how they are implemented, but rather what operations may be performed without error. All string operations work on all values, that's the only type for which that statement is true, so that makes the string type the supertype of all others.

FM: A type is a far more general concept. Philosophically, it is the footprint of something in the reality, the image of it in our mind. In it, we can distinguish some properties. These properties can be quantities (eg. a weight, numeric), a substance (eg. an animal, its class), some qualities (attributes), a place (geographic coords, 2 or 3 numbers), a shape, an epoch (time coordinate, numeric), things it may have (a stone in a shooe), what it can do (action, the thing is the subject driving the action), what can be done with it (passion, method, the thing is the object that is driven by the action)... In computing, the basic C types are the minimal set to express the properties of something. We can compose all these properties in a struct. If we add methods (i.e passions) in this struct, it become an object "a la" C++,..etc

If String can represent any properties of anything, we can't say the set of generic string methods (append, insert,...) can deal usefully with any type of properties : on numeric properties, or with a name of a class, these method would be totally meaningless. This could be true only if a string were defined as an application of a language, with a set of symbols and rules of grammar. eg, we can deal with numbers throught arithmetic language, using a string as a mathematical expression.

A simple string being just a concatenation of symbols, the grammar behind it is very different than the one of arithmetic.

If we can't derive the rules of arithmetic from the rules of concatenation, it will be wrong to say that string is the supertype of numerics.

In this case, we must apply to the string data (the ordered list of symbols) some particular rules of substitution, throwing away the generic string methods, to get the expected result of arithmetic.

PYK {2023 07 06}: FM, you are conflating type of a thing that is represented with the type of the representation itself. DKF is speaking about the type of a representation, whereas as you are speaking about the type of the that is represented. The only way to have a coherent discussion about types is to strictly articulate which of these types are being discussed. This conflation is a common mistake. In fact, the primary fallacy of object-oriented programming as it is widely practiced is the idea that code object types and the types of things those objects represent can be unified. This section is not "intensely misleading". The point of it is that Tcl proper deals only in strings, and each command brings along its own interpretation, both of the type of the representation and of the type of what is represented.

FM : the type of something is allways a representation. We have three actors here : the reality, the programmer, the computer. A programmer represents to himself a thing as a type. This is a logical type, that exists only in the programmer's mind. Then he tries to communicate this logical representation to the computer, along the technological contraints of the machine. This latter representation is, let's say, a "technological-constraint type", and exists only in the computer's circuits. Ok, the Tcl technology constraints all type to be "stringified", hiding the physical contraints of the variety of machineries. It's an heritage of shells, where all commands were writing there results on stdout, and can only be chained trought a pipe, redirecting the stdout of the last command to the stdin of the next command. It's good. But programmers deal with reality, so they need logical types, to be sure that the logic into their model is respected : If you create a programm to draw, you need to distinguish square from circle from path,...etc. No big drawing application was never written in Tcl, and there is good raison why. The lack of typology make it quicly unmaintable. If, as a programmer, I decide that some data must be an integer, I know why. Sometimes, for efficiency, I don't need my data to be kept "stringyfiable".

To summerize : Tcl hides "technical-constraint Types", and it's good for programmers. But to do it, Tcl makes also "logical Types" difficult to implement, what create some problems of modelisation. The ideal would be : hide the technical-constraint Types, but allow "logical Types" to be implemented.

DKF: Types in Tcl are formally subsets of the space of values. Conform to the subset membership constraint and you are a member of the type. The string type has the trivial membership constraint: all values are strings. Integers have a more restrictive definition, as do lists, etc. You can define your own types too; this is what rl_json does for example. There are overlaps; 123 is an integer and a string and a list (and other things besides), all at once.

Types in Tcl describe what operations may be applied to the values (without certain kinds of errors) but do not prescribe how values are stored in memory. (That is the representation.) A consequence of this is that if you have a non-string representation, you must either also have a string representation or be able to make one on demand.

Tcl does not make all values be objects. Tcl does make all values be immutable when they have other things observing the value (i.e., holding a reference to it). Tcl binds values to their originating thread.

Tcl has objects, but uses them for heavyweight purposes; those have internal mutable state. This is by design. The value that is the (current) name of the object is not the object; the thing is not the name, the territory is not the map of it.

All observably mutable entities are named. Conceivably the spaces of particular names could be types.

Your mistake appears to come from the idea that if an entity is a $THIS then it must not be a $THAT.

Types are enforced at runtime. Tcl has no notion of enforcement of them at any other time; there is no compile time, there is only Zuul.

FM Tcl_ObjTypes in Tcl are to Types what Tcl_Obj are to Objects: inappropriate and confusing terminology. Tcl_Obj are values. Tcl_ObjType are types of values.

A type is the abstraction of a thing, which consists of describing it as a set of properties and parts that are more or less independent of each other.

As an abstraction, these properties and parts do not have defined values ‚Äč‚Äčinitially. For example, the type "car" has the color property, but this color has no defined value as long as the type remains in the state of abstraction. Likewise, the type "car" contains an engine, but nothing designates it at this same stage. In short, as a set of undefined values, a type cannot therefore be a subset of the space of values.

Of course, we give a type a name, and this name is a value. But, as you say, the value of the name of a type is not the Type. It's another illustration that Types cannot be reduced as a subset of the space of values.

Type Safety

Type Safety refers to the ability of a compiler or interpreter to ensure that functions/commands are invoked only with values of the proper type. An explicitly and statically-typed language like C can provide type safety fairly easily, although C in particular allows the programmer to escape the confines of its type safety mechanism via casting. Higher-level languages that choose that attempt ensure type safety come up with various schemes for doing so. Both Tcl and Smalltalk act simply as conveyers of values (Tcl) or messages (Smalltalk). and any type checks that might be performed would be up to each command (Tcl) or object (Smalltalk).

See Also

abstract data types
JIT
type checking

Reference

Types and Programming Languages , Benjamin C. Pierce
A type system is a syntactic method for enforcing levels of abstraction in programs. The study of type systems--and of programming languages from a type-theoretic perspective--has important applications in software engineering, language design, high-performance compilers, and security. This text provides a comprehensive introduction both to type systems in computer science and to the basic theory of programming languages. The approach is pragmatic and operational; each new concept is motivated by programming examples and the more theoretical sections are driven by the needs of implementations. Each chapter is accompanied by numerous exercises and solutions, as well as a running implementation. Dependencies between chapters are explicitly identified, allowing readers to choose a variety of paths through the material. The core topics include the untyped lambda-calculus, simple type systems, type reconstruction, universal and existential polymorphism, subtyping, bounded quantification, recursive types, kinds, and type operators. Extended case studies develop a variety of approaches to modeling the features of object-oriented languages.