comp.lang.ada
 help / color / mirror / Atom feed
From: Shark8 <onewingedshark@gmail.com>
Subject: Re: Mixing operators and dot notation
Date: Fri, 3 Jun 2016 10:31:57 -0700 (PDT)
Date: 2016-06-03T10:31:57-07:00	[thread overview]
Message-ID: <c77d48b5-0f63-4adb-8403-78aaf2558bee@googlegroups.com> (raw)
In-Reply-To: <niroh2$43q$1@dont-email.me>

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.


  parent reply	other threads:[~2016-06-03 17:31 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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
replies disabled

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