Karim Belabas on Wed, 03 Oct 2007 15:05:37 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
variable scope in GP |
Hi all, this week-end I spent some time documenting * the new my() declarations [ lexically scoped variables ], and * the change of paradigm, from dynamic to lexical scoping, for variables having implicitly local scope [ names of function parameters, names of loop/summation indices ]. N.B. If the above items don't make sense to you, please update from CVS (2.4.2 series) and check sections 2.5 and 2.6 of the user's manual. ( If it still does not make sense after that, please ask questions and propose corrections ! ) The change has *far reaching* consequences, which Bill alluded to in his earlier messages. The most important ones: 1) If you were used to local(), you almost certainly want to use my() in its place. If you made essentially trivial use of local(), e.g. without having bothered to check the documentation and warnings therein, chances are that your scripts will still work. But, still, see 2): local() is now deprecated unless you know *exactly* what you're doing. 2) If you hit bizarre bugs in your scripts, check whether you were not making use of the following "feature": f(bnf) = ...; g(); ... g() = ... use bnf ... Using dynamic scoping [old], g() called within f() had access to the 'bnf' parameter given to f(), since control flow had not yet left the scope of f's body. [ Of course, calling g() from outside f had access to a different 'bnf'... ] Using lexical scoping [current], f's bnf is now private to the block of program text which is f's body, and g() is now accessing some global 'bnf' Same problem with 'loop indices' g() = ... use i ... for ( i = 1, 10, g() ) With the new behaviour, g() has no access to the loop index 'i'. A quick patch for problems of the above kind, without trying to fix the underlying code, is to use the following trick: f(bnf) = local(bnf = bnf); ...; g(); ... [ a new dynamically scoped 'bnf', initialized to the value of the lexically scoped 'bnf' passed as a function parameter; g can access the former ] 3) The debugging facilities offered by trap() and break loops have been drastically reduced: lexically scoped variables are not accessible to the break loop [ which is evaluated in a different scope ]. In fact names of lexical variables disappear during the compilation phase (since we know at that time where to find their values), the compiled code doesn't know anything about them. 4) For the same reason, 'eval' has become less powerful since it can't access lexically scoped variables: ? my(x = 1); eval("x") %1 = x since the lexical 'x' disappears during compilation, 'eval'uation occurs too late. Of course ? local(x = 1); eval("x") %1 = 1 still works, and so does the even more cryptic ? my(x = 1); local(x = x); eval("x") Besides the backward compatibility problems, which should remain limited, items 3) and 4) are bad news; they currently don't seem easy to fix. Please test and experiment ! Have fun, K.B. P.S: Two other sources of obscure bugs have been mentionned, which it would be desirable to address, at the cost of breaking backward compatibility in a more severe way: 1) Remove the possibility to abreviate f() to f. 2) Initialize new variables to "free variables" not to 0. -- Karim Belabas Tel: (+33) (0)5 40 00 26 17 Universite Bordeaux 1 Fax: (+33) (0)5 40 00 69 50 351, cours de la Liberation http://www.math.u-bordeaux.fr/~belabas/ F-33405 Talence (France) http://pari.math.u-bordeaux.fr/ [PARI/GP]