The Forum for Discussion about The Third Manifesto and Related Matters

Please or Register to create posts and topics.

What is the purpose of relations containing tuples/relations?

PreviousPage 5 of 7Next
Quote from AntC on June 17, 2019, 1:00 am

 

However, John's point -- that the facility for multiple constructors for an immutable value class in a typical object-oriented language is notionally isomorphic to TTM's multiple possreps -- is sound:

In a typical object-oriented language, multiple constructors for a given class may be used to create various instances which have an unspecified and hidden internal representation, but that appropriately reflects the chosen constructor.

Firstly there's Hugh's repeated and vehement objection to regarding TTM Selectors as equivalent to OO constructors.

Without confusing things too much, I just wanted to point out that some OO languages have value types. That includes C++ and C# in particular, but not Java or any of the dynamic languages.

All types in TTM/D are value types and not reference types, and therein lies the crucial difference. Value types are not instances, they are values. Two copies of a value in different memory locations (different variables or temporaries) are the very same value. They are indistinguishable. There is no pointer (unless some unsafe means are provided to create one).

And no, multiple constructors do not make that crucial guarantee, that every value can be produced by every selector.

No, this is not notional isomorphism, but it may be uninformed confusion or conflation.

Andl - A New Database Language - andl.org
Quote from AntC on June 17, 2019, 1:00 am
Quote from Dave Voorhis on June 16, 2019, 10:42 am

Would I be right in thinking that invoking one of these constructors:

a) Allocates a patch of memory;

Not necessarily.  If two of the above six operations return the same value, they are entirely free to allocate on the first invocation but not the second, or in some cases neither: see below.  This is the technical distinction between factory methods, which these are, and true constructors.

b) Executes some code to put values into that memory;

In terms of the Java model, it executes some code to return the value.

c) Returns a pointer to that memory?

At the implementation level, maybe or maybe not.  It could for example return the value in two machine integers if the compiler can prove that this makes no operational difference.

OK it's an immutable value ex hypothesi, but it's a pointer (contra OO Pro 2) not a value simpliciter.

Would I be further right in thinking that distinct program code that invokes the same constructor with the same arguments would also allocate a different patch of memory and return a different pointer value?

Again, not necessarily.  In practice, all appearances of 3 in a program written in any language are probably the same in storage terms: in practice, not all appearances of 1,475,979,915,214,180,235,084,898,622,737,381,736, 312,066,145,333,169,775,147,771,216,478,570,297,878,078,949,377,407,337,049, 389,289,382,748,507,531,496,480,477,281,264,838,760,259,191,814,463,365,330,
269,540,496,961,201,113,430,156,902,396,093,989,090,226,259,326,935,025,281,
409,614,983,499,388,222,831,448,598,601,834,318,536,230,923,772,641,390,209,
490,231,836,446,899,608,210,795,482,963,763,094,236,630,945,410,832,793,769,
905,399,982,457,186,322,944,729,636,418,890,623,372,171,723,742,105,636,440,
368,218,459,649,632,948,538,696,905,872,650,486,914,434,637,457,507,280,441,
823,676,813,517,852,099,348,660,847,172,579,408,422,316,678,097,670,224,011,
990,280,170,474,894,487,426,924,742,108,823,536,808,485,072,502,240,519,452,
587,542,875,349,976,558,572,670,229,633,962,575,212,637,477,897,785,501,552,
646,522,609,988,869,914,013,540,483,809,865,681,250,419,497,686,697,771,007 (a rather large Mersenne prime) are likely to be the same in storage terms, especially if they were computed in different ways.

There might be a comparison operator (however it's spelled) that says the references at the ends of those pointers are the same value. But this being OO, there's also a differently-spelled operator that will distinguish whether they're the same pointer and tell you they're not the same. So this fails the Leibniz equality test RM Pre 8 "It follows from this prescription that if ...", that I quoted recently.

Technically that is true.  However, unlike the identity operator on typical object instances, which is indeed usefully distinct from equality, this operator is a useless operation on Instance.  While it is possible to ask if two Instants are or are not object-identical, there is AFAIK no other operation whatsoever that is sensitive to the distinction.  What is more, if we switch from Java to C#, which is very very similar to Java and just as much an OO language, we find that such values in that language can be compared by equality or identity, but the result is guaranteed to be the same.  By the same token,  Python 3 permits integer values like the prime number above, whereas Fortran does not, but that does not mean that Python integers are a distinct concept from Fortran integers.

Quote from dandl on June 17, 2019, 1:39 am

Without confusing things too much, I just wanted to point out that some OO languages have value types. That includes C++ and C# in particular, but not Java or any of the dynamic languages.

Java does not have user-defined value types, but it does have system-defined ones.  Furthermore, there is nothing about the language that prevents user-defined value types: they have been specced by Oracle for a long time, but not yet released because it would mean a breaking change to the compiled class format.

Python likewise has system-defined value types: the is (identity) and = (equality) operators always return the same truth value when applied to two ints, floats, booleans, strings, or bytevectors, as well as the type whose single element is None.  The types decimal, complex, tuple, range, and immutable set are immutable but can be (uselessly) distinguished by is.  User-defined types can be value types in the same sense: they can be distinguished by is, but you can arrange to make it a runtime error to mutate them, just as with the other types in this paragraph.

Even Smalltalk and Ruby have a single system-defined value type:  SmallInteger.

And no, multiple constructors do not make that crucial guarantee, that every value can be produced by every selector.

Good point, though that is probably not enforceable by an implementation of D.  In any case, four of the six factory methods of Instant have that property.

Quote from johnwcowan on June 17, 2019, 4:10 am
Quote from dandl on June 17, 2019, 1:39 am

Without confusing things too much, I just wanted to point out that some OO languages have value types. That includes C++ and C# in particular, but not Java or any of the dynamic languages.

Java does not have user-defined value types, but it does have system-defined ones.  Furthermore, there is nothing about the language that prevents user-defined value types: they have been specced by Oracle for a long time, but not yet released because it would mean a breaking change to the compiled class format.

Python likewise has system-defined value types: the is (identity) and = (equality) operators always return the same truth value when applied to two ints, floats, booleans, strings, or bytevectors, as well as the type whose single element is None.  The types decimal, complex, tuple, range, and immutable set are immutable but can be (uselessly) distinguished by is.  User-defined types can be value types in the same sense: they can be distinguished by is, but you can arrange to make it a runtime error to mutate them, just as with the other types in this paragraph.

Even Smalltalk and Ruby have a single system-defined value type:  SmallInteger.

Everything you say here I already know, and at the end of it I really don't see what your point is. We're talking about user-defined types as per TTM Pre 4, and the extent to which they might be considered notionally the same as OO multiple constructors. You want to detour off into the bizarre territory that is system-only value types and open up the weird oddities they trigger in unsuspecting user code? Please don't. [Aside: do you know why SmallIntegers are 30 bits? It's horrible, but it was the only way they could get the code to run fast enough.]

The point is that TTM value types are really different from OO reference types, and this permeates the entire language. (See also OO VSS 2). A minority of OO languages do provide good support for (user-defined) value types, and this turns out to be amazingly useful. A few others fake it, and this turns out to be less useful and often rather messy.

[And yes, I have often lamented the shortsightedness of the various owners of Java for not biting the bullet early on and implementing value types, generics and fixed a couple of other minor things when they could have (such as the date/time types). They've finally caught up with LINQ, but without generics?]

And no, multiple constructors do not make that crucial guarantee, that every value can be produced by every selector.

Good point, though that is probably not enforceable by an implementation of D.  In any case, four of the six factory methods of Instant have that property.

Of course it's enforceable, it's baked into the DNA of the language and part of the unit test suite. But perhaps you mean that it might not be implemented, and there is indeed no enforcement of that.

Andl - A New Database Language - andl.org
Quote from AntC on June 17, 2019, 1:00 am
Quote from Dave Voorhis on June 16, 2019, 10:42 am
Quote from AntC on June 16, 2019, 9:08 am
Quote from johnwcowan on June 15, 2019, 9:59 pm

expose multiple constructors for their objects, which iff immutable are exactly instances of TTM scalar types.

Just. No. TTM does not have 'objects', that is does not have values encapsulated inside things whereby you must call methods to access the values. TTM's scalar types, Selector-defined types with components, attribute values and their types are all plain compare-by-value not compare-by-reference.

The Java immutable class Instant exposes no less than six, taking these respective arguments:

  1. the number of seconds since the Epoch,
  2. the number of milliseconds since the Epoch,
  3. the number of seconds and the number of nanoseconds within that second since the Epoch
  4. ...

There's nothing corresponds to that in TTM. Just. No. I'm on the verge of saying "not even wrong".

I might quarrel with some of John's choice of terminology, e.g., "expose multiple constructors for their objects, which iff immutable are exactly instances of TTM scalar types." (emphasis mine) -- where "selected values of TTM types" would be preferable to "instances of TTM scalar types" to avoid even a hint of TTM/OO mashup ...

Sorry Dave, I don't think you have avoided polluting this with OO concepts. I can't reconcile what you claim with TTM's Pres and Pros.

However, John's point -- that the facility for multiple constructors for an immutable value class in a typical object-oriented language is notionally isomorphic to TTM's multiple possreps -- is sound:

In a typical object-oriented language, multiple constructors for a given class may be used to create various instances which have an unspecified and hidden internal representation, but that appropriately reflects the chosen constructor.

Firstly there's Hugh's repeated and vehement objection to regarding TTM Selectors as equivalent to OO constructors.

Would I be right in thinking that invoking one of these constructors:

a) Allocates a patch of memory;

b) Executes some code to put values into that memory;

c) Returns a pointer to that memory?

OK it's an immutable value ex hypothesi, but it's a pointer (contra OO Pro 2) not a value simpliciter.

Would I be further right in thinking that distinct program code that invokes the same constructor with the same arguments would also allocate a different patch of memory and return a different pointer value? Then

All instances of that class can be compared with each other as if they had all been instantiated with the same constructor.

There might be a comparison operator (however it's spelled) that says the references at the ends of those pointers are the same value. But this being OO, there's also a differently-spelled operator that will distinguish whether they're the same pointer and tell you they're not the same. So this fails the Leibniz equality test RM Pre 8 "It follows from this prescription that if ...", that I quoted recently.

Then OO multiple-constructors are not "isomorphic to TTM's multiple possreps". There is deliberately no operation allowed by TTM that is isomorphic to testing for pointer equality. Prefixing "notionally" is just weasel-words trying to evade a logical difference -- one of those big ones.

This highlights the almost-inevitable pitfalls of comparing language X to language Y, particularly comparing language feature X.x to language feature Y.y: For every set of isomorphisms identified between X.x and Y.y by observer A, there exists some observer B who will identify one or more distinctions between X.x and Y.y that allegedly cancel out all the isomorphisms.

I think there is over-emphasis here on the significance of references/pointers in object oriented programming languages, at least compared to TTM. Yes, TTM is strictly value semantics and object oriented languages aren't, but in this case, focusing on it is a misdirection. It's like being told that internal combustion engines are essentially the same in cars and motorcycles -- they both have pistons, fuel injection (or carburation), a crankshaft and valves (if 4-cycle) -- but insisting they're different because motorcycles have two wheels and cars have four.

Again, I note these similarities between TTM multiple possreps and object oriented programming's multiple constructors (or static methods returning instances):

  • In a typical object-oriented language, multiple constructors for a given class may be used to create various instances which have an unspecified and hidden internal representation, but that appropriately reflects the chosen constructor. All instances of that class can be compared with each other as if they had all been instantiated with the same constructor.
  • Similarly, in TTM, multiple possreps for a given type may be used to select various values which have an unspecified and hidden internal representation, but that appropriately reflects the chosen selector. All values of that type can be compared with each other as if they had all been selected with the same selector.

Yes, there are certainly significant differences in terms of overall language semantics, but we're not talking about value semantics vs reference semantics here, or the fact that you can compare pointers in object oriented languages. Those differences don't undo my noted similarities. We're talking about engine similarities here, not differences in the number of wheels.

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org
Quote from dandl on June 17, 2019, 4:54 am

And no, multiple constructors do not make that crucial guarantee, that every value can be produced by every selector.

Good point, though that is probably not enforceable by an implementation of D.  In any case, four of the six factory methods of Instant have that property.

Of course it's enforceable, it's baked into the DNA of the language and part of the unit test suite. But perhaps you mean that it might not be implemented, and there is indeed no enforcement of that.

How is enforcing that "every value can be produced by every selector" baked into the DNA of the language (which language?) and part of the unit test suite (what unit test suite?)

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org
Quote from Dave Voorhis on June 17, 2019, 9:32 am

How is enforcing that "every value can be produced by every selector" baked into the DNA of the language (which language?) and part of the unit test suite (what unit test suite?)

Indeed, if an implementation can prove that the range of a function is equal to its codomain, it can also solve the halting problem.  See Rice's theorem.

Quote from Dave Voorhis on June 17, 2019, 9:32 am
Quote from dandl on June 17, 2019, 4:54 am

And no, multiple constructors do not make that crucial guarantee, that every value can be produced by every selector.

Good point, though that is probably not enforceable by an implementation of D.  In any case, four of the six factory methods of Instant have that property.

Of course it's enforceable, it's baked into the DNA of the language and part of the unit test suite. But perhaps you mean that it might not be implemented, and there is indeed no enforcement of that.

How is enforcing that "every value can be produced by every selector" baked into the DNA of the language (which language?) and part of the unit test suite (what unit test suite?)

I really don't understand the question.Is it that you don't know, or that you think you know better?

The language of course is an implementation of D designed to conform to TTM. The language designer provides means to create types as specified in RM Pre 4. The designer chooses a strategy for physical representations, POSSREPs and selectors such that the requirements of RM Pre 4 are satisfied by design (by proof), and creates a suite of unit tests to be confident that the implementation has been completed successfully.

I admit that this is somewhat less certain for system types, which may be implemented  by means outside the language designer's control, but the same principle applies. This is just boring old software engineering. Sometimes we make mistakes (we call them bugs, for historical reasons), but mostly we get it right sooner or later.

As it happens, the only language I know with a faithful implementation of POSSREPs is Rel, so maybe you better ask Dave if that roughly matches what he did.

Andl - A New Database Language - andl.org
Quote from dandl on June 17, 2019, 4:54 am

Everything you say here I already know

When I respond to your message, I am not necessarily addressing only you, or in some cases not you at all.

 [Aside: do you know why SmallIntegers are 30 bits? It's horrible, but it was the only way they could get the code to run fast enough.]

Lisps have been using this device since about 1963, and no, I don't think it's horrible.  Note that though the fixnum type is normally aligned with this representation, the standards do not actually require that, only that a fixnum be large enough to address arrays.

[And yes, I have often lamented the shortsightedness of the various owners of Java for not biting the bullet early on and implementing value types, generics and fixed a couple of other minor things when they could have (such as the date/time types). They've finally caught up with LINQ, but without generics?]

Hindsight is 20/20, and Anders Hejlsberg had the inestimable advantage of not having to maintain backward compatibility with a large installed base of programs.  See also Guy Steele's "Growing a Language"

 

Quote from dandl on June 17, 2019, 10:58 am
Quote from Dave Voorhis on June 17, 2019, 9:32 am
Quote from dandl on June 17, 2019, 4:54 am

And no, multiple constructors do not make that crucial guarantee, that every value can be produced by every selector.

Good point, though that is probably not enforceable by an implementation of D.  In any case, four of the six factory methods of Instant have that property.

Of course it's enforceable, it's baked into the DNA of the language and part of the unit test suite. But perhaps you mean that it might not be implemented, and there is indeed no enforcement of that.

How is enforcing that "every value can be produced by every selector" baked into the DNA of the language (which language?) and part of the unit test suite (what unit test suite?)

I really don't understand the question.Is it that you don't know, or that you think you know better?

The language of course is an implementation of D designed to conform to TTM. The language designer provides means to create types as specified in RM Pre 4. The designer chooses a strategy for physical representations, POSSREPs and selectors such that the requirements of RM Pre 4 are satisfied by design (by proof), and creates a suite of unit tests to be confident that the implementation has been completed successfully.

I admit that this is somewhat less certain for system types, which may be implemented  by means outside the language designer's control, but the same principle applies. This is just boring old software engineering. Sometimes we make mistakes (we call them bugs, for historical reasons), but mostly we get it right sooner or later.

As it happens, the only language I know with a faithful implementation of POSSREPs is Rel, so maybe you better ask Dave if that roughly matches what he did.

It's that I really didn't know. Your wording implied a specific D with (presumably) existing unit tests. I see now you were speaking (writing) hypothetically.

Ensuring that "every value can be produced by every selector" is technically unenforceable; it can only be satisfied by design. Even a comprehensive unit test suite, to be truly comprehensive, might not show a green bar until well after the heat death of the universe.

I'm pretty sure POSSREPs in Rel work as they should (modulo known bugs and limitations), but there is no way to guarantee -- in any automated fashion -- that every user-defined type guarantees that every value can be produced by every selector.

I'm the forum administrator and lead developer of Rel. Email me at dave@armchair.mb.ca with the Subject 'TTM Forum'. Download Rel from https://reldb.org
PreviousPage 5 of 7Next