Search code examples
first-class-functionsparipari-gp

Pari/GP: the user defined function as a return value


I have a problem with Pari/GP user defined functions making use of user defined functions returning functions. Here is a dumbed-down example:

? f(x) = { (t) -> x + t }
%1 = (x)->(t)->x+t
? g(x) = { local(y); y = f(x); (t) -> y(t) }
%2 = (x)->local(y);y=f(x);(t)->y(t)
? h = g(2)
%3 = (t)->my(x=2);y(t)
? h(1)
  ***   at top-level: h(1)
  ***                 ^----
  ***   in function h: y(t)
  ***                  ^----
  ***   not a function in function call
  ***   Break loop: type 'break' to go back to GP

I expected to get h(1)=(g(2))(1)=y(1)=(f(2))(1)=3. Am I running into a limitation of first-class functions in Pari, or am I doing something wrong? If the latter, how do I fix it?


Solution

  • Note, the local keyword bounds your variables within the dynamic scope. Make sure that the guy y from the same/outer scope is referred to the expected thing when h(1) is calling. In that case the appropriate fix can be as follows:

    ?f = (x) -> { (t) -> x + t }
    %1 = (x)->(t)->x+t
    
    ?g = (x) -> { local(y); (t) -> y(x)(t) }
    %1 = (x)->local(y);(t)->y(x)(t)
    
    ?h = g(2)
    %1 = (t)->my(x=2);y(x)(t)
    
    ?y = (x) -> f(x);
    ?h(1)
    %1 = 3
    
    ?y = 1;
    ?h(1)
    *** not a function in function call 
    

    Alternatively, I strongly recommend to use a static (lexical) scope for the variables in order to simplify your code and eliminate the referring dependencies. Use my specifier for that. Look at the fixed code below:

    ?f(x) = { (t) -> x + t }
    %1 = (x)->my(t);t->x+t
    
    ?g(x) = { my (y = f(x)); (t) -> y(t) }
    %1 = (x)->my(y=f(x));(t)->y(t)
    
    ?h = g(2)
    %1 = (t)->my(x=2,y=(t)->my(x=2);x+t);y(t)
    
    ?h(1)
    %1 = 3
    

    Note, the evaluation of last version of h takes less time. Also I recommend you to use the code style from the PARI/GP's authors (http://pari.math.u-bordeaux1.fr/pub/pari/manuals/2.4.2/users.pdf)