Unifying TUPLE! and PAIR! and 0.1 vs .1

We need a coherent generic TUPLE!. But being fully generic is obstructed as people do not want to let go of 6.28 being a DECIMAL!

Dots in tuples are mostly non-negotiable Not that I'm too concerned about representing IPv4 addresses accurately, or that I think colors represented as 255.255.0 are all that important either. It's the higher purposes I have in mind that are more concerning foo,bar: 10 just doesn't have a good look and feel to it. foo.bar: 10 does. That just happens to mesh with the fact that 1.2.3.4 looks better than 1,2,3,4 for purposes of an "atomic" value.

We can solve it by unifying PAIR! and TUPLE!

PAIR! can exist, but as a type constraint. So pair? tells you if you have a tuple of length 2. We need to rig up ways to do type tests like this in function parameters and such, so we use whatever that mechanism is to make PAIR! work for that.

If you have a two-element TUPLE! and its first and second items are numbers, you get an x instead of a dot:

>> to tuple! [1 2]
== 1x2

>> to tuple! [1 foo]
== 1.foo  ; second isn't a number, so no conflict

>> foo: 10
>> compose (foo).20  ; I'll have lots more to say about the power of this
== 10x20

Then we only have to worry about two more case, which is what to do when a tuple is blank in the first spot but has a single integer in the second. Or blank in the second spot with a single integer in the first.

We can't use x in this case, nor would we want to:

foo: 10
>> compose .(foo)
== x10  ; collides with variable named X10

So this means a small sacrifice for the math heads: 0.5 and 5.0 are DECIMAL!, but .5 and 5. are TUPLE!, just as /5 and 5/ are PATH!. If you're building some tabular data where you like the idea of having .5 and 5. be shorthands for numbers then go ahead, you'll just have to use TO DECIMAL! on them before you perform math on them.

So we sacrifice one tuple form and get the nice historical PAIR! look out of it. The result is a full spectrum answer for TUPLE!. Like PATH!, it can hold any number of WORD!, INTEGER!, BLOCK!, GROUP!, or TEXT! ... where the number of items is greater than 2.

There will be compression methods to take advantage of with single-item ANY-TUPLE! and ANY-PATH!, as well as two-item cases, or cases where they are all byte-sized numbers. There will be no length limit (e.g. no MAX_TUPLE)... if you exceed what can be stored in the cell, it will just make a series to store the data. Lots of opportunities opened up since TUPLE! and PATH! are top-level immutable...and COMPOSE is going to be great.

1 Like

See if I completely understand. So if we compose a bunch of pairs axb and sometimes a and/or b equals 0, we get nice decimals for those?

I am from Europe so in COBOL it was always "DECIMAL POINT IS COMMA", the comma used for decimals and the dot for separating multiples of thousands. Where a dot is easier to overlook than a comma, a missed dot as separator is not fatal in any way. But if you are from a part of the world where the use is reverse from that I can image that sentiment, all calculators use a dot because that is easier and cheaper on the old displays. Besides, I imagine

Too bad, but I sense you are close to nailing this issue, and PAIR! an be a subtype from TUPLE! ?

There will be cases for BLANK! and for NULL.

If you put a NULL in a pair, it will become to a single element:

 >> x: compose (if false [10])x20
 == 20

 >> type of x
 == @[integer]

If you use a BLANK!, it will still hold the slot...but invisibly so in the rendering:

 >> y: compose (try if false [10])x20
 == .20

 >> type of y
 == @[tuple]

 >> length of y
 == 2

  >> type of first y
  == @[blank]

  >> type of second y
  == @[integer]

If this bothers someone enough to think they want more checking, you could have helper functions like MAKE-PAIR that only take INTEGER!, etc.

I'm very confident this is all on the right track; just based on how well everything is folding together.

I haven't spent much time with PAIR!. But one thing I know about it is that allowing DECIMAL! in pairs really mucked them up. Decimal numbers can get pretty ugly, and there's a lot of rounding issues.

DECIMAL! will not be supported in TUPLE! for a number of reasons. You can put one in a BLOCK! or a GROUP! of a tuple element, but not insert it directly:

>> [10.20].[3.04]
== [10.20].[3.04]

>> '(10.20).(3.04)  ; evaluator active, so must quote
== (10.20).(3.04)

This means that with PAIR! as a subclass of tuple, decimal support will be dropped there as well in the "x" case:

>> compose (10).(3)
== 10x3

 >> compose (10.20).(3.04)
 ** Error: DECIMAL! not allowed in TUPLE!

Which is good, because I've really wanted to get rid of it for other reasons. Namely that decimals are wily in their rendering and precision, and make a big mess. Integers are much cleaner.

You'd think anyone were to complain about missing features of PAIR!, it would be Red. But they only have integer pairs. Using decimal causes... um... who knows what, but it's not decimals:

red>> 1.5x3.5
== 2645x2845  ; Er, what?

red>> make pair! [10.20 3.04]
== 10x3  ; okay, rounded