On 7/18/08, Oliver Kullmann <O.Kullmann at swansea.ac.uk> wrote:
> My first question is whether some helper functionality already
> exists in Maxima to handle the common tasks of creating new
> variable names, translating between the different forms etc. ?
Well, to generate a new variable, you can call the Lisp GENSYM function.
foo : ?gensym ();
=> g36372
bar : ?gensym (1234);
=> g1234
baz : ?gensym ("quux");
=> QUUX36373
The case inversion (quux --> QUUX) is an artifact of Lisp's bizarre
case sensitivity rules. Oh well. You don't need to know the assigned
name anyway, and can't really use the name as far as I can tell.
But you can bind that new symbol to a value via the indirect
assignment operator "::" .
baz :: 6789;
baz;
=> quux36373
''baz; /* that's 2 single quotes there */
=> 6789
> I started writing such functions myself (based on sconcat and eval_string),
If the answer is eval_string, almost certainly you probably meant
to ask a different question.
> Alright, so I create my artificial variable names like "x1, x2, ...",
> and so on, but the problem is that all breaks down if for example
> x1 is already in use.
>
> Now there are several solutions:
> 1) The trivial solution is to use "xyz" instead and hope the best.
> 2) Other computer algebra systems offer functions like "new_symbol".
> 3) For Maxima it seems easiest if one could do the following:
> a) Create a list L = [x1,x2, ...]
> of the variables concerned.
> b) Create a dynamic scope block(L, ...),
> and call all functions within this scope.
>
> No. 3 would look nice and natural to me, if only I knew an (easy) way
> how to tell the "block"-function to treat a first argument as the list
> of local variables. The issue seems to be that at parse-time a special
> treatment of "block([x1,x2])" is performed, while in "block(L)" that
> the list L shall be the list of variables is not recognised.
Well, code = data in Maxima as in Lisp ... If I understand the
problem, you can construct a suitable block (via buildq) and
then evaluate it.
L : [x, y, z];
buildq ([L], block (L, F (splice (L))));
=> block([x, y, z], F(x, y, z))
It sounds like you want to protect some code against accidental
name collisions --- if Maxima had lexical scope, maybe it wouldn't
be an issue ... Anyway maybe you are thinking of something like this?
sanitize ([b, c, e], foo(a, b, c, d, e));
=> foo(a, B36379, C36379, d, E36379)
sanitize ([x, y], foo (x, y) := y - x);
=> foo(X36379, Y36379) := Y36379 - X36379
where "sanitize" is the following bit of obscure macrology or something like it:
sanitize (L%, e%) ::=
(map (?gensym, map (string, L%)),
apply (buildq, [map (lambda ([x%, y%], buildq ([x%, y%], x% : y%)),
L%, %%), e%]));
Hope this helps in some way.
Robert Dodier