Hi Jens! Jens Vollinga wrote:
here now a small code example to make clear what I was taking about when I mentioned class-functions. A log10 function is declared as an example. The fclass (-> function) class basically installs some default printing and has some convenience ctors. I know there are some issues about the macros (fixed archiving defaults, naming, ...), some print stuff is missing in fclass, and there is no special code for log10 (series, ...) yet, but the main concept should become clear.
Eval: - compatibility is severly broken (but maybe we should break it anyhow: why not rename tgamma to Gamma, beta to Beta, lgamma to logGamma?) + logic like if (is_a<function>(e)) { std::string name = ex_to<function>(e).get_name(); if (name == "H") { ... can be replaced by more efficient code + hierarchies like polylog->nielsen_polylog->multiple_polylog possible + function.pl is no longer needed + eval/evalf slightly faster (?) + non-ex arguments for ctors (and eval, ...) possible + extra methods/logic/data can be included in the function class (projects like nestedsums, xloops suffer from not being able to do this at the moment) + more OOP like (disputable, but we will never hear the often raised question 'why didn't you just define the functions as classes?' again + better (OOP-like) handling of look-up tables (as static data or maybe the function might become a singleton) - no nice separation of cln and GiNaC code possible + print-Methods can also be changed at runtime for functions - archiving slightly slower because of longer reg_info list
Basically, I begin to appreciate (well, again) the idea of having symbolic functions as objects of different classes, one for each mathematical function. But the idea of _not_ being able to write sin(something), when I want a sine of something is not very appealing, I think. What about this alternative: Name the classes sin_t, log_t, tgamma_t (or some other uniform scheme) and provide functions sin, log, tgamma that return objects of these classes. The advantages are that people a) don't have to rewrite too much code and b) we don't bother our users with yet another convention for naming mathematical functions. Does that sound reasonable? Though, I totally agree with your earlier sentiment that in the general case we shouldn't worry too much about name clashes and instead we should put the burden of disambiguation on the user. But in special cases where there are conflicts with functions of built-in integral type, I think it is just fine to disambiguate in favor of the GiNaC functions by adding an explicit signature. This way, sin(1) stays what it is: sin(1) (well, sin_t(1) or function(42,1) or whatever) and does not become 0.84147... I remember that when we first hit the problem of what sin(1) is supposed to be, I had tons of explicit overloads but quickly found that the template was a more clever idea. Well, if it clashes again because GCC's cmath has become just as clever, good for GCC and maybe bad for us. Going back to some (not all!) explicit overloads sounds elegant, if it solves the problems at hand, doesn't it? Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>