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

Alexander Klenin klenin at gmail.com
Sun Jan 27 20:56:41 CET 2013


On Mon, Jan 28, 2013 at 4:46 AM, Hans-Peter Diettrich
<DrDiettrich1 at aol.com> wrote:

> Preface: In the following I assume that tuples can be implemented by
> records. The proposed syntax extensions can be applied to records as well,
> they are not restricted to a new type.
Ok, with a few caveats listed below.

>> 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.
>
> My point is the artificial overhead, introduced in above example. The code
> may *look* elegant, but in fact is a resource hog.
The only artificial overhead is using two temporary variables instead of one.
As I have demonstrated in previous messages, this overhead can, in principle,
be removed by optimizer.

>> Also note that in my version of proposal, nested tuples are impossible.
> I consider this an inacceptable restriction. Records can contain other records.
Yes, but tuples are just a syntax for constructing/deconstructing
records, not records themsleves.
They can be converted to a specific record type by casting.
Consider these examples:
var
  x, y, z: Integer;
  pt: TPoint;
...
(x, y)                      // record a, b: Integer; end;
(x, (y))                    // record a, b: Integer; end;
(x, (y, z))                // record a, b: Integer; end;
(x, TPoint(y, z))       // record a: Integer; b: TPoint; end;
(TPoint(x, y), TPoint(y, z))       // record a, b: TPoint; end;
(TPoint(x, y), pt)       // record a, b: TPoint; end;
(TPoint(x, y), Tuple(pt))   // record a: TPoint; b, c: Integer; end;

>>>> * Possible extensions
>>
>> 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.
>
>
> I doubt that a concept alone will help. I see the proposed extensions as an
> attempt to introduce elements from *functional programming* languages, for
> which OPL lacks many prerequisites.
True, functional programming is certainly the lergest modern paradigm
still lacking from FPC.
As for prerequisites, there are mostly closures/anonymous methods,
which are discussed in a parallel thread, and perhaps purity
annotation, which may be helpful,
but is optional.
After that, FPC will support FP as well as previous paradigms:
OOP, procedural, and structured programming.

>> Also, note "nil as lvalue" paragraph of my proposal, which allows to
>> deconstruct only part of tuple,
>> ignoring the rest.
> Just another syntax for accessing record members.
Yes, but a useful one in the context of a proposal.
Note yet another example of my proposal I have not yet provided:
Since procedure arguments are considered tuples, nil could also be used
in plase of "out" paragemets which are not needed by caller, e.g.:
instead of
var
  dummy: Integer;
...
Val(s, i, dummy);
it would be possible to write just
Val(s, i, nil);

>> 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;
>
>
> I'd accept a TMatrixPos as an array of Integer,
That was just my mistake, of course i meant aray of Integer, sorry.


> Why do you expect any difference between
>    A[Tuple(APos1)] := 1.0;
> and
>    A[APos1] := 1.0;
> ?
> The compiler will have to create the same code for both notations, or use
> the same RTL subroutine for doing the job.
The idea is that second case will require a manually-written operator[],
while the first one will work automatically.
So, again, just a syntax sugar -- but useful one.

>> 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.
>
> That's something very different, IMO. I frequently miss the lack of
> subroutine argument "templates", when e.g. implementing event handlers.
> Currently it's impossible to declare a method like
>   procedure OnClick(TNotifyEvent);
> or
>   handler OnClick: TNotifyEvent;
> with the compiler creating the right method signature (of TNotifyEvent), or
> of some much more complex event handler type.

You may be interested to know that i have just proposed exacty such an extension
in a parallel thread discussing anonyomous procedures.
Currently proposed syntax is:

OnClick := lambda TNotifyEvent
begin
end;

> But subroutine signatures are *declarative* elements with their own syntax,
> different from record or tuple declarations. Would you really extend the
> tuple declaration syntax, so that it could be used like e.g.
>   type MyTuple: (var Integer; array Of Char; const String default '');
That has certainly crosed my mind, but I decided to go one step at a time.
There is certainly much to discuss even with the current proposal.
Nevertheless, I did propose to use tuples in position of procedure *arguments*,
not parameters -- see my first mail in this thread.

>> 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.
>
>
> SEH has one big advantage: nobody can forget to test an error value. That's
> why it is used in Java, with further support (throws...).
>
> One problem with error codes is their data type. Booleans are not always
> sufficient, integers have no obvious meaning. That's why I prefer to use
> enumerated types with descriptive names. Which types would your *standard*
> return tuple contain?
Note again that I did not mean tuple to be a type, so what I suggested is a
convention, which might be adopted by some library for real-time,
embedded or other
low-level usage where exceptions add too much overhead:
res, error := SomeFunction(params);
where types of result and error will be chosen as appropriate for each function.
The advantages over usual
res := SomeFunction(params, error)
being:
1) Easier to read, once reader knows the convention
2) Ignoring error is more prominent:
res, nil := SomeFunction(params);
3) Since the result is actually a record, functions may still be
chained, while ignoring errors:
SomeFunction1(SomeFinction2(params).res);
You may look at http://golang.org/doc/effective_go.html#errors for
similar feature in Go.

> Of course this could be optimized, when the compiler is extended to
> move the result tuple into distinct hidden subroutine arguments (types
> omitted):
Note that at machine code level, there is no difference between
"distinct hidden subroutine arguments"
and "single result of a record type", so compiler already does what you suggest.

>>> 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).
>
> The compiler cannot find out when two or more (tuple) members of the same
> type are in wrong order.
And is also can not find out when two or more procedure parameters of
the same type
are in wrong order. This is exactly the same situation.

>> Note that in my version of tuples proposal tuples are decoupled from
>> "records without field names".
>
> I'm not sure what you exactly mean. In my proposal, that tuples are nothing
> but records, it's immediately clear whether and how every syntax extension
> can be implemented. Any "decoupling" risks to run into dead ends, because
> the implementation efforts are unpredictable.

I mean not decoupling of records, just of suggestion to allow defining
record types without field names.

> It would help a lot in understanding your ideas, when you mention the
> record-based implementation for every proposed syntax extension.
Will try -- I thought implementation was obvious (which does not mean
it is easy, of course).

--
Alexander S. Klenin



More information about the fpc-devel mailing list