Continued from TopsTypeDeterminatorChallenge
Some of the above talk implies a dedicated operator "per type". However there are at least two different ways to think about and/or implement association of operator to "type", and both are valid models, at least for "built-in" types. One is OOP-style polymorphism where each "type" has its own version of a given operator (same name, different method), such as "add" or "print". The other is the old-school case or IF statement where there is a single name (operator) and the behavior branches or changes depending on the item's "type".
// Pseudo-code for internal implementation of PRINT operation on // a single scalar (variable or constant). function printScalar(theVariable) { var theType = extractType(theVariable); // get type tag var theValue = extractValue(theVariable); // if (theType=='int' || theType=='date') { byte1 = getByte1(theValue); byte2 = getByte2(theValue); intVal = getIntValue(byte1, byte2); if (theType=='int') { return (doSometingInt(intVal)); } return(dateSeparate(intVal)); // split parts (date stored in RAM as an Int) } elseif (theType=='float') { byte1 = getByte1(theValue); byte2 = getByte2(theValue); byte3 = getByte3(theValue); byte4 = getByte4(theValue); return(doSomethingFloat(byte1, byte2, byte3, byte4)); } elseif (theType=='string) { // etc... } }Discarding for now which is "better" for future expansion, such as user defined types, there is no reason to say one model is more valid than the other to explain and/or define what is "happening with types". You cannot objectively say each type "has its own operators" because it doesn't have to be modeled that way (in one's head) nor implemented that way. They both explain what the program "does".
--top
Remember that the definition from TopsTypeDeterminatorChallenge is "Type = a (relatively) invariant set of values and zero or more associated operators." My choice of the word "associated" was deliberate, and it means something quite different from "dedicated".
Note the following code snippet from your printScalar() example above:
} elseif (theType=='float') { byte1 = getByte1(theValue); byte2 = getByte2(theValue); byte3 = getByte3(theValue); byte4 = getByte4(theValue); return(doSomethingFloat(byte1, byte2, byte3, byte4)); }In the absence of a 'float' type, the block between curly braces would never be called. In the presence of a 'float' type, it might be called. That means printScalar() is associated with a 'float' type. That relationship is indubitable -- the code says so.
"Associated with" in a general sense, sure. But that doesn't say anything definitive about the relationship other than it exists. Applying any further details or limits seems to assume a specific implementation or language.
Yes! Exactly! That's why "associated" is appropriate, accurate, and correct.
Further, does the type "go away" if we delete a routine that used to change behavior/output based on it? For example, what if I have a "string" and a "label" type tag. The one routine that used to make a distinction between the two fell out of use and thus was deleted. "Label" may still suggest a usage to some users, but otherwise is now treated exactly like a "string" in the current software version. One could argue that peoples' heads are still making use of it and thus "operating" on it, but many other things that we don't normally call "types" can affect behavior also. "Affect behavior" is rather broad.
A type goes away if you delete every reference to it, i.e., if there are no associations with it. If there are no associations with it, it isn't used or usable, and is thus effectively non-existent.
I disagree that it's not a "type" but the others are. That appears to be your personal assessment.
Sorry, not following you. What "others" do you mean? If there are no associations with a type, it's not referenced. If it's not referenced, it's effectively not there because no code uses it.
Other "tags" that may be referenced in IF statements etc. Humans may still use it if it's say printed out. In the case given it may be used more like a comment. Whether somebody chooses to make the software behave differently based on such may change. It's information. Sometimes we use it and sometimes we don't. To pivot "typeness" on whether it happens to be used somewhere in software is rather arbitrary in my opinion.
If you're printing out a label associated with a type, then you have one implicit operator that returns the right "type" label for a value of your type, and you have a second operator that allows you to select values of that type (you must, or you wouldn't have been able to get a value to print out in the first place). Whilst until now I've avoided complicating the issue by pointing out that your "type-tag" is, in fact, an operator associated with a type that returns a label for a value of that type, that's exactly what it is. So, you have two operators associated with the type. If you have no operators associated with the type, then nothing references the type. That means it's effectively not there. You might argue that you still have some source code somewhere that defines the structure of values of that type. However, if that type is not referenced, the code is as good as a set of comments. The type is effectively not there. This is not arbitrary; it's simple logic and common sense.
var x = 3.4; x = 2; x = 'p'; x = new Spleen(); x = "fish";
{A column in a database has a name (i.e. city) along with a type...why is that fuzzy? The name of the column is similar to named items in a C struct. A C struct has items that contain both a name, and a type. If a column has a type indicator (if that's what you want to call it) it doesn't mean that type indicator implements a proper type system. i.e. if you visually mark off the column as "boolean" but then allow integers and strings inside the cells, the "type indicator" is just a lying indicator and not a real type system. I believe SqLite has something like this which is considered a feature by some, and a bug by hardcore programmers and theorists. I don't see how it is fuzzy whether or not a column name is the same or similar to the column type: for example if the column name is "city" and has a type "string" with a maximum of 100 characters, how is that fuzzy? What is problematic is the computer industry and product market making things fuzzy when they need not be fuzzy, and purposely confusing matters for I don't know what gain. }
Indeed. An attribute, in database parlance, is simply a type and a label.
Sorry, I meant a "domain type" not a column's database type. For example, let's say we have "employee types" of "worker", "manager", and "executive". (This may be an oversimplification for illustration simplicity.) One could also call that an "attribute". One could also divide up employees by retirement plan, say Plan-A, Plan-B, and Plan-C.
A domain type is a type. Don't make the common mistake of thinking the only alternatives for, say, a RetirementPlanType are either an unpleasantly-fixed enumeration of retirement plans, or an overly-general string attribute with a lookup table. With a suitable TypeSystem, you can compose EmployeeType and RetirementPlanType from a string type, and obtain specific employee types or retirement plans from a lookup table. The assumption is that their "stringness" is invariant, but the list of employee types and retirement plans is (relatively) dynamic. Thus, we gain TypeSafety in that we can't accidentally join an employee type to a retirement plan, but we can still perform the usual string manipulations and we can easily add or remove employee types and retirement plans.
For example, in TutorialDee/RelProject:
TYPE EmployeeType POSSREP {value CHAR}; TYPE RetirementPlanType POSSREP {value CHAR}; VAR EmployeeTypes REAL RELATION {etype EmployeeType} KEY {etype}; EmployeeTypes := RELATION { TUPLE {etype EmployeeType('worker')}, TUPLE {etype EmployeeType('manager')}, TUPLE {etype EmployeeType('executive')} }; VAR RetirementPlanTypes REAL RELATION {rtype RetirementPlanType} KEY {rtype}; RetirementPlanTypes := RELATION { TUPLE {rtype RetirementPlanType('PLAN-A')}, TUPLE {rtype RetirementPlanType('PLAN-B')}, TUPLE {rtype RetirementPlanType('PLAN-C')} }; VAR Employees REAL RELATION {id INTEGER, name CHAR, etype EmployeeType, rtype RetirementPlanType} KEY {id}; CONSTRAINT employee_etype_fkey EmployeeTypes >= Employees; CONSTRAINT employee_rtype_fkey RetirementPlanTypes >= Employees; INSERT Employees RELATION { TUPLE {id 1, name 'Dave', etype EmployeeType('worker'), rtype RetirementPlanType('PLAN-C')} };I'm not sure what your point is. I'm not asking how to make programming "safer" here. And, that's a specific implementation. We could make colors and car models into these kinds of things or just about anything. What does that tell us? It's just an implementation choice.
It shows how types can be implemented which do not devolve into a "type vs. attribute" dichotomy.
So, then you haven't shown that there is a hard line between them.
There is, though they may be used together. The set of values described by EmployeeType is precisely the same as the set of values of CHAR, but it has a different set of operators. The selection of specific EmployeeTypes, however, is constrained by the database, not the type.
One can view that as simply an implementation detail. A super-flexible database could let the character sets be defined in tables instead of hard-wired into the interpreter/compiler/engine. (I'm not commenting on the practicality of it here.)
Yes, you can do that.
So, what's the diff between attributes, look-up tables, and types? (And please be careful about "being" a look-up table versus using a table as a look-up table.) We can define the retirement plans as a language "type" or as an entity represented as table(s).
{Well a similar question can be asked: what is the difference between a C struct versus a table? A C struct is a small table with one row, but it is a limited table that you can't do much with compared to a proper table. You can't run queries on a C struct like you can a proper table. So yes there is overlap between the two, and you could have difficulty drawing the line. Probably there is some performance hits with using a full fledged table instead of using a simpler option like a struct. There are also overlaps between associative arrays and tables too. Isn't an associative array just a poor mans table without all the benefits and features of a real table? I guess it boils down to using the right tool for the right job. You can't really draw a clear line between a table and a struct because a struct can be represented as a table, and a table can be represented by an array of structs. It reminds me of the "TuringComplete" mind game. However one tool makes programming easier in certain situations than the other tool. People have been using C structs for years to emulate OOP, and people have been using arrays for years to emulate tables, and people have been using tables to emulate ranges, and vice versa. In a regex, the range "a..Z" is a terse way of expressing a character range. Instead of a range you could have populated a database table with all characters from a..Z, and replaced "a..Z" regex language with some kind of query language. The query however wouldn't be as terse as the range syntax.}
That still doesn't help answer the question of what is a "type". This discussion is not really about the practical merits of different techniques with similar properties. There are indeed multiple ways to achieve the same thing.
It's quite clearly established what a "type" is. There are various recognised, compatible, and established definitions. One was presented on the page that spawned this one, TopsTypeDeterminatorChallenge. You appear to reject recognised definitions in favour of a personal definition that is neither recognised nor established, and you haven't successfully deprecated the established definitions or effectively promoted your definition. Please, consider the possibility that your unwillingness to accept established definitions is a foible of your own, rather than an indication of problems with established definitions.
It's a crappy, vague def still. And I've seen no evidence that it has popular support.
{OK. I added a definition of what a type is to WhatAreTypes. The essence is: Properties of programs.}
Note that the first bullet is a slightly less-formal version of the "Type = a (relatively) invariant set of values and zero or more associated operators" definition presented on TopsTypeDeterminatorChallenge. I think Wikipedia counts as "popular support", and is perhaps the best test of popular support that we have.
Re: "A data type is a classification identifying one of various types of data [...], that determines the possible values for that type; the operations that can be done on values of that type;[...]"
That's fairly close to the 3rd proposed side-tag def at TopsTypeDeterminatorChallenge. However, this doesn't say "where" the classification is; it could be in a desk drawer in a cave in Timbuktu under that. It lacks association. "Side tag" better describes how it relates to the programming objects/features in that it is associated with the features, and brings up visions of shirt tags and mattress tags and/or motorcycle side-cars to imply an association with a primary or target object. Thus, I find it a more informative definition even if it has "embellished visual artifacts". But, we are getting closer to each other's. That's progress. --top
I'm not clear why you need to introduce a "side-tag" in order to specify association. Isn't it enough to say that, for example, a value has a type? That's as "where" as needed for any purpose, without unduly tainting the concept with flavours of implementation. It's simpler, too.
There's a problem with it, but I can't quite put my finger on it yet. And it's not just "values". Functions, constants, etc. can "have" a type.
Sure. Constants, variables, whatever, can "have" or be associated with types. Again, I'm not sure why "side-tags" need to be introduced into the simple notion that some <x> is of a given type.
Values can also affect "possible values and operations that can be done". We need a more formal definition of "value". I agree that there is a "tradition" in the way things are partitioned into "type" indicators/trackers/limiters and into "values", but I cannot state a clear-cut pattern without referencing tradition so far. One can do branching and computations using "types" also (depending only language), as if values and types are potentially interchangeable. I suspect tradition is clouding our ability to state clear rules that distinguish.
What makes you think values and types are interchangeable? "Value" is generally well-understood to be an immutable instance of a type, i.e., an individual constant from the set of constants described by a type. For example, 3 is a value of type integer.
An example of interchangeable is using using type "Integer" to mean True and type "String" to mean False. This is perfectly possible in many dynamic languages. (Recommended, probably not.) I bet many languages would pass TuringComplete muster using type tags/behavior alone. And where is this "immutability" happening? How can one objectively verify it exists in a programming language? I understand how it works in math, but that's just a head model, and again not necessarily the only head model one can use to make predictions about program behavior. I agree that the "type" is often used to modify a program's handling of the value portion, but the reverse can also be true in dynamic languages.
Could you provide an example of using type "Integer" to mean True and type "String" to mean False? What is a "head model"?
if typeOf(x) = "integer" then print("The ship arrived") else print("The ship is not in yet") end ifClearly, 'x' is a variable which may contain values of integer type (or, perhaps more accurately, the value in 'x' belongs to a type that is associated with an operator typeOf that returns the string "integer" when given a value of that type). I don't see any confusion between type, value, or variable here.
You mean a "mental model" or "concept"? Why the special terminology?
Immutability is a defining characteristic of a value. It distinguishes a value from a variable. A thing that is mutable is, by definition, a variable.
I'm not sure how this allows one to distinguish between values and types by looking at languages and/or source code.
Without any knowledge of semantics, merely looking at languages and/or source code is meaningless.
As a practical note, if you hard-wire the "lists" of "type instances" into your D code, then only programmers and DBA's can add new employee levels and retirement plans. You'd probably want it done via a set of CRUD screens.
Of course. The above is an example, not a ready-to-use application.