comp.lang.ada
 help / color / mirror / Atom feed
* Mixing operators and dot notation
@ 2016-06-02 21:38 Alejandro R. Mosteo
  2016-06-02 21:42 ` Alejandro R. Mosteo
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Alejandro R. Mosteo @ 2016-06-02 21:38 UTC (permalink / raw)


Hello all,

I'm trying to abuse Ada syntax for nefarious purposes and have arrived 
at something that looks inconsistent to me, but I fail to see if it is 
expected behavior or a bug. This is a self-contained example which is below.

The gist is to have an operator that returns a class-wide type in order 
to use dot notation on it. The problem is in the last statement. Should 
it work just like the function version?:

procedure Cla is

    generic
    package Nested is
          type Object is tagged null record;
	 procedure Method (O : Object) is null;
    end Nested;

    package Nest is new Nested;

    function Op (X, Y : Integer) return Nest.Object'Class is
       pragma Unreferenced (X, Y);
    begin
       return Nest.Object'(null record);
    end Op;

    function "&" (X, Y : Integer) return Nest.Object'Class renames Op;

    N : Nest.Object'Class := Op (1, 2);
    M : Nest.Object'Class := 1 & 2; -- Both work

begin
    N.Method;
    M.Method; -- Of course both work

    Op (1, 2).Method;  --  Fine

    --  (1 & 2).Method;  --  Error: statement expected
end Cla;

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-02 21:38 Mixing operators and dot notation Alejandro R. Mosteo
@ 2016-06-02 21:42 ` Alejandro R. Mosteo
  2016-06-02 22:28 ` Robert A Duff
  2016-06-02 23:05 ` Jeffrey R. Carter
  2 siblings, 0 replies; 17+ messages in thread
From: Alejandro R. Mosteo @ 2016-06-02 21:42 UTC (permalink / raw)


Failed to say: tested with gnat gpl 2015 and 2016.

On 02/06/16 23:38, Alejandro R. Mosteo wrote:
> Hello all,
>
> I'm trying to abuse Ada syntax for nefarious purposes and have arrived
> at something that looks inconsistent to me, but I fail to see if it is
> expected behavior or a bug. This is a self-contained example which is
> below.
>
> The gist is to have an operator that returns a class-wide type in order
> to use dot notation on it. The problem is in the last statement. Should
> it work just like the function version?:
>
> procedure Cla is
>
>     generic
>     package Nested is
>           type Object is tagged null record;
>       procedure Method (O : Object) is null;
>     end Nested;
>
>     package Nest is new Nested;
>
>     function Op (X, Y : Integer) return Nest.Object'Class is
>        pragma Unreferenced (X, Y);
>     begin
>        return Nest.Object'(null record);
>     end Op;
>
>     function "&" (X, Y : Integer) return Nest.Object'Class renames Op;
>
>     N : Nest.Object'Class := Op (1, 2);
>     M : Nest.Object'Class := 1 & 2; -- Both work
>
> begin
>     N.Method;
>     M.Method; -- Of course both work
>
>     Op (1, 2).Method;  --  Fine
>
>     --  (1 & 2).Method;  --  Error: statement expected
> end Cla;

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-02 21:38 Mixing operators and dot notation Alejandro R. Mosteo
  2016-06-02 21:42 ` Alejandro R. Mosteo
@ 2016-06-02 22:28 ` Robert A Duff
  2016-06-02 23:26   ` Randy Brukardt
  2016-06-02 23:05 ` Jeffrey R. Carter
  2 siblings, 1 reply; 17+ messages in thread
From: Robert A Duff @ 2016-06-02 22:28 UTC (permalink / raw)


"Alejandro R. Mosteo" <alejandro@mosteo.com> writes:

> I'm trying to abuse Ada syntax for nefarious purposes and have arrived
                ^^^^^ Probably an apt description.  ;-)

> at something that looks inconsistent to me, but I fail to see if it is
                          ^^^^^^^^^^^^
Yes, the rules are inconsistent.

> expected behavior or a bug. This is a self-contained example which is
> below.

>    Op (1, 2).Method;  --  Fine
>
>    --  (1 & 2).Method;  --  Error: statement expected

That's syntactically illegal; take a look at the BNF.

But you can say:

   Nest.Object'Class'(1 & 2).Method;

Ada makes a syntactic distinction between 'name' and 'expression',
which I think is unwise.  ARG has been chipping away at it over
the years.  Anyway, nowadays, a qualified_expression is a name,
so if you have an expression you want to use as a name, you can
just qualify it.

- Bob

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-02 21:38 Mixing operators and dot notation Alejandro R. Mosteo
  2016-06-02 21:42 ` Alejandro R. Mosteo
  2016-06-02 22:28 ` Robert A Duff
@ 2016-06-02 23:05 ` Jeffrey R. Carter
  2 siblings, 0 replies; 17+ messages in thread
From: Jeffrey R. Carter @ 2016-06-02 23:05 UTC (permalink / raw)


On 06/02/2016 02:38 PM, Alejandro R. Mosteo wrote:
> 
>    --  (1 & 2).Method;  --  Error: statement expected

What do you get for

"&" (1, 2).Method;

?

-- 
Jeff Carter
"It has been my great privilege, many years ago,
whilst traveling through the mountains of Paraguay,
to find the Yack'Wee Indians drinking the juice of
the cacti."
The Old Fashioned Way
152


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-02 22:28 ` Robert A Duff
@ 2016-06-02 23:26   ` Randy Brukardt
  2016-06-03 11:09     ` Alejandro R. Mosteo
  0 siblings, 1 reply; 17+ messages in thread
From: Randy Brukardt @ 2016-06-02 23:26 UTC (permalink / raw)


"Robert A Duff" <bobduff@TheWorld.com> wrote in message 
news:wccshwvgr8n.fsf@TheWorld.com...
> "Alejandro R. Mosteo" <alejandro@mosteo.com> writes:
>
>> I'm trying to abuse Ada syntax for nefarious purposes and have arrived
>                ^^^^^ Probably an apt description.  ;-)
>
>> at something that looks inconsistent to me, but I fail to see if it is
>                          ^^^^^^^^^^^^
> Yes, the rules are inconsistent.
>
>> expected behavior or a bug. This is a self-contained example which is
>> below.
>
>>    Op (1, 2).Method;  --  Fine
>>
>>    --  (1 & 2).Method;  --  Error: statement expected
>
> That's syntactically illegal; take a look at the BNF.

> But you can say:
>
>   Nest.Object'Class'(1 & 2).Method;
>
> Ada makes a syntactic distinction between 'name' and 'expression',
> which I think is unwise.  ARG has been chipping away at it over
> the years.  Anyway, nowadays, a qualified_expression is a name,
> so if you have an expression you want to use as a name, you can
> just qualify it.

True (for Ada 2012), but it probably defeats the purpose to do that. (If you 
have to know the full expanded names of everything, there's little value to 
prefix notation in the first place.)

You also can write:

    "&" (1, 2).Method

which might defeat the purpose less. (Or not, not knowing the actual 
intent.)

Also to Bob's point, a type conversion always has been a name, so that:

   Nest.Object'Class(1 & 2).Method;

is syntactically legal in Ada 2005 as well, but it not resolve (the operand 
of a type conversion can't use the context in any way, so it depends on what 
& operators are visible as to whether this would work). This was the reason 
that we changed Ada 2012, since it is silly that type conversions would be 
allowed somewhere, but qualified expressions (which just confirm the type) 
would not be.

                            Randy.




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-02 23:26   ` Randy Brukardt
@ 2016-06-03 11:09     ` Alejandro R. Mosteo
  2016-06-03 12:19       ` Dmitry A. Kazakov
                         ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: Alejandro R. Mosteo @ 2016-06-03 11:09 UTC (permalink / raw)


On 03/06/16 01:26, Randy Brukardt wrote:
> "Robert A Duff" <bobduff@TheWorld.com> wrote in message
> news:wccshwvgr8n.fsf@TheWorld.com...
>> "Alejandro R. Mosteo" <alejandro@mosteo.com> writes:
>>
>>> I'm trying to abuse Ada syntax for nefarious purposes and have arrived
>>                 ^^^^^ Probably an apt description.  ;-)

Since currently I'm using Ada only as a hobby, I mostly try bizarre 
things ;-)

>>> at something that looks inconsistent to me, but I fail to see if it is
>>                           ^^^^^^^^^^^^
>> Yes, the rules are inconsistent.

Ouch.

>>
>>> expected behavior or a bug. This is a self-contained example which is
>>> below.
>>
>>>     Op (1, 2).Method;  --  Fine
>>>
>>>     --  (1 & 2).Method;  --  Error: statement expected
>>
>> That's syntactically illegal; take a look at the BNF.
>
>> But you can say:
>>
>>    Nest.Object'Class'(1 & 2).Method;
>>
>> Ada makes a syntactic distinction between 'name' and 'expression',
>> which I think is unwise.  ARG has been chipping away at it over
>> the years.  Anyway, nowadays, a qualified_expression is a name,
>> so if you have an expression you want to use as a name, you can
>> just qualify it.
>
> True (for Ada 2012), but it probably defeats the purpose to do that. (If you
> have to know the full expanded names of everything, there's little value to
> prefix notation in the first place.)
>
> You also can write:
>
>      "&" (1, 2).Method
>
> which might defeat the purpose less. (Or not, not knowing the actual
> intent.)

Both defeat the purpose. I explain it below.

> Also to Bob's point, a type conversion always has been a name, so that:
>
>     Nest.Object'Class(1 & 2).Method;
>
> is syntactically legal in Ada 2005 as well, but it not resolve (the operand
> of a type conversion can't use the context in any way, so it depends on what
> & operators are visible as to whether this would work). This was the reason
> that we changed Ada 2012, since it is silly that type conversions would be
> allowed somewhere, but qualified expressions (which just confirm the type)
> would not be.

Yep, I've done this too, but it's again not practical in my current pursuit.

To give you the essence. I'm back to trying to get a minimal ReactiveX 
(http://reactivex.io)-like thing working. The gist is that you can chain 
many transformation operations:

SourceType.Generate_Data
    .Op1 (...)
    ...
    .OpN (...)
    .Endpoint (Operate_With_Resulting_Transformed_Data);

As long as the ops receive and emit the same type, I can do it with 
generics. But those are in the minority. Since they receive one type and 
emit another, I'm trying to find the most elegant Ada solution that 
keeps compile-time type checking if possible, and straight code flow 
(this is where parentheses in the solutions above don't work, since they 
create "boxes within boxes").

I'm pursuing several approaches: one is to use a tagged type with all 
operations (which is the Java approach), and marshalling of arguments 
via generics (which java doesn't need by having in-place instatiations). 
That's not too bad but duplicates code, in the sense that for each 
operation you need too pieces: the operation and the marshalling, but at 
least the library user writes her code using only her own types, which I 
like:

SourceType.Generate_Data
    .Op1 (FromXtoY.Transformer
       (User_FuncX'Access)) -- User_FuncX returns Y
    .Op2 (FromYtoZ.Transformer
       (User_FuncY'Access)) -- User FuncY returns Z
    .Endpoint (Z_Type.As_Z (Function'Access));

Of course with proper shorter names it looks better. However, checks are 
performed at run time.

Another idea was to use "&" instead of dot notation,

Stream := SourceType.Generate_Data &
    Type1.Op1(...) &
    Type2.Op2(...) &
    Type4.Endpoint (...);

having all needed "&" in scope. This possibly requires more "use type" 
clauses and I haven't tested it yet but I think it should work and be 
neater, having a "&" taking different left and right types.

Another way I was trying was the hybrid one that doesn't work: Using dot 
notation while there are no type changes, and & to cast to the new type 
only when needed. (I needed it to work even without parentheses.)

The root of the problem is in that, to keep code natural (and 
compile-time checks) I want to keep the user unaware of class-wide 
wrappers, and that involves generics. Once you have generic instances, 
you lose dot notation for transforming operations (since you need to 
somehow glue two types together, and the new operations are no longer 
primitive). (On this path, I have an idea involving two instantiations 
for each type being used, but I'm trying to avoid that for now). (Also I 
had a neat approach using elaboration-time instantiations but I collided 
with accessibility checks since I didn't want everything to be at 
library level.)

Anyway, I will keep playing and probably come back for criticism/ideas. 
It's possible I'm missing other options, of course, which are welcome. I 
will post my experimental repository once/if something takes shape.

Álex.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-03 11:09     ` Alejandro R. Mosteo
@ 2016-06-03 12:19       ` Dmitry A. Kazakov
  2016-06-03 14:45       ` G.B.
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 17+ messages in thread
From: Dmitry A. Kazakov @ 2016-06-03 12:19 UTC (permalink / raw)


On 03/06/2016 13:09, Alejandro R. Mosteo wrote:
> Anyway, I will keep playing and probably come back for criticism/ideas.
> It's possible I'm missing other options, of course, which are welcome. I
> will post my experimental repository once/if something takes shape.

Yes, please keep us informed if you find an elegant solution. (I have 
this kind of problems [parallel hierarchies x MD] all the time)

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-03 11:09     ` Alejandro R. Mosteo
  2016-06-03 12:19       ` Dmitry A. Kazakov
@ 2016-06-03 14:45       ` G.B.
  2016-06-03 17:31       ` Shark8
  2016-06-06  8:10       ` Mixing operators and dot notation briot.emmanuel
  3 siblings, 0 replies; 17+ messages in thread
From: G.B. @ 2016-06-03 14:45 UTC (permalink / raw)


On 03.06.16 13:09, Alejandro R. Mosteo wrote:
>
> SourceType.Generate_Data
>     .Op1 (FromXtoY.Transformer
>        (User_FuncX'Access)) -- User_FuncX returns Y
>     .Op2 (FromYtoZ.Transformer
>        (User_FuncY'Access)) -- User FuncY returns Z
>     .Endpoint (Z_Type.As_Z (Function'Access));

Seeing the syntax all the time---just the syntax, the
flow construction principles may deserve their own mode
of expression---in Javascript and Swift, I can't say
that it always seems so lovable: no names! No stops.
No context. Where does it start?  Burdensome, obfuscating.

In fact, this becomes a stretched, vertical APL.

Must I really buy a savvy folding editor just to find
the beginning of the chain without scrolling and backwards
scanning, reverting syntactical development in my head?

ML did something by emplying "and" for multiple such
points all relating to one start (the fun's name);
later languages have improved that somewhat by repeating
the name (even though this is referring to definitions,
not chains of calls, just for the picture).

A dialect of Eiffel by the maker of the lout formatting
software (sorry, don't remember the name) has turned MI
Eiffel "functional", every call producing another object
(no state change in objects).

So, if parentheses are to be avoided, and chaining is
an important principle of software construction, should it
not deserve some syntax of its own that reflects the
clarity of Ada's?

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-03 11:09     ` Alejandro R. Mosteo
  2016-06-03 12:19       ` Dmitry A. Kazakov
  2016-06-03 14:45       ` G.B.
@ 2016-06-03 17:31       ` Shark8
  2016-06-03 20:41         ` Alejandro R. Mosteo
  2016-06-06  8:10       ` Mixing operators and dot notation briot.emmanuel
  3 siblings, 1 reply; 17+ messages in thread
From: Shark8 @ 2016-06-03 17:31 UTC (permalink / raw)


On Friday, June 3, 2016 at 5:09:23 AM UTC-6, Alejandro R. Mosteo wrote:
> To give you the essence. I'm back to trying to get a minimal ReactiveX 
> (http://reactivex.io)-like thing working. The gist is that you can chain 
> many transformation operations:
> 
> SourceType.Generate_Data
>     .Op1 (...)
>     ...
>     .OpN (...)
>     .Endpoint (Operate_With_Resulting_Transformed_Data);
> 
> As long as the ops receive and emit the same type, I can do it with 
> generics. But those are in the minority. Since they receive one type and 
> emit another, I'm trying to find the most elegant Ada solution that 
> keeps compile-time type checking if possible, and straight code flow 
> (this is where parentheses in the solutions above don't work, since they 
> create "boxes within boxes").

I'm doing something similar with Byron.

Also note that the "boxes within boxes" can be used to some advantage as you can make generics dependent on generics: this requires some up-front designing and discipline though... and really learning the generic system.

There is one possible solution for you that doesn't quite require such gymnastics:

Package Testing_Package is
    
    Type Type_Interface is Interface;
    Function Operation_1(Object : Type_Interface) return Type_Interface is abstract;
    -- However many base operations there are.
    
    Generic
	Type X is private;
	with Function Op_1( Data : X ) return X;
	-- with for appropriate operations.
    Package Make_Interfaced is
	
	Type Y is new Type_Interface with record
	    Data : X;
	end record;
	
	Function Create( Object : X ) return Y;
	overriding Function Operation_1(Object : Y) return Y;
	
	Function "+" (Object : X) return Y renames Create;
	Function "-" (Object : Y) return X;
    Private
	
	Function Operation_1(Object : Y) return Y is
	  ( Data => Op_1(Object.Data) );
	  
	Function Create( Object : X ) return Y is
	  ( Data => Object );
	
	Function "-" (Object : Y) return X is
	  ( Object.Data );
	
    End Make_Interfaced;
    
    
    Generic
	Type A(<>) is new Type_Interface with private;
	Type B(<>) is new Type_Interface with private;
	With Function Operation( Item_1 : A; Item_2 : B ) return A;
    Function Concat( Left : A; Right : B ) return Type_Interface'Class;
    
    Function Concat( Left : A; Right : B ) return Type_Interface'Class is
      ( Type_Interface'Class(Operation(Left,Right)) );
    
    
End Testing_Package;

> 
> I'm pursuing several approaches: one is to use a tagged type with all 
> operations (which is the Java approach), and marshalling of arguments 
> via generics (which java doesn't need by having in-place instatiations). 
> That's not too bad but duplicates code, in the sense that for each 
> operation you need too pieces: the operation and the marshalling, but at 
> least the library user writes her code using only her own types, which I 
> like:
> 
> SourceType.Generate_Data
>     .Op1 (FromXtoY.Transformer
>        (User_FuncX'Access)) -- User_FuncX returns Y
>     .Op2 (FromYtoZ.Transformer
>        (User_FuncY'Access)) -- User FuncY returns Z
>     .Endpoint (Z_Type.As_Z (Function'Access));
> 
> Of course with proper shorter names it looks better. However, checks are 
> performed at run time.
> 
> Another idea was to use "&" instead of dot notation,
> 
> Stream := SourceType.Generate_Data &
>     Type1.Op1(...) &
>     Type2.Op2(...) &
>     Type4.Endpoint (...);
> 
> having all needed "&" in scope. This possibly requires more "use type" 
> clauses and I haven't tested it yet but I think it should work and be 
> neater, having a "&" taking different left and right types.
> 
> Another way I was trying was the hybrid one that doesn't work: Using dot 
> notation while there are no type changes, and & to cast to the new type 
> only when needed. (I needed it to work even without parentheses.)
> 
> The root of the problem is in that, to keep code natural (and 
> compile-time checks) I want to keep the user unaware of class-wide 
> wrappers, and that involves generics. Once you have generic instances, 
> you lose dot notation for transforming operations (since you need to 
> somehow glue two types together, and the new operations are no longer 
> primitive). (On this path, I have an idea involving two instantiations 
> for each type being used, but I'm trying to avoid that for now). (Also I 
> had a neat approach using elaboration-time instantiations but I collided 
> with accessibility checks since I didn't want everything to be at 
> library level.)
> 
> Anyway, I will keep playing and probably come back for criticism/ideas. 
> It's possible I'm missing other options, of course, which are welcome. I 
> will post my experimental repository once/if something takes shape.
> 
> Álex.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-03 17:31       ` Shark8
@ 2016-06-03 20:41         ` Alejandro R. Mosteo
  2016-06-06  8:14           ` briot.emmanuel
  0 siblings, 1 reply; 17+ messages in thread
From: Alejandro R. Mosteo @ 2016-06-03 20:41 UTC (permalink / raw)


Thank you for the detailed example. In fact I was doing something quite 
similar but temporarily went away of it because of the inability to use 
dot notation. I'm going to try again with operator "&".

My solution used a base generic as formal for all subsequent formals, 
and it was the first time I saw the need for that, so it was quite engaging.

Álex.

On 03/06/16 19:31, Shark8 wrote:
> On Friday, June 3, 2016 at 5:09:23 AM UTC-6, Alejandro R. Mosteo wrote:
>> To give you the essence. I'm back to trying to get a minimal ReactiveX
>> (http://reactivex.io)-like thing working. The gist is that you can chain
>> many transformation operations:
>>
>> SourceType.Generate_Data
>>      .Op1 (...)
>>      ...
>>      .OpN (...)
>>      .Endpoint (Operate_With_Resulting_Transformed_Data);
>>
>> As long as the ops receive and emit the same type, I can do it with
>> generics. But those are in the minority. Since they receive one type and
>> emit another, I'm trying to find the most elegant Ada solution that
>> keeps compile-time type checking if possible, and straight code flow
>> (this is where parentheses in the solutions above don't work, since they
>> create "boxes within boxes").
>
> I'm doing something similar with Byron.
>
> Also note that the "boxes within boxes" can be used to some advantage as you can make generics dependent on generics: this requires some up-front designing and discipline though... and really learning the generic system.
>
> There is one possible solution for you that doesn't quite require such gymnastics:
>
> Package Testing_Package is
>
>      Type Type_Interface is Interface;
>      Function Operation_1(Object : Type_Interface) return Type_Interface is abstract;
>      -- However many base operations there are.
>
>      Generic
> 	Type X is private;
> 	with Function Op_1( Data : X ) return X;
> 	-- with for appropriate operations.
>      Package Make_Interfaced is
> 	
> 	Type Y is new Type_Interface with record
> 	    Data : X;
> 	end record;
> 	
> 	Function Create( Object : X ) return Y;
> 	overriding Function Operation_1(Object : Y) return Y;
> 	
> 	Function "+" (Object : X) return Y renames Create;
> 	Function "-" (Object : Y) return X;
>      Private
> 	
> 	Function Operation_1(Object : Y) return Y is
> 	  ( Data => Op_1(Object.Data) );
> 	
> 	Function Create( Object : X ) return Y is
> 	  ( Data => Object );
> 	
> 	Function "-" (Object : Y) return X is
> 	  ( Object.Data );
> 	
>      End Make_Interfaced;
>
>
>      Generic
> 	Type A(<>) is new Type_Interface with private;
> 	Type B(<>) is new Type_Interface with private;
> 	With Function Operation( Item_1 : A; Item_2 : B ) return A;
>      Function Concat( Left : A; Right : B ) return Type_Interface'Class;
>
>      Function Concat( Left : A; Right : B ) return Type_Interface'Class is
>        ( Type_Interface'Class(Operation(Left,Right)) );
>
>
> End Testing_Package;
>
>>
>> I'm pursuing several approaches: one is to use a tagged type with all
>> operations (which is the Java approach), and marshalling of arguments
>> via generics (which java doesn't need by having in-place instatiations).
>> That's not too bad but duplicates code, in the sense that for each
>> operation you need too pieces: the operation and the marshalling, but at
>> least the library user writes her code using only her own types, which I
>> like:
>>
>> SourceType.Generate_Data
>>      .Op1 (FromXtoY.Transformer
>>         (User_FuncX'Access)) -- User_FuncX returns Y
>>      .Op2 (FromYtoZ.Transformer
>>         (User_FuncY'Access)) -- User FuncY returns Z
>>      .Endpoint (Z_Type.As_Z (Function'Access));
>>
>> Of course with proper shorter names it looks better. However, checks are
>> performed at run time.
>>
>> Another idea was to use "&" instead of dot notation,
>>
>> Stream := SourceType.Generate_Data &
>>      Type1.Op1(...) &
>>      Type2.Op2(...) &
>>      Type4.Endpoint (...);
>>
>> having all needed "&" in scope. This possibly requires more "use type"
>> clauses and I haven't tested it yet but I think it should work and be
>> neater, having a "&" taking different left and right types.
>>
>> Another way I was trying was the hybrid one that doesn't work: Using dot
>> notation while there are no type changes, and & to cast to the new type
>> only when needed. (I needed it to work even without parentheses.)
>>
>> The root of the problem is in that, to keep code natural (and
>> compile-time checks) I want to keep the user unaware of class-wide
>> wrappers, and that involves generics. Once you have generic instances,
>> you lose dot notation for transforming operations (since you need to
>> somehow glue two types together, and the new operations are no longer
>> primitive). (On this path, I have an idea involving two instantiations
>> for each type being used, but I'm trying to avoid that for now). (Also I
>> had a neat approach using elaboration-time instantiations but I collided
>> with accessibility checks since I didn't want everything to be at
>> library level.)
>>
>> Anyway, I will keep playing and probably come back for criticism/ideas.
>> It's possible I'm missing other options, of course, which are welcome. I
>> will post my experimental repository once/if something takes shape.
>>
>> Álex.
>


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-03 11:09     ` Alejandro R. Mosteo
                         ` (2 preceding siblings ...)
  2016-06-03 17:31       ` Shark8
@ 2016-06-06  8:10       ` briot.emmanuel
  2016-06-06 13:58         ` Alejandro R. Mosteo
  3 siblings, 1 reply; 17+ messages in thread
From: briot.emmanuel @ 2016-06-06  8:10 UTC (permalink / raw)


> To give you the essence. I'm back to trying to get a minimal ReactiveX 
> (http://reactivex.io)-like thing working. The gist is that you can chain 
> many transformation operations:
> 
> SourceType.Generate_Data
>     .Op1 (...)
>     ...
>     .OpN (...)
>     .Endpoint (Operate_With_Resulting_Transformed_Data);


Funny, I have been playing with exactly the same purpose recently
although I only started from the promises pattern, which I am now
extending.

https://github.com/briot/Ada-promises


I had exactly the same problems you had, and copy with using operators,
so my current syntax is:

      Get_Promise
           and new Op1
           and (new Op2 & new Op3)
           and new Endpoint;

(using tagged types for the operations). That's because things need to be
type safe as well, so the operations are declared in generic packages,
and therefore we can't use the dot notation here. I believe there could be
some extension to the language here.

Emmanuel


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-03 20:41         ` Alejandro R. Mosteo
@ 2016-06-06  8:14           ` briot.emmanuel
  2016-06-06 13:51             ` Alejandro R. Mosteo
  2016-06-07 11:24             ` Traits and iterators (was: Mixing operators and dot notation) Alejandro R. Mosteo
  0 siblings, 2 replies; 17+ messages in thread
From: briot.emmanuel @ 2016-06-06  8:14 UTC (permalink / raw)


> My solution used a base generic as formal for all subsequent formals, 
> and it was the first time I saw the need for that, so it was quite engaging.

it is indeed a powerful approach.
The Ada standard calls them signature packages, other languages sometimes
call them traits. D calls them policy-based containers, I think.


We are working on a containers library using this, so that algorithms, for instance,
can be made independent of containers, and that users can configure a lot of the
behavior of containers (checks or not, bounded or not, definite or indefine
elements) by the proper usage of formal package parameters.
See https://github.com/AdaCore/ada-traits-containers if you want more info.

Look at the docs for some of the rationales behind the current design choices.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-06  8:14           ` briot.emmanuel
@ 2016-06-06 13:51             ` Alejandro R. Mosteo
  2016-06-07 11:24             ` Traits and iterators (was: Mixing operators and dot notation) Alejandro R. Mosteo
  1 sibling, 0 replies; 17+ messages in thread
From: Alejandro R. Mosteo @ 2016-06-06 13:51 UTC (permalink / raw)


On 06/06/16 10:14, briot.emmanuel@gmail.com wrote:
>> My solution used a base generic as formal for all subsequent formals,
>> and it was the first time I saw the need for that, so it was quite engaging.
>
> it is indeed a powerful approach.
> The Ada standard calls them signature packages, other languages sometimes
> call them traits. D calls them policy-based containers, I think.
>
>
> We are working on a containers library using this, so that algorithms, for instance,
> can be made independent of containers, and that users can configure a lot of the
> behavior of containers (checks or not, bounded or not, definite or indefine
> elements) by the proper usage of formal package parameters.
> See https://github.com/AdaCore/ada-traits-containers if you want more info.
>
> Look at the docs for some of the rationales behind the current design choices.

Now I remember I saw some discussion about this project. Perhaps in 
AdaCore's blog? Thanks, I will take a look.

Álex.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Mixing operators and dot notation
  2016-06-06  8:10       ` Mixing operators and dot notation briot.emmanuel
@ 2016-06-06 13:58         ` Alejandro R. Mosteo
  0 siblings, 0 replies; 17+ messages in thread
From: Alejandro R. Mosteo @ 2016-06-06 13:58 UTC (permalink / raw)


On 06/06/16 10:10, briot.emmanuel@gmail.com wrote:
>> To give you the essence. I'm back to trying to get a minimal ReactiveX
>> (http://reactivex.io)-like thing working. The gist is that you can chain
>> many transformation operations:
>>
>> SourceType.Generate_Data
>>      .Op1 (...)
>>      ...
>>      .OpN (...)
>>      .Endpoint (Operate_With_Resulting_Transformed_Data);
>
>
> Funny, I have been playing with exactly the same purpose recently
> although I only started from the promises pattern, which I am now
> extending.
>
> https://github.com/briot/Ada-promises

Noted.

>
> I had exactly the same problems you had, and copy with using operators,
> so my current syntax is:
>
>        Get_Promise
>             and new Op1
>             and (new Op2 & new Op3)
>             and new Endpoint;
>
> (using tagged types for the operations). That's because things need to be
> type safe as well, so the operations are declared in generic packages,
> and therefore we can't use the dot notation here. I believe there could be
> some extension to the language here.

Talk about serendipity. Just last night I arrived at a solution I find 
satisfactory, and I see it's basically the same as yours (using "&" 
instead). From a cursory glance at your Ada-promises site I see that we 
had the same thinking about lambda functions too.

My RxAda outline is here:

https://bitbucket.org/amosteo/rxada/

Álex.

>
> Emmanuel
>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Traits and iterators (was: Mixing operators and dot notation)
  2016-06-06  8:14           ` briot.emmanuel
  2016-06-06 13:51             ` Alejandro R. Mosteo
@ 2016-06-07 11:24             ` Alejandro R. Mosteo
  2016-06-08  7:31               ` briot.emmanuel
  1 sibling, 1 reply; 17+ messages in thread
From: Alejandro R. Mosteo @ 2016-06-07 11:24 UTC (permalink / raw)


On 06/06/16 10:14, briot.emmanuel@gmail.com wrote:

> We are working on a containers library using this, so that algorithms, for instance,
> can be made independent of containers, and that users can configure a lot of the
> behavior of containers (checks or not, bounded or not, definite or indefine
> elements) by the proper usage of formal package parameters.
> See https://github.com/AdaCore/ada-traits-containers if you want more info.

I've now been going over the documentation and it is very good. It 
clarifies a lot of things that were still a bit muddy in my head.

A question arises (actually a lot of them, sorry for not being clearer 
since I'm lacking the final grasp): if one wants to receive via generics 
a type to which the "of" operator can be applied, what would be the 
minimal signature? Is it doable?

I understand the compiler recognizes such types from the aspects in the 
type declaration (I'm looking at Doubly_Linked_Lists for example) so... 
should the type be descended from some other type having the aspects? 
This example, IIUC, says that: 
http://www.adacore.com/adaanswers/gems/gem-128-iterators-in-ada-2012-part-2/

OTOH, I see the example for the traits containers given as:

generic
    with package Elements is new Elements_Policy (<>);
    type Container is private;
    type Cursor is private;
    with function First (Self : Container) return Cursor is <>;
    with function Has_Element
       (Self : Container; C : Cursor) return Boolean is <>;
    with function Element (C : Cursor) return Elements.Element is <>;
    with procedure Next (C : in out Cursor) is <>;
package Forward_Cursors_Policy is
end Forward_Cursors_Policy;

That, in itself, I don't think will give the ability to use "of" in 
iterations, although it enables one to iterate over an unknown type.

I guess what I'm asking for is what's the simplest way to say that some 
type is "iterable", in the "of"-applicability sense, via generics. 
Another my guess is that, from a Cursors policy package, one could have 
a wrapper type with the proper aspects declared using these subprograms.

Sorry for the barrage of not very clear questions/musings.

Thanks,
Álex.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Traits and iterators (was: Mixing operators and dot notation)
  2016-06-07 11:24             ` Traits and iterators (was: Mixing operators and dot notation) Alejandro R. Mosteo
@ 2016-06-08  7:31               ` briot.emmanuel
  2016-06-08 11:18                 ` Traits and iterators Alejandro R. Mosteo
  0 siblings, 1 reply; 17+ messages in thread
From: briot.emmanuel @ 2016-06-08  7:31 UTC (permalink / raw)


> generic
>     with package Elements is new Elements_Policy (<>);
>     type Container is private;
>     type Cursor is private;
>     with function First (Self : Container) return Cursor is <>;
>     with function Has_Element
>        (Self : Container; C : Cursor) return Boolean is <>;
>     with function Element (C : Cursor) return Elements.Element is <>;
>     with procedure Next (C : in out Cursor) is <>;
> package Forward_Cursors_Policy is
> end Forward_Cursors_Policy;
> 
> That, in itself, I don't think will give the ability to use "of" in 
> iterations, although it enables one to iterate over an unknown type.


Indeed, this signature package allows you to write an explicit iteration loop, where
you manipulate cursors explicitly. I don't know, and I don't think it is doable, how to
pass a formal type and mention that it should be iterable in the sense of the "for..of"
loop.
That means that any generic algorithm we write will take the above Policy package,
but will not be able to use "for..of". That's a bit more work to write, but just as
efficient in the end, but perhaps a limitation in the language.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Traits and iterators
  2016-06-08  7:31               ` briot.emmanuel
@ 2016-06-08 11:18                 ` Alejandro R. Mosteo
  0 siblings, 0 replies; 17+ messages in thread
From: Alejandro R. Mosteo @ 2016-06-08 11:18 UTC (permalink / raw)


On 08/06/16 09:31, briot.emmanuel@gmail.com wrote:
>> generic
>>      with package Elements is new Elements_Policy (<>);
>>      type Container is private;
>>      type Cursor is private;
>>      with function First (Self : Container) return Cursor is <>;
>>      with function Has_Element
>>         (Self : Container; C : Cursor) return Boolean is <>;
>>      with function Element (C : Cursor) return Elements.Element is <>;
>>      with procedure Next (C : in out Cursor) is <>;
>> package Forward_Cursors_Policy is
>> end Forward_Cursors_Policy;
>>
>> That, in itself, I don't think will give the ability to use "of" in
>> iterations, although it enables one to iterate over an unknown type.
>
>
> Indeed, this signature package allows you to write an explicit iteration loop, where
> you manipulate cursors explicitly. I don't know, and I don't think it is doable, how to
> pass a formal type and mention that it should be iterable in the sense of the "for..of"
> loop.
> That means that any generic algorithm we write will take the above Policy package,
> but will not be able to use "for..of". That's a bit more work to write, but just as
> efficient in the end, but perhaps a limitation in the language.

Thanks for the confirmation. Sometimes I miss interfaces for these 
things in the language.

Álex.


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2016-06-08 11:18 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-02 21:38 Mixing operators and dot notation Alejandro R. Mosteo
2016-06-02 21:42 ` Alejandro R. Mosteo
2016-06-02 22:28 ` Robert A Duff
2016-06-02 23:26   ` Randy Brukardt
2016-06-03 11:09     ` Alejandro R. Mosteo
2016-06-03 12:19       ` Dmitry A. Kazakov
2016-06-03 14:45       ` G.B.
2016-06-03 17:31       ` Shark8
2016-06-03 20:41         ` Alejandro R. Mosteo
2016-06-06  8:14           ` briot.emmanuel
2016-06-06 13:51             ` Alejandro R. Mosteo
2016-06-07 11:24             ` Traits and iterators (was: Mixing operators and dot notation) Alejandro R. Mosteo
2016-06-08  7:31               ` briot.emmanuel
2016-06-08 11:18                 ` Traits and iterators Alejandro R. Mosteo
2016-06-06  8:10       ` Mixing operators and dot notation briot.emmanuel
2016-06-06 13:58         ` Alejandro R. Mosteo
2016-06-02 23:05 ` Jeffrey R. Carter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox