| Karim Belabas on Tue, 16 Jul 2019 13:25:21 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| Re: Using local variable for memoizing in recursion |
* Дмитрий Рыбас [2019-07-16 09:44]:
> So, for system functions pointers are marked with ampersand (&) and for
> user functions pointers are marked with tilde (~) in 2.12 ?
Not quite: we don't have true user function pointers (hence the tilde
instead of the customary ampersand). It's really a mutable *container*
(we're allowing to modify in place an object of list/vector/matrix-type),
this is not a side effect changing a variable value. Compare:
? f(~x) = x = 1;
? x = 0; f(~x); x \\ x didn't change
%2 = 0
? g(~x) = x[1] = 1;
? x = [0]; g(~x); x \\ but the *content* of a container type x would change
%4 = [1]
This can also be used to make sure that a given bulky argument is
*never* copied by user functions. GP's copy optimizer is usually clever
enough but it sometimes errs on the paranoid side to survive problematic
constructs (usually involving global variables). E.g.,
x = [1]; /* global; no lexical scoping */
f(y) = /*...complicated code...*/;
f(x)
Must must we make a deep copy of 'x' in case some user subroutine called by
f messes with it, or is a shallow copy safe enough ? [ In fact it's
rarely safe because GP is not compiled: global subroutines called by f may be
redefined at any time... ]
With
f(~y) = ...
f(~x)
there's no problem: no copy.
> That's great! But a little bit strange if that difference really exist.
> Will be waiting for 2.12 stable.
>
> As for "cumbersome" way, here is what I has written:
>
> p(n,k) =
> {
> local(M = Map()); /* Do not use my() here, use local() !! */
> my(memo_p = (N,K)-> my(res);
> if(N==0 && K==0,return(1));
> if(k<1,return(0));
^--- you mean K here
> if(mapisdefined(M,[N,K],&res),return(res));
> if(K>=N,res=numbpart(N);mapput(M,[N,K],res);return(res));
> res=self()(N,K-1)+self()(N-K,K);
> mapput(M,[N,K],res);
> return(res));
> memo_p(n,k);
> }
You can simplify this a little:
p(n,k) =
{
local(M = Map()); /* yes, local is needed: sorry... */
my(memo_p = (N,K)-> my(res);
if(N==0 && K==0,return(1));
if(K<1,return(0));
if(mapisdefined(M,[N,K],&res),return(res));
res = if(K>=N, numbpart(N), self()(N,K-1)+self()(N-K,K));
mapput(M,[N,K],res); return(res));
memo_p(n,k);
}
Cheers,
K.B.
--
Karim Belabas, IMB (UMR 5251) Tel: (+33) (0)5 40 00 26 17
Universite de Bordeaux Fax: (+33) (0)5 40 00 21 23
351, cours de la Liberation http://www.math.u-bordeaux.fr/~kbelabas/
F-33405 Talence (France) http://pari.math.u-bordeaux.fr/ [PARI/GP]
`