Dear GiNaC developers, In "What doesn't belong into GiNaC" section of GiNaC tutorial you encourage using GiNaC as a bottom of a complete CAS. I have used GiNaC in connection with Python language and found that such a combination can be very close to a perfect environment that has powerful programming capabilities with efficient symbolic algebra support. However, GiNaC lacks one important feature, that is, creating new functions in runtime. It is clear that within C++ environment it is not desired (if not impossible) as users can define their functions at the compilation stage. In scripting languages, however, new functions can be defined only in runtime. Therefore, I have been looking ways how to create new functions to GiNaC without forcing re-compilations of C++ codes. One can find different approaches for that but they all require some modifications to GiNaC sources. So, I am writing to you with a hope that these modifications could be done in GiNaC repository, rather than by me or anybody else with a similar projects, each time as a new version of GiNaC is released. After trying out many approaches, I have reached to the following conclusion: It is impossible to define dynamic functions in GiNaC because the variables function_options::eval_f,evalf_f,series_f,derivative_f must point to static functions where is impossible to determine what function called it (that is, with what serial number). Now, let me describe a solution to this problem: 1) (Interface authors) define special functions dynfunc_eval_f,etc as follows (I'll use Python C/API for illustrations): ex dynfunc_eval_f(const exvector & seq) { unsigned serial = function::current_serial; //see below (3) PyObject *func = dynfunc_eval_cache[serial]; //see below (2) /* Implement call: result = func(seq), specific to different languages */ return result; } 2) Dynamic functions are created by calling the following (a minimal implementation): void build_function(const string & name, unsigned nparams, PyObject* py_eval_func, //pointers to Python functions PyObject* py_evalf_func, ...) { function_options opts; opts = set_name(name).eval_func(dynfunc_eval_f); // NOTE: all dynamically created functions have the same eval_f. // There, using cache and serial, appropriate Python function is called. // See above (1) opts.test_and_set_params(nparams); unsigned serial = function::register_new(opts); // Store Python function in cache: dynfunc_eval_cache[serial] = py_eval_func; } where std::map<unsigned, PyObject*> dynfunc_eval_cache; is defined in the interface space (similarly are defined hooks for evalf,series,derivative). 3) The following definitions would be new to GiNaC: typedef ex (* GiNaC::eval_funcp_v)(const exvector &); function_options& function_options::eval_func(eval_funcp_v e) { use_vector_args = true; eval_f = eval_funcp(e); return *this; } class function_options { ... protected: bool use_vector_args; /* are to be set false by default */ }; class function { ... public: static unsigned current_serial; }; and in GiNaC::function::eval the following lines are added just before the 'switch (opt.nparams) {..}' statement: if (registered_functions()[serial].use_vector_args) { current_serial = serial; eval_result = ((eval_funcp_v)(registered_functions()[serial].eval_f))(seq); } else Similar hooks are added to functions GiNaC::function::eval,series,pderivative. What do you think? Can I can implement/test these modifications and send you them as a patch? Thanks, Pearu