comp.lang.ada
 help / color / mirror / Atom feed
* Defining a binary operator between function access types: Is it possible?
@ 2008-10-16 13:34 soychangoman
  2008-10-16 14:26 ` Dmitry A. Kazakov
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: soychangoman @ 2008-10-16 13:34 UTC (permalink / raw)


I'm trying to define a binary operator between function access types
that returns the access to the function that is the binary operator
acting on both functions. Let's put it a bit clearer:

-----------
procedure operating_on_access is

  type function_access is access function ( x : Real) return Real;

  function "+" (f1 : function_access; f2 : function_access) return
function_access is
  begin
     -- The question is what to put here
  return null;
  end "+"

  funcion square (x : Real) return Real is
  begin
      return x**2;
  end square;

  funcion cubic (x : Real) return Real is
  begin
      return x**3;
  end square;

  f1_acc,   f2_acc,   f3_acc : function_access;

begin

  f1_acc := square'Access;
  f2_acc := cubic'Access;

  -- f3_acc := f1_acc + f2_acc;
-- the idea is that ' f3_acc.all ( x )  ' and ' square (x) + cubic(x)
' are equivalent

end operating_on_access;
-----

Thanks in advance

Matías Niklison



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

* Re: Defining a binary operator between function access types: Is it possible?
  2008-10-16 13:34 Defining a binary operator between function access types: Is it possible? soychangoman
@ 2008-10-16 14:26 ` Dmitry A. Kazakov
  2008-10-16 14:29 ` Adam Beneschan
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Dmitry A. Kazakov @ 2008-10-16 14:26 UTC (permalink / raw)


On Thu, 16 Oct 2008 06:34:30 -0700 (PDT), soychangoman@gmail.com wrote:

> I'm trying to define a binary operator between function access types
> that returns the access to the function that is the binary operator
> acting on both functions.

You cannot create a new subprograms and return it from another subprogram.
To have the effect of an interpreted language you have to define
corresponding first-class types. For example:

   type Operation is abstract tagged private;
   function Evaluate (F : Operation; X : Real) return Real is abstract;
   ...
   type Squaring is new Operation with null record;
   overriding function Evaluate (F : Squaring; X : Real) return Real;
   Square : constant Squaring;
   ...

   type Composed_By_Plus is new Operation with private;
   function "+" (L, R : Operation'Class) return Composed_By_Plus;
   overriding
      function Evaluate (F : Composed_By_Plus; X : Real) return Real;
   ...

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



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

* Re: Defining a binary operator between function access types: Is it possible?
  2008-10-16 13:34 Defining a binary operator between function access types: Is it possible? soychangoman
  2008-10-16 14:26 ` Dmitry A. Kazakov
@ 2008-10-16 14:29 ` Adam Beneschan
  2008-10-16 22:18   ` Robert A Duff
  2008-10-16 15:14 ` Jacob Sparre Andersen
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Adam Beneschan @ 2008-10-16 14:29 UTC (permalink / raw)


On Oct 16, 6:34 am, soychango...@gmail.com wrote:
> I'm trying to define a binary operator between function access types
> that returns the access to the function that is the binary operator
> acting on both functions. Let's put it a bit clearer:
>
> -----------
> procedure operating_on_access is
>
>   type function_access is access function ( x : Real) return Real;
>
>   function "+" (f1 : function_access; f2 : function_access) return
> function_access is
>   begin
>      -- The question is what to put here
>   return null;
>   end "+"
>
>   funcion square (x : Real) return Real is
>   begin
>       return x**2;
>   end square;
>
>   funcion cubic (x : Real) return Real is
>   begin
>       return x**3;
>   end square;
>
>   f1_acc,   f2_acc,   f3_acc : function_access;
>
> begin
>
>   f1_acc := square'Access;
>   f2_acc := cubic'Access;
>
>   -- f3_acc := f1_acc + f2_acc;
> -- the idea is that ' f3_acc.all ( x )  ' and ' square (x) + cubic(x)
> ' are equivalent
>
> end operating_on_access;

You must be used to Lisp or something, right?  This isn't going to
work at all.  A Function_Access is basically a pointer to a function
that has already been written.  You're asking the program to build a
*new* function on the fly and return a pointer to that.  That pretty
much works only in interpreted languages, and Ada isn't one of those.

If you really need something like this, you'll have to build your own
interpreter somehow.  It could be a very simple one depending on what
your needs are.

                             -- Adam




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

* Re: Defining a binary operator between function access types: Is it possible?
  2008-10-16 13:34 Defining a binary operator between function access types: Is it possible? soychangoman
  2008-10-16 14:26 ` Dmitry A. Kazakov
  2008-10-16 14:29 ` Adam Beneschan
@ 2008-10-16 15:14 ` Jacob Sparre Andersen
  2008-10-17  7:10 ` Defining a binary operator between function access types: Is it anon
  2008-10-21  6:46 ` Defining a binary operator between function access types: Is it possible? Ivan Levashew
  4 siblings, 0 replies; 8+ messages in thread
From: Jacob Sparre Andersen @ 2008-10-16 15:14 UTC (permalink / raw)


soychangoman@gmail.com writes:

> I'm trying to define a binary operator between function access types
> that returns the access to the function that is the binary operator
> acting on both functions.

You can't do that quite like that.

The first idea which springs to mind for solving this kind of problem
is to make a hack using tagged types ...

   type Abstract_Binary_Operation is abstract tagged null record;
   function Operate (O    : Abstract_Binary_Operation;
                     L, R : Real) return Real is abstract;

   type Composed_Addition (FL, FR : access function (X : Real) return Real) is
     new Abstract_Binary_Operation with null record;
   function Operate (O    : Composed_Addition;
                     L, R : Real) return Real is
   begin
      return O.FL (L) + O.FR (R);
   end Operate;

Just a wild thought!  Not tested!

Greetings,

Jacob
-- 
People in cars cause accidents. Accidents in cars cause people.



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

* Re: Defining a binary operator between function access types: Is it possible?
  2008-10-16 14:29 ` Adam Beneschan
@ 2008-10-16 22:18   ` Robert A Duff
  0 siblings, 0 replies; 8+ messages in thread
From: Robert A Duff @ 2008-10-16 22:18 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> On Oct 16, 6:34 am, soychango...@gmail.com wrote:
>> I'm trying to define a binary operator between function access types
>> that returns the access to the function that is the binary operator
>> acting on both functions. Let's put it a bit clearer:
>>
>> -----------
>> procedure operating_on_access is
>>
>>   type function_access is access function ( x : Real) return Real;
>>
>>   function "+" (f1 : function_access; f2 : function_access) return
>> function_access is
>>   begin
>>      -- The question is what to put here
>>   return null;
>>   end "+"
>>
>>   funcion square (x : Real) return Real is
>>   begin
>>       return x**2;
>>   end square;
>>
>>   funcion cubic (x : Real) return Real is
>>   begin
>>       return x**3;
>>   end square;
>>
>>   f1_acc,   f2_acc,   f3_acc : function_access;
>>
>> begin
>>
>>   f1_acc := square'Access;
>>   f2_acc := cubic'Access;
>>
>>   -- f3_acc := f1_acc + f2_acc;
>> -- the idea is that ' f3_acc.all ( x )  ' and ' square (x) + cubic(x)
>> ' are equivalent
>>
>> end operating_on_access;
>
> You must be used to Lisp or something, right?

You can't do that sort of thing in Ada.  What the OP is asking for is
"full closures".  Ada only has "downward closures" -- you can pass
procedures into procedures, but not out.

>...This isn't going to
> work at all.  A Function_Access is basically a pointer to a function
> that has already been written.  You're asking the program to build a
> *new* function on the fly and return a pointer to that.  That pretty
> much works only in interpreted languages, and Ada isn't one of those.

Full closures are typically supported by functional languages, such as
Lisp (which Adam mentioned), Scheme, SML, OCaml, Haskell, etc.  They do
not need to be "interpreted languages" -- it is reasonable to compile to
machine code in many such languages, and it's done in practice.

They do normally need garbage collection.

Jacob Sparre Andersen outlined how to simulate full closures using
tagged and class-wide types.

> If you really need something like this, you'll have to build your own
> interpreter somehow.  It could be a very simple one depending on what
> your needs are.

- Bob



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

* Re: Defining a binary operator between function access types: Is it
  2008-10-16 13:34 Defining a binary operator between function access types: Is it possible? soychangoman
                   ` (2 preceding siblings ...)
  2008-10-16 15:14 ` Jacob Sparre Andersen
@ 2008-10-17  7:10 ` anon
  2008-10-21  6:46 ` Defining a binary operator between function access types: Is it possible? Ivan Levashew
  4 siblings, 0 replies; 8+ messages in thread
From: anon @ 2008-10-17  7:10 UTC (permalink / raw)


--
-- File b.adb
--
-- Even though Adam is correct, the following program works using 
-- pointers and assigning the function dynamically.
-- Also, using Ada 95 specs 
--
with Ada.Text_IO ;
use  Ada.Text_IO ;

with Ada.Float_Text_IO ;
use  Ada.Float_Text_IO ;

procedure b is

  type function_access is access function ( x : Float ) return Float ;

  --
  -- Library routines
  --
  function square ( x : Float ) return Float is
    begin
      return x ** 2 ;
    end square ;

  function cubic ( x : Float ) return Float is
    begin
      return x ** 3 ;
    end cubic ;


  function f3 ( x : Float ) return Float ;
  --
  -- dynamically assignable
  --
  f1_access : function_access := null ;
  f2_access : function_access := null ;
  --
  -- lock access to function f3 only 
  --
  f3_access : constant function_access := f3'access ; 

  -- 
  -- Dynamic useable function
  --
  function f3 ( x : Float ) return Float is

    Function_Error : exception ;

    begin -- f3
      if f1_access /= null and then f2_access /= null then
        return f1_access.all ( x ) + f2_access.all ( x ) ;
      end if ;
    raise Function_Error ;
    end f3 ;



begin
  
  -- Initialize functions variables
  
  f1_access := square'Access ;
  f2_access := cubic'Access ;


  -- f3_acc := f1_acc + f2_acc ;
  -- the idea is that  f3_acc.all ( x )  =>  square ( x ) + cubic ( x )

  Put ( "1.0 := " ) ;
  Put ( f3_access.all ( 1.0 ) ) ;
  New_Line ;

  Put ( "Perform 'square ( x ) + cubic ( x )'  => " ) ;
  Put ( "where x => 2.0 gives " ) ;
  Put ( f3_access.all ( 2.0 ) ) ;
  New_Line ;


  -- Reassign f2 to a square 
  f2_access := square'Access ;

  Put ( "Perform 'square ( x ) + square ( x )' => " ) ;
  Put ( "where x => 2.0 gives " ) ;
 
  Put ( f3_access.all ( 2.0 ) ) ;
  New_Line ;

end b ;


In <fed9902a-28f0-4e70-a427-4773b20aae47@p49g2000hsd.googlegroups.com>, soychangoman@gmail.com writes:
>I'm trying to define a binary operator between function access types
>that returns the access to the function that is the binary operator
>acting on both functions. Let's put it a bit clearer:
>
>-----------
>procedure operating_on_access is
>
>  type function_access is access function ( x : Real) return Real;
>
>  function "+" (f1 : function_access; f2 : function_access) return
>function_access is
>  begin
>     -- The question is what to put here
>  return null;
>  end "+"
>
>  funcion square (x : Real) return Real is
>  begin
>      return x**2;
>  end square;
>
>  funcion cubic (x : Real) return Real is
>  begin
>      return x**3;
>  end square;
>
>  f1_acc,   f2_acc,   f3_acc : function_access;
>
>begin
>
>  f1_acc :=3D square'Access;
>  f2_acc :=3D cubic'Access;
>
>  -- f3_acc :=3D f1_acc + f2_acc;
>-- the idea is that ' f3_acc.all ( x )  ' and ' square (x) + cubic(x)
>' are equivalent
>
>end operating_on_access;
>-----
>
>Thanks in advance
>
>Mat=EDas Niklison




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

* Re: Defining a binary operator between function access types: Is it possible?
  2008-10-16 13:34 Defining a binary operator between function access types: Is it possible? soychangoman
                   ` (3 preceding siblings ...)
  2008-10-17  7:10 ` Defining a binary operator between function access types: Is it anon
@ 2008-10-21  6:46 ` Ivan Levashew
  2008-10-21 13:17   ` soychangoman
  4 siblings, 1 reply; 8+ messages in thread
From: Ivan Levashew @ 2008-10-21  6:46 UTC (permalink / raw)


Nobody seems to mention another way to do the trick. One can use just
downwards closures, and circumvent upwards closures restriction via
CPS, e. g. add extra "Continuation : access procedure" argument in
every procedure, and add extra
"Continuation : access procedure (Result : Your_Result_Type)" argument
in every function. It will actually work. Despite being clearly crazy
(it blows your stack), blowing stack and heap is what actually happens
when C++ compiler interpretes BOOST, Loki, Blitz++ sources. IIUC
standards-compliant C++ compiler can't get rid of any of intermediate
results.

P. S. http://okasaki.blogspot.com/2008/07/functional-programming-inada.html



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

* Re: Defining a binary operator between function access types: Is it possible?
  2008-10-21  6:46 ` Defining a binary operator between function access types: Is it possible? Ivan Levashew
@ 2008-10-21 13:17   ` soychangoman
  0 siblings, 0 replies; 8+ messages in thread
From: soychangoman @ 2008-10-21 13:17 UTC (permalink / raw)


Well, first of all thanks for all the responses. I finally found a
solution that makes me happy and I was able to implement.

Here's what I did:

I defined:
--------------
   type Symbols_Enumeration is ('+', '-','*', '/', Power,
                                analytic);
   package Symbols is new Stacks(Symbols_Enumeration);

   type Analytic_Function_Access is access function ( x : Real'Base)
return Real'Base;
   package Analytics is new Stacks(Analytic_Function_Access);

   package Real_Numbers is new Stacks(Real);

   type My_Function is record
      Symbols_Stack      : Symbols.Stack;

      Analytics_Stack    : Analytics.Stack;
      Real_Numbers_Stack : Real_Numbers.Stack;

   end record;
-------------
Where the package Stacks is a generic Stack manager.

The idea is to use the calculator notation, I mean, if I do:
------
f1,f2,f : My_Function;

--some kind of initialization to f1 and f2 where I say that
--f1.Symbols_Stack   f1.Analytic_Stack
--|analytic|         |f1_acc|
-- the same for f2

f := f1 + f2;
------
then f will have
f.Symbols_Stack   f.Analytic_Stack
|+       |         |f1_acc|
|analytic|         |f2_acc|
|analytic|

If I have a * or even a ** the compiler takes care of precedence of
the operators, all i have to take care is to put everithing on the
stack.
example:
f := (f1+f2) * (f3+f4);

f.Symbols_Stack   f.Analytic_Stack
|*       |
|+       |        |f1_acc|
|analytic|        |f2_acc|
|analytic|        |f3_acc|
|+       |        |f4_acc|
|analytic|
|analytic|

If I want to do this
f:= f1 * 2.0;

then

f.Symbols_Stack   f.Analytic_Stack    f.Real_Numbers_Stack
|*          |
|analytic   |
|Real_Number|        |f1_acc|         |2.0  |

When I want to get f(x) I just do like the calculator. I Get symbol by
Symbol in the Symbols_Stack and when I find something that is not a
operator (like a 'Real_Number') I look for it in the corresponding
stack (f.Real_Numbers_Stack).

I didn't post the source code becouse it's a little long, but if
anyone has curiosity just mail me.
About Ivan Levashew's Post... well I realy didn't quite understood
yet, but I think that if the package is used adequately it won't blow
my stack away, even if it's used for big calculations, am I right?

Thanks everyone again =)

Saludos

Matías Niklison



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

end of thread, other threads:[~2008-10-21 13:17 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-16 13:34 Defining a binary operator between function access types: Is it possible? soychangoman
2008-10-16 14:26 ` Dmitry A. Kazakov
2008-10-16 14:29 ` Adam Beneschan
2008-10-16 22:18   ` Robert A Duff
2008-10-16 15:14 ` Jacob Sparre Andersen
2008-10-17  7:10 ` Defining a binary operator between function access types: Is it anon
2008-10-21  6:46 ` Defining a binary operator between function access types: Is it possible? Ivan Levashew
2008-10-21 13:17   ` soychangoman

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