[fpc-devel] RFC: Support for new type "tuple" v0.1

Alexander Klenin klenin at gmail.com
Sun Jan 27 12:02:31 CET 2013


On Sun, Jan 27, 2013 at 12:35 PM, Hans-Peter Diettrich
<DrDiettrich1 at aol.com> wrote:
>>   (a, b) := (b, a); // the compiler needs to ensure the correct usage of
>> temps here!
>
>
> What will happen here?
>
> At compile time a tuple type (integer; integer) has to be defined, and an
> instance must be allocated for it. Initialization and finalization
> information/code must be added if required.
>
> At runtime the arguments are copied into that tuple instance, then copied
> into the target variables. All "copies" may be subject to type conversions
> and reference counting.
>
> Consider memory usage and runtime when tuples are nested, or contain large
> data structures (records, static arrays...).

Any time large data structures are used as values (as opposed to references),
the incur memory and run-time overhead -- parameter passing, assignment, etc.
Tuples are neither better not worse in this aspect.
Additionally, standard optimization techniques may be used to
significantly reduce
or even eliminate the overhead:
a, b := b, a
=>
temp1 := b;
temp2 := a;
a := temp1;
b := temp2;
=>
optimizer may notice that temp1 is redundant
=>
temp2 := a;
a := b;
b := temp2;

which is exactly equivalent to manually written code.
Also note that in my version of proposal, nested tuples are impossible.

>>   a := 42;
>>   (a, e) := (a * 2, a); // (a, e) should be (84, 42), not (84, 84)
> Such code tends to become cryptic with larger tuples.
> High level (source code) debugging will be impossible :-(
Why do you think so? I think adding tuples as watchable item to debugger
is rather straight forward, although a bit redundand.
Actually, even totally independently from tuples,
allowing to enter several comma-separated values in evaluate/modify window
to be displayed at once would be a useful feature.

>> * Possible extensions
>>
>> Note: This section is not completely thought through!
>>
>> An possible extension would be to allow the assignment of tuples to
>> records and/or arrays (and vice versa). [...]
>
> Without references to distinct tuple elements the coder has to provide local
> variables for *all* tuple elements, then decompose the *entire* tuple,
> before access to a single element will be possible. This may be accomplished
> with less source code when a tuple can be assigned to a record variable, but
> then it would be simpler to use records *instead* of tuples.
This is why I think tuples as a data type are not needed.
Instead, I suggest them as a powerful way to manipulate
records, arrays, and parameter lists using one relatively simple concept.
Also, note "nil as lvalue" paragraph of my proposal, which allows to
deconstruct only part of tuple,
ignoring the rest.

BTW, I just remembered another tuple usage example:
type
  T3DMatrix = array of array of array of Double;
  TMatrixPos = array [1..3] of Double;

procedure P(A: T3DMatrix; APos1: TMatrixPos);
begin
  A[Tuple(APos1)] := 1.0; // Instead of A[APos[1], APos[2], APos[3]]
end;

> When a record type is modified, during development, all *compatible* tuples
> and tuple types must be updated accordingly.
True. Similarly, when a procedure is modified, all call sites must be updated --
note that there is deliberate analogue between tuples and parameter
lists in my proposal.

>> - use for multivalues return values which can make the code more readable
>> (instead of using records or out parameters)
>
> This IMO makes sense only when such tuples are passed along many times,
> before references to their elements occur. Otherwise full tuple
> decomposition is required when e.g. only a succ/fail indicator in the result
> tuple has to be examined.

Not necessarily. There are, as you know, two basic styles of error handling:
exceptions and error codes. Most of Pascal code is based on exceptions,
but there are cases, for example embedded programming, server/service
programming,
where using error codes is advantageous.
In that case, using (result, error) tuple as a standard return value
is a good convention.
There are languages (Go is a most modern example), where this convention is used
as a primary method across all standard library.

>> - use as result value for iterators (this way e.g. key and data of
>> containers can be queried)
> This reminds me of SQL "SELECT [fieldlist]", where *specified* record fields are copied.
That is correct analogy -- in some variants of relational theory,
term "tuple" is used to mean "database record".

> But I wonder how confusion can be eliminated in the order of the
> tuple elements. Will (k,v) or (v,k) be the right order for key and value?
> What are the proper types of key and value?
If you want to find a substring in a string, do you write
Pos(str, substr) or Pos(substr, str) ?
To find out, use function signature (in the case of tuples, return
value type fields).
If all else fails, there is (maybe) documentation :)
Note that in my version of tuples proposal tuples are decoupled from
"records without field names".

> SSE should be used with array types, where all elements *definitely* have
> the same type. Then one "+" operator can be implemented for open arrays of
> any size, what looks quite impossible for tuples.

Speaking specifically of SSE, array size is fixed by the processor architecture,
so there is no need for arbitrary sizes.
Nevertheless, I agree that in this example, tuples are useful mostly
as an array constructor/
deconstructor, and the operation itself should be defined on array type.

> IMO tuples are *abstract* templates (mathematical notation) for *concrete*
> (record...) implementations. I see no need or purpose in the introduction of
> such an abstract type into any concrete language, except when that languages
> lacks an already existing record (or equivalent) type.
I agree with the premise, but not with the conclusion. As already
stated, I propose tuples
as a tool/syntax for manipulation of records, not as a separate type.

--
Alexander S. Klenin



More information about the fpc-devel mailing list