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

2013-01-28 Thread Alexander Klenin
On Mon, Jan 28, 2013 at 7:25 PM, Hans-Peter Diettrich
drdiettri...@aol.com wrote:
 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;


 I don't see the correspondence between the left and right sides, sorry.
 I also dont see whether the left sides are tuple constructors or
 deconstructors, what's the intended effect...

Right side contains examples of records which would be compatible with
the tuples on the left -- for both construction and deconstruction.

 True, functional programming is certainly the largest modern paradigm
 still lacking from FPC.

 What's modern? I've learned about functional programming in 1970 - did
 all the following languages miss something important?
Current consensus in the field of programming languages design is
that they did -- which is why FP features are added to just eny
language you look at,
from C++ to PHP :)

 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.

 NACK. How comes that the compiler should break a tuple into a list of
 indices, but not an array? In detail when the tuple contains such an array?
Well, that was the idea, auto- breaking a tuple but not an array,
so by converting array to tuple programmer can control it.

 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);

 The latter looks like breaking tuple rules, by acessing a tuple element by
 name.
The record becomes a tuple only by either explicit conversion,
or deconstructing assignment.

 This means more writing, and the typical use of error codes becomes much
 more complicated IMO:
   if f(x, res) then ...
 has to be rewritten as
   res, error := f(x); //or: (res,error) := f(x);?
   if error then ...
That depends on the type or err



 That's why I wonder about yet another syntax proposal. Your proposal
 *requires* that a record/tuple type *is* used for the result, where
 otherwise the subroutine could return the result in an CPU or FPU register,
 ready for immediate further use.
There is no reason why a record can not be returned in a register.
Actually, there is perhaps even greater chance for that compared to
out parameter,
which is usually implemented as pointer.

--
Alexander S. Klenin
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Alexander Klenin
On Sun, Jan 27, 2013 at 12:35 PM, Hans-Peter Diettrich
drdiettri...@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 + 

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

2013-01-27 Thread Michael Van Canneyt



On Sun, 27 Jan 2013, Alexander Klenin wrote:


On Sun, Jan 27, 2013 at 4:43 AM, Sven Barth pascaldra...@googlemail.com wrote:

Based on the results of the for-in-index thread I've decided to come up
with a draft for the Tuple type which is thought by many people to be a
better alternative to for-in-index.

Please note the following points:
* This is not the final specification for Tuples and thus open to discussion
(there are still some issues with this draft that need to be solved)
* I won't implement this feature myself (at least not in the near future) as
I have other topics on my list (most importantly generics once type helpers
are commited), so Alexander is free to give the task for implementation to
his student.



Heh, I have started to write similar in form, but different in
substance proposal, but needed some sleep,
and you have beaten me to it :)

I want to quickly summarize the most important points of my proposal
before writing it out in length:

1) In a form proposed by Sven (and, IIUC, implemented in Oxygen),
tuples are not different enough from records
(so perhaps a term like anonymous records is preferable, as well of
re-using keyword record).
I agree that anonymous records might be good, but I consider them a
separate, and weaker, extension.

2) The most important differentiating features of my proposal are:

2.1) Tuples are always temporary and anonymous. You can not store a
tuple, define tuple type, of variable of tuple type.
 So tuples are 100% static, compile-time feature -- no change to
RTTI, variants etc.


No.

I think that tuples should be a full fledged type, not an anonymous 
one with all the restrictions that come from it. Pascal is declarative.

So, you must declare a tuple when you want one.

As for notation:
Adding the () brackets to indicate a tuple adds to clarity, simply 
relying on the comma to indicate a tuple is not acceptable. 
Pascal IS a verbose language. If you want unreadable: go for Javascript.


I consider Sven's proposal the one to go for. 
It is more in line with what Object Pascal stands for.


The idea of a tuple is already a concession to avoid the for in index 
monstrosity.

So let's not get carried away too much.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Sven Barth

On 27.01.2013 02:35, Hans-Peter Diettrich wrote:

Sven Barth schrieb:


* Description

What are tuples? Tuples are an accumulation of values of different or
same type where the order matters. Sounds familiar? They are in this
regard similar to records, but it's only the order of an element that
matters, not its name. So what does make them special? Unlike records
you can only query or set all the elements of a tuple at once. They
basically behave like multiple assignments. In effect they allow you
to return e.g. a multivalued result value without resorting to the
naming of record fields (you'll still need to declare a tuple type) or
the need for out parameters. This in turn allows you to use them for
example in for-in loops.


The lack of element names results in bloated code and runtime overhead.
See below.



I don't see why it should result in bloated code and runtime overhead.


* Declaration:

[...]


The usage of constructors and destructors also allows a realisation of
group assignment:

=== code begin ===

var
  a, b, e: Integer;
  c, d: String;
begin
  a := 42;
  c := 'Hello World';
  (b, d) := (a, c);
  a := 21;
  b := 84;



  (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.


And here you are wrong. We have an assignment node with a tuple node on 
the left and a tuple node on the right. So the compiler can insert 
direct assignments between the corresponding elements on the left and 
right maybe with the need to insert a few temp vars to resolve cases 
like the above. And even then the optimizer can reduce the amount of 
temps. So the amount of temps is normally less or equal to the count of 
elements, but often it should be less than the count of elements.


If a tuple node is only on one side of the assignment and the other one 
is a load node for a tuple variable then construction/deconstruction 
(depending on the side) will take place.




Consider memory usage and runtime when tuples are nested, or contain
large data structures (records, static arrays...).



You'll have similar memory usage and runtime problems when you don't use 
tuples...



  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 :-(




You can also write cryptic code without tuples. Also why should 
debugging become impossible? It's just a matter of adding the correct 
debug information.



[...]

* 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.


There is always Michael's idea of single element access (which can be 
extended by allowing ranges)...




When a record type is modified, during development, all *compatible*
tuples and tuple types must be updated accordingly.



If you modify code it's likely that you need to modify other parts anyway...


* Possible uses

- use for group assignments which can make the code more readable

... or unreadable (see above).


- 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.


- 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. 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?


The order of key and value will depend on the corresponding 
implementation. You need to look this up like you need to look up other 
things as well. By implementing builtin enumerators and those of the FCL 
consistently we might be able to provide a guide for other developers...


And the types of key and value depend on what your key and your value 
is. You have the same problem currently as well 

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

2013-01-27 Thread Alexander Klenin
On Sun, Jan 27, 2013 at 10:10 PM, Michael Van Canneyt
mich...@freepascal.org wrote:
 2.1) Tuples are always temporary and anonymous. You can not store a
 tuple, define tuple type, of variable of tuple type.
  So tuples are 100% static, compile-time feature -- no change to
 RTTI, variants etc.
 No.

 I think that tuples should be a full fledged type, not an anonymous one with
 all the restrictions that come from it.

Let me restate:
1) Tuple as a type does nothing new compared to a record, except for
possibility to omit field names.
2) While I agree that omitting field names might be a useful shortcut,
it is wasteful to introduce a whole new
  keyword and syntax just for that -- I propose to just extend record
syntax, possible variants:
  type TKeyValue = record (Integer, String) end;
  type TKeyValue = record of Integer, String end;
  type TKeyValue = record Integer; String end;
  type TKeyValue = (Integer; String);
3) The main part of the feature, IMHO, is a new tools for record and
array manipulation -- construction and deconstruction of tuples.
  So in my proposal, tuple is not a type, but a concept underlying a
syntax construct -- similar to, for example,
  a sequence of statements, or a parameter list.

 Pascal is declarative.
No, it is not.
http://www.britannica.com/EBchecked/topic/417798/declarative-language
http://en.wikipedia.org/wiki/Declarative_programming

I think you meant that in Pascal identifiers must be declared before
usage -- that is true,
and of course tuples proposal agrees with that.

 So, you must declare a tuple when you want one.
Consider the most basic example:
a, b := b, a;
What do you propose to declare here?

 As for notation:
 Adding the () brackets to indicate a tuple adds to clarity, simply relying
 on the comma to indicate a tuple is not acceptable. Pascal IS a verbose
 language. If you want unreadable: go for Javascript.
Verbosity in Pascal usually comes from using more keywords, not more
punctuation.
Using comma only would simplify grammar
(and possibly parsing, although I am not sure of that -- FPC parser is
not easy to understand).
Consider, again:

for k, v in a do
vs
for (k, v) in a do

a, b := b, a;
vs
(a, b) := (b, a);

DrawLine(Tuple(ARect), AColor);
vs
DrawLine((Tuple(ARect), AColor));

Why do you think second examples are more clear then first ones?
Of course, if the expression becomes complex, programmes may add brackets --
as is already the case with other expressions.

OTOH, this is the point I am willing to concede --
the difference is rather small.

--
Alexander S. Klenin
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Michael Van Canneyt



On Sun, 27 Jan 2013, Alexander Klenin wrote:


On Sun, Jan 27, 2013 at 10:10 PM, Michael Van Canneyt
mich...@freepascal.org wrote:

2.1) Tuples are always temporary and anonymous. You can not store a
tuple, define tuple type, of variable of tuple type.
 So tuples are 100% static, compile-time feature -- no change to
RTTI, variants etc.

No.

I think that tuples should be a full fledged type, not an anonymous one with
all the restrictions that come from it.


Let me restate:
1) Tuple as a type does nothing new compared to a record, except for
possibility to omit field names.


That's all we need.



2) While I agree that omitting field names might be a useful shortcut,
it is wasteful to introduce a whole new
 keyword and syntax just for that -- I propose to just extend record
syntax, possible variants:
 type TKeyValue = record (Integer, String) end;
 type TKeyValue = record of Integer, String end;
 type TKeyValue = record Integer; String end;
 type TKeyValue = (Integer; String);
3) The main part of the feature, IMHO, is a new tools for record and
array manipulation -- construction and deconstruction of tuples.
 So in my proposal, tuple is not a type, but a concept underlying a
syntax construct -- similar to, for example,
 a sequence of statements, or a parameter list.


That is exactly what I want to avoid; messing with syntax.

I think that Sven (or Oxygen, they apparenly have it too) has more 
succeeded in preserving the essence of Pascal than your proposal does.


Sven's proposal is the least invasive in terms of concepts and whatnot.
It is simply a new type, and besides solving your original problem, it has
additional advantages: I see Python has it too, so it gives you 
ammunition in that discussion too.


I do not wish to reuse the record keyword, because the record syntax is 
already messy as it is with the variant parts.


The TKeyValue = (Integer; String); is too reminiscent of an enumerated.
The only thing that differentiates it is the use of type names. 
At the level of a parser, you have no way to decide what you are 
parsing without knowing what the symbols are.





Pascal is declarative.

No, it is not.
http://www.britannica.com/EBchecked/topic/417798/declarative-language
http://en.wikipedia.org/wiki/Declarative_programming

I think you meant that in Pascal identifiers must be declared before
usage -- that is true,
and of course tuples proposal agrees with that.


My apologies for the mixup in terminology, the latter is what I meant.

But the latter is why I think Sven's proposal (or the Oxygen implementation)
is more appropriate than yours:
- No messing with syntax, just a new type.
- Ability to declare a named type (not anonymous).

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Michael Van Canneyt



On Sun, 27 Jan 2013, Paul Ishenin wrote:


27.01.13, 1:43, Sven Barth wrote:

Based on the results of the for-in-index thread I've decided to come
up with a draft for the Tuple type which is thought by many people to be
a better alternative to for-in-index.


I think it is big overkill to implement a new base type for such a small task 
as returning a key in for-in loop.


And (for Michael) I don't see any beauty in this. Imo, initial index 
extension is much more beauty than suggested here (a,b,c) := d; 
constructions.


Well, there we obviously differ in opinion.

To be clear: I am not a proponent of tuples. I can live without it.

But the for in index solves exactly 1 problem, and a very very very small one at that, 
(in fact, I don't even think it is a problem) which can be solved in many different ways as well.


A tuple at least has the potential to solve more than one problem.
Oxygene and python have tuples. Maybe other languages too; I don't know.

So, if this very very very small maybe even non-existent problem must be soleved, 
I prefer to do it with a tuple.


But hey, if you don't like tuples, and I don't like index: 
We'll do without tuples and index.


I'll be perfectly happy. Many others undoubtedly too. 
Till now I didn't hear you complain about the absence of index, so...


Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Jonas Maebe

On 26 Jan 2013, at 21:45, Alexander Klenin wrote:

 2.2.2) Any record or array type may be converted to a tuple of its
 elements using either assignment or Tuple intrinsic.
 For example: Tuple(ARectangle) is a tuple of 4 elements;
 x, y := APoint; // same as x := APoint.x; y := APoint.y;
[snip]
 2.3.2) When tuple appears inside of a function/procedure argument, it
 is deconstructed, and its elements are passed as a separate arguments.
  Tuple elements corresponding to var, out and constref parameters
 must be lvalues. Note that due to (2.2.2) tuple may represent only
 part of arguments.
  Together with (2.2) we note that normal semantics of procedure
 parameters is left unchanged :)
  We also gain this:
 
 procedure SomeLibrary.DrawLine(X1, Y1, X2, Y2, Color: Integer); //
 Author did forgot/did not want to declare overload with TRect
 parameter.
 ...
 DrawLine(Tuple(ClientRect), clRed); // No need, tuples help here

I don't like these automatic conversions/deconstructions of records at all, nor 
the ability to have the compiler automatically convert a tuple to its component 
elements when resolving function calls. It means that you no longer have a 
tuple type, but rather a deconstruct_into_component_types() type conversion 
operator along with anonymous records. The fact that the tuple() operator is 
required when deconstructing a record when calling a function (as in 2.3.2) 
while it is not when assigning a record to multiple values (as in 2.2.2) shows 
that such automatic conversions are not a good idea. Implicitly applying it in 
one case and not in another is not good, and I'm definitely against 
automatically converting records into its component elements for passing as 
parameters.

A tuple should either be a real type with fixed type conversion semantics that 
behave the same in every situation (like other types, and like how Pascal 
usually works: context-insensitive evaluation of expressions), or not exist at 
all (and this option is certainly fine with me as well). And another option is 
indeed extending the syntax of the for-statement, although there of course also 
downsides to do doing that. However, new magic operators that have their own 
rules are what really complicates a language, both in the compiler 
implementation and for people that have to use it.


Jonas___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Alexander Klenin
On Mon, Jan 28, 2013 at 1:26 AM, Paul Ishenin paul.ishe...@gmail.com wrote:
 27.01.13, 1:43, Sven Barth wrote:

 Based on the results of the for-in-index thread I've decided to come
 up with a draft for the Tuple type which is thought by many people to be
 a better alternative to for-in-index.
 I think it is big overkill to implement a new base type for such a small
 task as returning a key in for-in loop.
Of course. But note that in this thread, many more uses of tuples
(which I do NOT want to make a type -- see my previous mail for
lengthy explanation why).
Some of the uses are: record and array constructors, adaptation of
inconvenient signatures,
better support for return code style of error handling, etc.

 And (for Michael) I don't see any beauty in this. Imo, initial index
 extension is much more beauty than suggested here (a,b,c) := d;
 constructions.
I have a compromise suggestion:
Implement for-index extension with the syntax:
for (k, v) in a do
this syntax is forward-compatible with both tuples proposals,
is simple to do (basically, already done -- only a small change in
parsing is required)
and will give immediate benefit regardless of outcome of larger discussion.

--
Alexander S. Klenin
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Martin

On 27/01/2013 14:42, Alexander Klenin wrote:

On Mon, Jan 28, 2013 at 1:26 AM, Paul Ishenin paul.ishe...@gmail.com wrote:

27.01.13, 1:43, Sven Barth wrote:

Based on the results of the for-in-index thread I've decided to come
up with a draft for the Tuple type which is thought by many people to be
a better alternative to for-in-index.

I think it is big overkill to implement a new base type for such a small
task as returning a key in for-in loop.

Of course. But note that in this thread, many more uses of tuples
(which I do NOT want to make a type -- see my previous mail for
lengthy explanation why).
Some of the uses are: record and array constructors, adaptation of
inconvenient signatures,
better support for return code style of error handling, etc.


If I understand this correct, the ability to return more than one value 
from a function (without out parm) is identical to using a record.

Except you do not want a type declaration for a record.

Therefore in this case tuple becomes an inline (lack of better word) 
declared record (match like you can declare an array outside a type 
section)
And since it has no named type, it is (other tan records) assignment 
compatible if it has the same declaration (same as 2 array of integer, 
only array can not hold different types)


So really here you would need an assignment compatible record (I do not 
say it is a good thing, but if the multi return case is addressed, it 
may be a better way than toupe)


type
  TFoo1 = compatible record  a: integer; b: string end;
  TFoo2 = compatible record  a: integer; b: string end;

function Bar: compatible record  a: integer; b: string end;

and variables/results of any of these are assignment compatible. 
(compatible record can be restricted to none variant records)




And (for Michael) I don't see any beauty in this. Imo, initial index
extension is much more beauty than suggested here (a,b,c) := d;
constructions.

I have a compromise suggestion:
Implement for-index extension with the syntax:
for (k, v) in a do

can be solved with records too?

The typeof(a) needs to declare the key values anyway (provide an 
iterator, or something)


So together with that, a named record (normal record as exists today) 
can be defined? Or am I missing something?



___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Alexander Klenin
On Mon, Jan 28, 2013 at 1:38 AM, Jonas Maebe jonas.ma...@elis.ugent.be wrote:
 you no longer have a tuple type, but rather a 
 deconstruct_into_component_types()
 type conversion operator along with anonymous records.
Yes, this is quite close to what I wanted to propose.
I am glad someone has understood me :)
Please see arguments for this (as opposed to just a tuple type) in my
previous emails.

The fact that the
 tuple() operator is required when deconstructing a record when calling a
 function (as in 2.3.2) while it is not when assigning a record to multiple
 values (as in 2.2.2) shows that such automatic conversions are not a good 
 idea.
Yes, automatic conversions from records is indeed a weak point in my proposal.
It may be dropped, but at a cost of bulkier syntax:
handle, error := Tuple(OpenFile('name'));
vs
handle, error := OpenFile('name');
I am not sure whether to prefer better consistency of better readability.

Perhaps Tuple could be made a keyword instead of intrinsic, and thus
allowed to omit brackets:

handle, error := tuple OpenFile('name');
rectangle := tuple point1, tuple point2;

Alternatively, some kind of tuple operator may be introduced
(yes, I know, everyone is against punctuation -- consider it just a
brainstorming attempt):
handle, error := @@OpenFile('name'); // double-@ is currently useless
handle, error := ,OpenFile('name'); // crazy :)
handle, error := ~OpenFile('name'); // random unused character

 Implicitly applying it in one case and not in another is not good, and
 I'm definitely against automatically converting records into its component
 elements for passing as parameters.
Of course, since it would make it impossible to pass records as parameters :)
Tuple keyword/intrinsic is definitely unavoidable in this case.

 However, new magic
 operators that have their own rules are what really complicates a language,
 both in the compiler implementation and for people that have to use it.
Note that my proposal actually reduces the number of magic operators,
since it unifies the meaning of comma-in-parameter-list, comma-in-open-array
and comma-in-array-index to be the same comma-in-tuple.

--
Alexander S. Klenin
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Alexander Klenin
On Mon, Jan 28, 2013 at 2:01 AM, Martin laza...@mfriebe.de wrote:
 Of course. But note that in this thread, many more uses of tuples
 (which I do NOT want to make a type -- see my previous mail for
 lengthy explanation why).
 Some of the uses are: record and array constructors, adaptation of
 inconvenient signatures,
 better support for return code style of error handling, etc.

 If I understand this correct, the ability to return more than one value from
 a function (without out parm) is identical to using a record.
 Except you do not want a type declaration for a record.

Actually, I have nothing against type declaration of record.
What I want to relax is the restriction that the *caller* must use
a record to receive the value too -- I want to allow assigning result
directly to a list of variables.

 Therefore in this case tuple becomes an inline (lack of better word)
 declared record (match like you can declare an array outside a type
 section)
Yes, this is exactly why I am against introducing tuples as a new data type --
inline (I prefer term anonymous) records are good enough.

 And since it has no named type, it is (other tan records) assignment
 compatible if it has the same declaration (same as 2 array of integer,
 only array can not hold different types)
 So really here you would need an assignment compatible record (I do not say
 it is a good thing, but if the multi return case is addressed, it may be a
 better way than toupe)

 type
   TFoo1 = compatible record  a: integer; b: string end;
   TFoo2 = compatible record  a: integer; b: string end;

 function Bar: compatible record  a: integer; b: string end;

 and variables/results of any of these are assignment compatible.
 (compatible record can be restricted to none variant records)
I do not think compatible records are good enough, because with named records,
the same effect can be achieved simply by type conversion:
x := TFoo1(Bar);

What I want is:
var
  a: Integer;
  b: String;
  c: TIntegerDynArray;
  x: TFoo1;

a, b := Bar;
c[0], b := Bar;
c[i], c[j] := c[j], c[i];
x := Bar; // This will not work with anonymous record
x := TFoo1(a, b);
a, b := x;

etc.

Note that, except for the commented line, it does not matter whether
Bar is declared as
function Bar: TFoo1;
or
function Bar: record  a: integer; b: string end;

 I have a compromise suggestion:
 Implement for-index extension with the syntax:
 for (k, v) in a do

 can be solved with records too?

 The typeof(a) needs to declare the key values anyway (provide an iterator,
 or something)

 So together with that, a named record (normal record as exists today) can be
 defined? Or am I missing something?

You got it right.
More detailed, I suggest to extend Enumerable interface with optional
property CurrentWithKey: TValueKey
where TValueKey must be a record of two (or perhaps even more) fields.
for k, v in a do
will call CurrentWithKey for each item, assign first field to k, second -- to v.
When/if tuples will be introduced, no change will be needed here.

--
Alexander S. Klenin
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Michael Van Canneyt



On Mon, 28 Jan 2013, Alexander Klenin wrote:


On Mon, Jan 28, 2013 at 1:26 AM, Paul Ishenin paul.ishe...@gmail.com wrote:

27.01.13, 1:43, Sven Barth wrote:


Based on the results of the for-in-index thread I've decided to come
up with a draft for the Tuple type which is thought by many people to be
a better alternative to for-in-index.

I think it is big overkill to implement a new base type for such a small
task as returning a key in for-in loop.

Of course. But note that in this thread, many more uses of tuples
(which I do NOT want to make a type -- see my previous mail for
lengthy explanation why).
Some of the uses are: record and array constructors, adaptation of
inconvenient signatures,
better support for return code style of error handling, etc.


And (for Michael) I don't see any beauty in this. Imo, initial index
extension is much more beauty than suggested here (a,b,c) := d;
constructions.

I have a compromise suggestion:
Implement for-index extension with the syntax:
for (k, v) in a do
this syntax is forward-compatible with both tuples proposals,
is simple to do (basically, already done -- only a small change in
parsing is required)


what concerns syntax, I have no problem with this.

What bothers me immensely is the same what bothered me in the totally braindead
Delphi implementation of the for in loop : the bunch of requirements 
you put on the iterator implementation: an interface with special status. 
You can't get more stupid and ugly than that. 
I would gladly kill the borland/inprise/embarcadero engineer who 
thought of this, after torturing him for 3 days, just for unleashing 
this monstrosity on the world...


[Disclaimer: the above is humor. Just trying to show how bad I think it is]

Your initial proposal makes it even worse by adding more conditions to the 
interface,
it would not even be an interface any more.

So: No, no, no. It is ugly beyond words.

That is why I think you need a proper tuple value to solve this.
it gives a more fundamental solution: the loop variable type equals 
the type returned by the iterator/enumerator. No messing with index 
(bad syntax) and even worse: special 'interfaces' and whatnot.


Pascal is a strongly typed language. So, if we absolutely must solve this:
introduce a proper type. A tuple fits the job.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Alexander Klenin
On Mon, Jan 28, 2013 at 2:59 AM, Michael Van Canneyt
mich...@freepascal.org wrote:


 On Mon, 28 Jan 2013, Alexander Klenin wrote:
 I have a compromise suggestion:
 Implement for-index extension with the syntax:
 for (k, v) in a do
 this syntax is forward-compatible with both tuples proposals,
 is simple to do (basically, already done -- only a small change in
 parsing is required)

 what concerns syntax, I have no problem with this.

 What bothers me immensely is the same what bothered me in the totally
 braindead
 Delphi implementation of the for in loop : the bunch of requirements you
 put on the iterator implementation: an interface with special status. You
 can't get more stupid and ugly than that.
Out of curiosity -- how would you implement it?
(Except the Oberon way -- by telling the programmer that he is
better off without this feature :-))

I have no particular like or dislike for the Delphi's enumerable implementation,
but it is quite similar to for-in iterators in most other compiled languages.

 Your initial proposal makes it even worse by adding more conditions to the
 interface, it would not even be an interface any more.
I am not sure what are you talking about. Interface is a list of methods.
My for-in proposal would add a new interface (with a single method)
which, if supported by enumerator, would allow user to write for-in-index loops.

 That is why I think you need a proper tuple value to solve this.
 it gives a more fundamental solution: the loop variable type equals the type
 returned by the iterator/enumerator. No messing with index (bad syntax) and
 even worse: special 'interfaces' and whatnot.
I agree that index keyword was perhaps not optimal choice.
New interface is needed anyway to preserve backwards compatibility
(and efficiency for the case when the key is not needed).
Do not slow down existing code.

 Pascal is a strongly typed language. So, if we absolutely must solve this:
 introduce a proper type. A tuple fits the job.
So does the record -- tuple is needed here only to deconstruct that
record in separate variables.

--
Alexander S. Klenin
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Michael Van Canneyt



On Mon, 28 Jan 2013, Alexander Klenin wrote:


On Mon, Jan 28, 2013 at 2:59 AM, Michael Van Canneyt
mich...@freepascal.org wrote:



On Mon, 28 Jan 2013, Alexander Klenin wrote:

I have a compromise suggestion:
Implement for-index extension with the syntax:
for (k, v) in a do
this syntax is forward-compatible with both tuples proposals,
is simple to do (basically, already done -- only a small change in
parsing is required)


what concerns syntax, I have no problem with this.

What bothers me immensely is the same what bothered me in the totally
braindead
Delphi implementation of the for in loop : the bunch of requirements you
put on the iterator implementation: an interface with special status. You
can't get more stupid and ugly than that.

Out of curiosity -- how would you implement it?


Define an iterator type/operator.

- No interface
- No 'specially named function' in the class. The iterator should be separate 
from the class.
Now they promoted 1 function with a special name to a special status: 
'GetEnumerator'

(I know this is how Python and so did it, but I'm not particularly fond of that 
either).


(Except the Oberon way -- by telling the programmer that he is
better off without this feature :-))


I am still not convinced that language support for iterators are needed.

You may be bothered by the various loop methods in the rtl/fcl.
But I am not in the least bothered by it.


I have no particular like or dislike for the Delphi's enumerable implementation,
but it is quite similar to for-in iterators in most other compiled languages.


Well, I do not like to give special status to certain functions or interfaces.
All identifiers should be equal for the law :-)

I was horribly disappointed when they introduced that.


Your initial proposal makes it even worse by adding more conditions to the
interface, it would not even be an interface any more.

I am not sure what are you talking about. Interface is a list of methods.
My for-in proposal would add a new interface (with a single method)
which, if supported by enumerator, would allow user to write for-in-index loops.


I know. I just do not like the approach. 
Probably because I don't particularly like interfaces themselves.



That is why I think you need a proper tuple value to solve this.
it gives a more fundamental solution: the loop variable type equals the type
returned by the iterator/enumerator. No messing with index (bad syntax) and
even worse: special 'interfaces' and whatnot.

I agree that index keyword was perhaps not optimal choice.


Quick, we should call the newspaper, we agree on something ;-)


New interface is needed anyway to preserve backwards compatibility
(and efficiency for the case when the key is not needed).
Do not slow down existing code.


Yes.


Pascal is a strongly typed language. So, if we absolutely must solve this:
introduce a proper type. A tuple fits the job.

So does the record -- tuple is needed here only to deconstruct that
record in separate variables.


True.

Which begs the question why you didn't use a record to begin with.

I still do not see why the enumerator could not simply return a record
record
  key : tkey;
  value : tactualtype
end;

for r in myclass do
  begin
  Writeln(r.key);
  With r.value do
  end.

to recapitulate:

The construction with interface/index is really very ugly in my opinion, 
and I would very much regret it if it became part of Object Pascal.


I can understand the need to have simpler variables. 
So a tuple and/or a record deconstructor comes in naturally.


I think a tuple as a type construct may have value in itself.
and as such would prefer to see it as a 'first class citizen' of Object Pascal,
just as it is in e.g. Python, and to a lesser degree, other languages.
The exact details are for me less important.

A small word:

Like most people here I think Pascal is an elegant language, easy to read 
and whatnot. It was meant/designed as such, and Wirth did a good job.


I am very passionate about that, I'm sure you noticed. I may use 
exuberant language, and probably bad humor, in my efforts to defend it.


Despite that, please do not make the mistake of thinking that I would stop 
features just because I do not like them. That said, I will zealously defend 
possible alternatives that I think add to the elegance and readability of Pascal.

(as witnessed by the discussions this weekend...)

Borland did a world of good for (Object) Pascal, up to Delphi 7.
After that, it went seriously downhill in my opinion; 
Adding randomly features without clear direction or regard for the

intent and philosophy of the Pascal language - or so it seems to me.
Like a ship at the mercy of the waves...

I would be very sorry to see that happening to Free Pascal.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Hans-Peter Diettrich
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.


Alexander Klenin schrieb:

On Sun, Jan 27, 2013 at 12:35 PM, Hans-Peter Diettrich
drdiettri...@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.


My point is the artificial overhead, introduced in above example. The 
code may *look* elegant, but in fact is a resource hog.




Also note that in my version of proposal, nested tuples are impossible.


I consider this an inacceptable restriction. Records can contain other 
records.





  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.


Watching tuples (records) is not enough for debugging such complex 
assignments.



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.


Indeed it would be nice to have more specialized watches for e.g. 
records or classes. When e.g. a class (TWinControl...) contains records 
or lists, these elements may hide following and more interesting members 
of derived classes in the output.



* 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.


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.



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.



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, but not of Double. What 
result do you expect from an index array of (-5.2, 3.7, 9.5)? Pascal 
requires explicit rounding (round, trunc, floor...) of real values to 
integers, for good reason. Tuple deconstructors can use only one of 
these functions for *every* tuple, so that the choice may be good for 
one use, but inappropriate in other situations, regardless of the 
choosen method.


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.




When a record type is modified, during development, all *compatible* tuples
and tuple types must be updated accordingly.

True.


This was my point.


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.


But subroutine signatures 

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

2013-01-27 Thread Hans-Peter Diettrich

Sven Barth schrieb:


The lack of element names results in bloated code and runtime overhead.
See below.



I don't see why it should result in bloated code and runtime overhead.


--- See below ;-)



  (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.


And here you are wrong. We have an assignment node with a tuple node on 
the left and a tuple node on the right. So the compiler can insert 
direct assignments between the corresponding elements on the left and 
right maybe with the need to insert a few temp vars to resolve cases 
like the above.


Are you sure that the compiler will detect all (possible) side effects, 
so that an optimization is always *safe*?


Finally somebody (you?) has to implement all the new features, and stand 
for its correctness.




  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 :-(




You can also write cryptic code without tuples. Also why should 
debugging become impossible? It's just a matter of adding the correct 
debug information.


With explicit assignments you can check every single statement, 
eventually step into embedded functions. A tuple assignment is a single 
statement, no chance to find out what happens in detail.


DoDi

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Alexander Klenin
On Mon, Jan 28, 2013 at 4:19 AM, Michael Van Canneyt
mich...@freepascal.org wrote:
 Define an iterator type/operator.

 - No interface
 - No 'specially named function' in the class. The iterator should be
 separate from the class.
 Now they promoted 1 function with a special name to a special status:
 'GetEnumerator'

Ah, you mean that FPC's operator Enumerator is better?
I agree, but the difference is not too great.

 All identifiers should be equal for the law :-)
I know only two languages with such extreme disdain for reserved words:
Forth and, to a lesser extent, Lisp.
For example, in Forth, a comment (!) is not a built-in construct,
but a word (Forth's analog of procedure) defined in standard library.


 Which begs the question why you didn't use a record to begin with.

 I still do not see why the enumerator could not simply return a record
 record
   key : tkey;
   value : tactualtype
 end;

 for r in myclass do
   begin
   Writeln(r.key);
   With r.value do
   end.

the point of my tuples proposal is to do exactly that, with only a
single change --
allow to *also* write loop as
for key, value in myclass do
   begin
   Writeln(key);
   with value do
   end;

while keeping enumerator the same.

 Borland did a world of good for (Object) Pascal, up to Delphi 7.
 After that, it went seriously downhill in my opinion; Adding randomly
 features without clear direction or regard for the
 intent and philosophy of the Pascal language - or so it seems to me.
 Like a ship at the mercy of the waves...
I would rephrase slightly -- the features they added are, in
principle, good ones.
However, they hastily (and randomly?) copied them from other languages without a
proper adaptation.
Take, for example, recently added to FPC array constructors:
TIntegerDynArray.Create(1, 2, 3) is much too noisy, and inconsistent
with other syntax
(it resembles a standard constructor, but takes variable-length
argument list, which is impossible for standard constructors).
So I would much prefer
TIntegerDynArray(1, 2, 3), TIntegerDynArray([1, 2, 3]), or maybe even
just [1, 2, 3] if appropriate automatic conversions are defined.

--
Alexander S. Klenin
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Michael Van Canneyt



On Mon, 28 Jan 2013, Alexander Klenin wrote:


On Mon, Jan 28, 2013 at 4:19 AM, Michael Van Canneyt
mich...@freepascal.org wrote:

Define an iterator type/operator.

- No interface
- No 'specially named function' in the class. The iterator should be
separate from the class.
Now they promoted 1 function with a special name to a special status:
'GetEnumerator'


Ah, you mean that FPC's operator Enumerator is better?
I agree, but the difference is not too great.


It never is. It is all in details.




All identifiers should be equal for the law :-)

I know only two languages with such extreme disdain for reserved words:
Forth and, to a lesser extent, Lisp.
For example, in Forth, a comment (!) is not a built-in construct,
but a word (Forth's analog of procedure) defined in standard library.



Which begs the question why you didn't use a record to begin with.

I still do not see why the enumerator could not simply return a record
record
  key : tkey;
  value : tactualtype
end;

for r in myclass do
  begin
  Writeln(r.key);
  With r.value do
  end.


the point of my tuples proposal is to do exactly that, with only a
single change --
allow to *also* write loop as
for key, value in myclass do
  begin
  Writeln(key);
  with value do
  end;

while keeping enumerator the same.


regarding syntax, we agree.




Borland did a world of good for (Object) Pascal, up to Delphi 7.
After that, it went seriously downhill in my opinion; Adding randomly
features without clear direction or regard for the
intent and philosophy of the Pascal language - or so it seems to me.
Like a ship at the mercy of the waves...

I would rephrase slightly -- the features they added are, in
principle, good ones.
However, they hastily (and randomly?) copied them from other languages without a
proper adaptation.


Yes. That is what I meant.

I have no objections to the features themselves.
Just the way the were introduced, is, to my taste, totally 
disregarding Pascal philosophy.


And I regret that heavily.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-27 Thread Alexander Klenin
On Mon, Jan 28, 2013 at 4:46 AM, Hans-Peter Diettrich
drdiettri...@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 

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

2013-01-27 Thread Sven Barth

On 27.01.2013 20:16, Alexander Klenin wrote:

Borland did a world of good for (Object) Pascal, up to Delphi 7.
After that, it went seriously downhill in my opinion; Adding randomly
features without clear direction or regard for the
intent and philosophy of the Pascal language - or so it seems to me.
Like a ship at the mercy of the waves...

I would rephrase slightly -- the features they added are, in
principle, good ones.
However, they hastily (and randomly?) copied them from other languages without a
proper adaptation.
Take, for example, recently added to FPC array constructors:
TIntegerDynArray.Create(1, 2, 3) is much too noisy, and inconsistent
with other syntax
(it resembles a standard constructor, but takes variable-length
argument list, which is impossible for standard constructors).
So I would much prefer
TIntegerDynArray(1, 2, 3), TIntegerDynArray([1, 2, 3]), or maybe even
just [1, 2, 3] if appropriate automatic conversions are defined.


Here we - again - agree. I would have also preferred the latter one (as 
this could be used for non named array types as well...). I already 
thought about simply implementing it...


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Sven Barth

Hello together!

Based on the results of the for-in-index thread I've decided to come 
up with a draft for the Tuple type which is thought by many people to be 
a better alternative to for-in-index.


Please note the following points:
* This is not the final specification for Tuples and thus open to 
discussion (there are still some issues with this draft that need to be 
solved)
* I won't implement this feature myself (at least not in the near 
future) as I have other topics on my list (most importantly generics 
once type helpers are commited), so Alexander is free to give the task 
for implementation to his student.


Regards,
Sven

The draft:

* Description

What are tuples? Tuples are an accumulation of values of different or 
same type where the order matters. Sounds familiar? They are in this 
regard similar to records, but it's only the order of an element that 
matters, not its name. So what does make them special? Unlike records 
you can only query or set all the elements of a tuple at once. They 
basically behave like multiple assignments. In effect they allow you to 
return e.g. a multivalued result value without resorting to the naming 
of record fields (you'll still need to declare a tuple type) or the need 
for out parameters. This in turn allows you to use them for example in 
for-in loops.


* Declaration:

The declaration of a tuple type is build up as follows (pseudo grammar):

TUPLETYPE ::= [packed] tuple of (TUPLEELEMENTS)
TUPLEELEMENTS ::= TYPENAME, TYPENAME [, TYPENAME]*

This shows that a tuple must at least consist of two elements. While in 
theory a one element tuple would be possible the question is on the one 
hand why you'd use a tuple type at all and on the other hand this avoids 
potential problems for the compiler especially if the tuple type is used 
as the left side of an assignment (the compiler currently allows e.g. 
(Writeln('Foobar')) as a statement).
Note: If single element tuples are desired they need to be made 
assignment compatible with corresponding scalar values.


The memory layout of tuples is also similar to records in that the 
elements are aligned according to the current alignment settings. This 
alignment is not used if the packed modifier is used.


Like sets tuples can be declared anonymously:

=== code begin ===

var
  t: tuple of (Integer, String);

=== code end ===

Tuples can not be declared as generic, but they can be declared inside 
generics with generic parameters as one or more element types.


* Assignment compatibility:

Two different tuples A and B are considered assignment compatible if and 
only if they contain the same number of elements and each element Ai is 
assignment compatible to Bi (please note that this might contain 
precision/data loss).


E.g.:

=== code begin ===

var
  t1, t2: tuple of (Integer, Single, TObject, String);
  t3: tuple of (Byte, Double, TStrings, ShortString);
  t4: tuple of (Integer, Single);
  t5: tuple of (Single, Double, TObject, String);
  t6: tuple of (TObject, Integer, String, Single);
begin
  t1 := t2; // ok
  t1 := t3; // ok (with precision loss in second element)
  t3 := t1; // not ok, because TObject is not a subclass of TStrings
  t1 := t4; // not ok, because the count of elements is not equal
  t5 := t1; // ok, element 1 will be converted to a Single
  t6 := t1; // not ok, order of elements is not equal
end;
=== code end ===

* Usage:

Tuples can be used by assigning either another compatible tuple (see 
above) to it or by constructing or deconstructing a tuple value.


A constructor looks as follows:

TUPLECONSTRUCTOR ::= (RVALUE, RVALUE [,RVALUE]*)

While a deconstructor looks as follows:

TUPLEDECONSTRUCTOR ::= (LVALUE, LVALUE, [,LVALUE]*)

In both cases the amount of elements must be equal to the amount of 
elements the tuple is assigned to/from (and also the types must be 
compatible).


Examples:

=== code begin ===
var
  t1: tuple of (Integer, String, Single);
  t2: tuple of (TObject, Integer);
  s: String;
  i: LongInt;
  d: Double;
  o: TObject;
  sl: TStringList;
begin
  // constructors
  t1 := (42, 'Hello World', 3.14);
  t1 := (i, s, d); // with precision loss in third element upon assignment
  t2 := (TObject.Create, 42);
  t2 := (Nil, 0);
  t2 := (TStringList.Create, Random(42));
  //t2 := (0, False); // not ok, because elements are not compatible
  //t2 := (Nil, 0, ''); // not ok, because the count is different
  // deconstrucors
  (i, s, d) := t1;
  //(42, s, d) := t1; // not valid, because 42 can not be assigned to!
  //(i, s) := t1; // not valid, because the count of elements differs
  (o, i) := t2;
  (o, sl.Capacity) := t2; // properties can be assigned to as well
end;

=== code end ===

The usage of constructors and destructors also allows a realisation of 
group assignment:


=== code begin ===

var
  a, b, e: Integer;
  c, d: String;
begin
  a := 42;
  c := 'Hello World';
  (b, d) := (a, c);
  a := 21;
  b := 84;
  (a, b) := (b, a); // the compiler needs to ensure the correct 

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

2013-01-26 Thread Marco van de Voort
In our previous episode, Sven Barth said:
 up with a draft for the Tuple type which is thought by many people to be 
 a better alternative to for-in-index.
 
 Please note the following points:
 * This is not the final specification for Tuples and thus open to 
 discussion (there are still some issues with this draft that need to be 
 solved)
 * I won't implement this feature myself (at least not in the near 
 future) as I have other topics on my list (most importantly generics 
 once type helpers are commited), so Alexander is free to give the task 
 for implementation to his student.

In a quick read, I cannot see any limitations to the type used for
a tuple-element except that it behaves like file of...

So that would mean a record type (or other non variant compatible type)
would qualify?
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Sven Barth

On 26.01.2013 18:52, Marco van de Voort wrote:

In our previous episode, Sven Barth said:

up with a draft for the Tuple type which is thought by many people to be
a better alternative to for-in-index.

Please note the following points:
* This is not the final specification for Tuples and thus open to
discussion (there are still some issues with this draft that need to be
solved)
* I won't implement this feature myself (at least not in the near
future) as I have other topics on my list (most importantly generics
once type helpers are commited), so Alexander is free to give the task
for implementation to his student.


In a quick read, I cannot see any limitations to the type used for
a tuple-element except that it behaves like file of...

So that would mean a record type (or other non variant compatible type)
would qualify?


Whether there should be restrictions of types could be added to the open 
issues as I'd want to have at least equality operators working for 
tuples and thus we need to think about something for records... (as a 
solution one could require that a = operator for records must be in scope)


But without that problem in mind I had wanted to allow every type for 
tuple elements (even tuples).


Out of curiosity: Do you see this positive or negative?

Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Marco van de Voort
In our previous episode, Sven Barth said:
  In a quick read, I cannot see any limitations to the type used for
  a tuple-element except that it behaves like file of...
 
  So that would mean a record type (or other non variant compatible type)
  would qualify?
 
 Whether there should be restrictions of types could be added to the open 
 issues as I'd want to have at least equality operators working for 
 tuples and thus we need to think about something for records... (as a 
 solution one could require that a = operator for records must be in scope)
 
 But without that problem in mind I had wanted to allow every type for 
 tuple elements (even tuples).
 
 Out of curiosity: Do you see this positive or negative?

To be frank, I'm not interested in the whole shebang. It reeks too much like
first wanting an extension, and then thinking of one.

But, like you, when it is being done, it should be done decent, and IMHO
using array of variant (or tvarrec) as implementation vehicle is limiting
the feature too much. Either good, or not.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Sven Barth

On 26.01.2013 19:20, Marco van de Voort wrote:

In our previous episode, Sven Barth said:

In a quick read, I cannot see any limitations to the type used for
a tuple-element except that it behaves like file of...

So that would mean a record type (or other non variant compatible type)
would qualify?


Whether there should be restrictions of types could be added to the open
issues as I'd want to have at least equality operators working for
tuples and thus we need to think about something for records... (as a
solution one could require that a = operator for records must be in scope)

But without that problem in mind I had wanted to allow every type for
tuple elements (even tuples).

Out of curiosity: Do you see this positive or negative?


To be frank, I'm not interested in the whole shebang. It reeks too much like
first wanting an extension, and then thinking of one.

But, like you, when it is being done, it should be done decent, and IMHO
using array of variant (or tvarrec) as implementation vehicle is limiting
the feature too much. Either good, or not.


Ah, this is how you meant it.

As I've written in the beginning of the draft I think of tuples more 
like a simplified record type (in terms of compiler implementation, etc).


Regards,
Sven

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Michael Van Canneyt



On Sat, 26 Jan 2013, Sven Barth wrote:


Hello together!

Based on the results of the for-in-index thread I've decided to come up 
with a draft for the Tuple type which is thought by many people to be a 
better alternative to for-in-index.


Please note the following points:
* This is not the final specification for Tuples and thus open to discussion 
(there are still some issues with this draft that need to be solved)
* I won't implement this feature myself (at least not in the near future) as 
I have other topics on my list (most importantly generics once type helpers 
are commited), so Alexander is free to give the task for implementation to 
his student.


After a first read, looks OK. You seem to have thought of everything that needs 
to be described, except maybe extraction of a single element:


b : tuple of (integer, integer);
a : integer;

begin
  b:=(1,2);
  a:=b[0]; // a = 1 after this.
end;

In this sense, it seems more like an array of const than as a record.

I would not do the extensions. The tuple is simply a logical, immutable 
grouping of values.
I would also not allow operators other than :=  and =, because in expressions,
when encountering a (, it is not clear what is meant.

Stick to what can be considered well-defined.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Mark Morgan Lloyd

Sven Barth wrote:

Hello together!

Based on the results of the for-in-index thread I've decided to come 
up with a draft for the Tuple type which is thought by many people to be 
a better alternative to for-in-index.


Nice, but I've got reservations about making tuples compatible with 
dynamic arrays (or at least, any more compatible than a dynamic array is 
with a normal array).


I also note Alexander's earlier

   ZEROES: array [1..10] of Integer = (0, 0, ..., 0);
 ...
 (x, y, z) := Tuple(ZEROES);

which I'm afraid I really don't like since that sort of thing is too 
easily misinterpreted as making the language indeterminate. I'd vote for 
having implicit compatibility between a single element and a tuple i.e. 
something like


 (x, y, z) := Tuple(0);

provided that x, y and z are all the same type. Granted that the same 
effect can be had by overlaying the assignment operator but this would 
save having to use per-element assignment or an intermediate array.


--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Sven Barth

On 26.01.2013 20:13, Mark Morgan Lloyd wrote:

Sven Barth wrote:

Hello together!

Based on the results of the for-in-index thread I've decided to come
up with a draft for the Tuple type which is thought by many people to
be a better alternative to for-in-index.


Nice, but I've got reservations about making tuples compatible with
dynamic arrays (or at least, any more compatible than a dynamic array is
with a normal array).


Which is why I added it under extensions.



I also note Alexander's earlier

ZEROES: array [1..10] of Integer = (0, 0, ..., 0);
  ...
  (x, y, z) := Tuple(ZEROES);

which I'm afraid I really don't like since that sort of thing is too
easily misinterpreted as making the language indeterminate.


Which is in turn why I required that the count of elements is the same...


I'd vote for
having implicit compatibility between a single element and a tuple i.e.
something like

  (x, y, z) := Tuple(0);

provided that x, y and z are all the same type. Granted that the same
effect can be had by overlaying the assignment operator but this would
save having to use per-element assignment or an intermediate array.



I don't know... this is again the the right side is evaluated without 
knowing the left side problem. Thus it is not known what types 
Tuple(0) should return. (Note: this problem does not apply to group 
assignments as proposed, because if necessary every value could just be 
copied to the stack and then retrieved (of course the compiler will 
optimize here...)


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Sven Barth

On 26.01.2013 20:14, Michael Van Canneyt wrote:



On Sat, 26 Jan 2013, Sven Barth wrote:


Hello together!

Based on the results of the for-in-index thread I've decided to come
up with a draft for the Tuple type which is thought by many people to
be a better alternative to for-in-index.

Please note the following points:
* This is not the final specification for Tuples and thus open to
discussion (there are still some issues with this draft that need to
be solved)
* I won't implement this feature myself (at least not in the near
future) as I have other topics on my list (most importantly generics
once type helpers are commited), so Alexander is free to give the task
for implementation to his student.


After a first read, looks OK. You seem to have thought of everything
that needs to be described, except maybe extraction of a single element:

b : tuple of (integer, integer);
a : integer;

begin
   b:=(1,2);
   a:=b[0]; // a = 1 after this.
end;

In this sense, it seems more like an array of const than as a record.


The question is whether we really need it. But if you think it's 
worthwhile then one can add it. But then we might also need support for 
Length and maybe also (just for the sake of completeness) Low and 
High. And then there's also the question whether to start at 0 or 1...




I would not do the extensions. The tuple is simply a logical, immutable
grouping of values.


That's why I proposed them as extensions. I'm myself not very sure in 
allowing them or not, but I added them for Alexander's sake ;)



I would also not allow operators other than :=  and =, because in
expressions,
when encountering a (, it is not clear what is meant.


Here are two possiblities:
* allow operator overloads only for named tuples, which would mean that 
only t3 := t1 + t2 would be supported
* allow operator overloads also for anonymous tuples, which would mean 
that (like I wrote in open issues) (d1, d2, d3, d4) := (d1, d2, d3, d4) 
+ (1.0, 2.0, 3.0, 4.0) would be supported


The former is also the case for other types (e.g. sets, though there 
only a few operators (like **) can be overloaded), so this would be 
consistent...


Regards,
Sven

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Sven Barth

On 26.01.2013 20:36, Sven Barth wrote:

After a first read, looks OK. You seem to have thought of everything
that needs to be described, except maybe extraction of a single element:

b : tuple of (integer, integer);
a : integer;

begin
   b:=(1,2);
   a:=b[0]; // a = 1 after this.
end;

In this sense, it seems more like an array of const than as a record.




And I just got the following idea:

=== example begin ===

var
  t1: tuple of (Integer, Integer, Integer, Integer);
  t2: tuple of (Integer, Integer);
begin
  t1 := (4, 3, 2, 1);
  t2 := tl[2..3]; // with 1 based access t2 will be (3, 2);
  t1[3..4] := (5, 6); // t1 will now be (4, 3, 5, 6)
end;

=== example end ===

Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Mark Morgan Lloyd

Sven Barth wrote:


I'd vote for
having implicit compatibility between a single element and a tuple i.e.
something like

  (x, y, z) := Tuple(0);

provided that x, y and z are all the same type. Granted that the same
effect can be had by overlaying the assignment operator but this would
save having to use per-element assignment or an intermediate array.



I don't know... this is again the the right side is evaluated without 
knowing the left side problem. Thus it is not known what types 
Tuple(0) should return. (Note: this problem does not apply to group 
assignments as proposed, because if necessary every value could just be 
copied to the stack and then retrieved (of course the compiler will 
optimize here...)


In that case how about

type TInteger2Tuple= tuple of (integer, integer);

var  i2: TInteger2Tuple;

begin
  i2 := TIntegerTuple(0);

for the very specific case where the tuple on the LHS is only allowed 
elements of a single type (or at the very least must be 
assignment-compatible with each other) and there is only a single 
element on the RHS.


Since under normal circumstances a tuple contains more than one element, 
this couldn't be confused with a cast.


--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Mark Morgan Lloyd

Michael Van Canneyt wrote:

On Sat, 26 Jan 2013, Sven Barth wrote:


Hello together!

Based on the results of the for-in-index thread I've decided to come 
up with a draft for the Tuple type which is thought by many people to 
be a better alternative to for-in-index.


Please note the following points:
* This is not the final specification for Tuples and thus open to 
discussion (there are still some issues with this draft that need to 
be solved)
* I won't implement this feature myself (at least not in the near 
future) as I have other topics on my list (most importantly generics 
once type helpers are commited), so Alexander is free to give the task 
for implementation to his student.


After a first read, looks OK. You seem to have thought of everything 
that needs to be described, except maybe extraction of a single element:


b : tuple of (integer, integer);
a : integer;

begin
  b:=(1,2);
  a:=b[0]; // a = 1 after this.
end;


Iff a tuple contains elements of the same type and if tuples with this 
restriction are compatible with arrays, wouldn't this behaviour be implicit?


--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Mark Morgan Lloyd

Alexander Klenin wrote:


2) The most important differentiating features of my proposal are:

2.1) Tuples are always temporary and anonymous. You can not store a
tuple, define tuple type, of variable of tuple type.
  So tuples are 100% static, compile-time feature -- no change to
RTTI, variants etc.


If you can't define a tuple type then you can't check that it's 
assignment-compatible with e.g. an array.



2.2) Tuples construction: after some thinking, I propose to define a
plain comma as an operator creating a tuple.


I must say that I prefer the idea of any collection being in some form 
of brackets. I'm tempted to say any language extension being in 
bracket-like entities, even if that's paired keywords.



  This way, any comma-separated list is considered a tuple, and
parenthesis may be used simply to control priority,
  since priority of comma is lower than all other operators. I will
demonstrate below how the compatibility with existing features is
still preserved.

2.2.1) Tuples are *flattening*, so (1, 2, (3, 4)) is a tuple of 4
elements, not of 3 elements, last being tuple.


I've got a bad feeling about that. Apart from anything else I think it 
implies that (pseudocode)


(TPoint, TColor) := (TColor, TPoint);

would be valid.


Single-value tuples are
useless, so Tuple(1) is either a no-op or error.


Except that a variant of that could be used to expand an element to a 
tuple. Or provided that tuples *did* *not* flatten it could expand a 
tuple to a tuple-of-tuples.


type TPoint= tuple of Double;
 TRect= tuple of TPoint;

var  rect: TRect;

begin
  rect := TRect(TPoint(100.0));

OK, so that's a zero-size rectangle but I'm trying to demonstrate 
potential syntax rather than do anything useful.


--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Alexander Klenin
On Sun, Jan 27, 2013 at 8:40 AM, Mark Morgan Lloyd
markmll.fpc-de...@telemetry.co.uk wrote:
 If you can't define a tuple type then you can't check that it's
 assignment-compatible with e.g. an array.
I do not see a link here.

 2.2) Tuples construction: after some thinking, I propose to define a
 plain comma as an operator creating a tuple.

 I must say that I prefer the idea of any collection being in some form of
 brackets. I'm tempted to say any language extension being in bracket-like
 entities, even if that's paired keywords.
Nothing stops you from adding extra brackets, if you like them.
However, I think that in all cases:
a, b := b, a;
for v, k in a do
DrawLine(Tuple(r), clRed);
Nothin useful is gained by abbing extra pair of brackets.
Also, comma is always a tuple removes grammar ambiguity --
there is no need to look ahead after the opening bracket.

 2.2.1) Tuples are *flattening*, so (1, 2, (3, 4)) is a tuple of 4
 elements, not of 3 elements, last being tuple.
 I've got a bad feeling about that. Apart from anything else I think it
 implies that (pseudocode)

 (TPoint, TColor) := (TColor, TPoint);

 would be valid.

No, you'll have to write
Tuple(APoint), AColor := AColor, Tuple(APoint);

 Single-value tuples are
 useless, so Tuple(1) is either a no-op or error.

 Except that a variant of that could be used to expand an element to a tuple.
As Sven pointed out, the main problem with that is that expression type now
suddenly depends on context, which is quite a rare feature in
programming languages,
and is probably much bugger change to Pascal than this whole tuple business.
OTOH, define Tuple(x, 5) to mean (x, x, x, x, x) is quite possible,
although less convenient:

x, y, z := Tuple(0, 3);
arr := Tuple(x, Length(arr));

--
Alexander S. Klenin
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Alexander Klenin
On Sun, Jan 27, 2013 at 12:11 PM, Alexander Klenin kle...@gmail.com wrote:
 Nothin useful is gained by abbing extra pair of brackets.
Sorry, I mean Nothing useful is gained by adding ...

--
Alexander S. Klenin
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


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

2013-01-26 Thread Hans-Peter Diettrich

Sven Barth schrieb:


* Description

What are tuples? Tuples are an accumulation of values of different or 
same type where the order matters. Sounds familiar? They are in this 
regard similar to records, but it's only the order of an element that 
matters, not its name. So what does make them special? Unlike records 
you can only query or set all the elements of a tuple at once. They 
basically behave like multiple assignments. In effect they allow you to 
return e.g. a multivalued result value without resorting to the naming 
of record fields (you'll still need to declare a tuple type) or the need 
for out parameters. This in turn allows you to use them for example in 
for-in loops.


The lack of element names results in bloated code and runtime overhead. 
See below.



* Declaration:

[...]

The usage of constructors and destructors also allows a realisation of 
group assignment:


=== code begin ===

var
  a, b, e: Integer;
  c, d: String;
begin
  a := 42;
  c := 'Hello World';
  (b, d) := (a, c);
  a := 21;
  b := 84;


  (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...).



  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 :-(


[...]

* 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.


When a record type is modified, during development, all *compatible* 
tuples and tuple types must be updated accordingly.



* Possible uses

- use for group assignments which can make the code more readable

... or unreadable (see above).

- 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.


- 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. 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?




* Implementation notes

Tuples need to pay attention to managed types (strings, interfaces, 
etc.). Thus an Init RTTI will be required (which needs to be handled by 
fpc_initalize/fpc_finalize accordingly).
It might be worthwhile to add a new node type for tuple 
constructors/deconstructors (one node type should be sufficient) and 
handle them in assignment nodes accordingly.


I'd reuse the record type node for that purpose.



* Open issues

Should anonymous tuples (together with tuple constructors) be allowed to 
participate in operator search as well? This would on the one hand allow 
the following code, but on the other hand make operator lookup rules 
less clear (because of assignment compatibility rules):


=== code begin ===

type
  TDoubleVector = tuple of (Double, Double, Double, Double);

operator + (aLeft, aRight: TDoubleVector): TDoubleVector;
// implement by e.g. using SSE instructions

// somewhere else
begin
  (d1, d2, d3, d4) := (d1, d2, d3, d4) + (1.0, 2.0, 3.0, 4.0);
end;

=== code end ===


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.



Conclusion:

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.


Nonetheless the discussion revealed some possible improvements of record