dolfin team mailing list archive
-
dolfin team
-
Mailing list archive
-
Message #10295
Re: new Function design
2008/10/22 Johan Hake <hake@xxxxxxxxx>:
> On Wednesday 22 October 2008 21:49:10 Martin Sandve Alnæs wrote:
>> 2008/10/22 Anders Logg <logg@xxxxxxxxx>:
>> > On Wed, Oct 22, 2008 at 09:36:27PM +0200, Johan Hake wrote:
>> >> On Wednesday 22 October 2008 18:37:44 Anders Logg wrote:
>> >> > On Wed, Oct 22, 2008 at 11:55:10AM +0200, Martin Sandve Alnæs wrote:
>> >> > > 2008/10/22 Johan Hake <hake@xxxxxxxxx>:
>> >> > > > On Wednesday 22 October 2008 11:12:02 Martin Sandve Alnæs wrote:
>> >> > > >> 2008/10/22 Johan Hake <hake@xxxxxxxxx>:
>> >> > > >> > On Wednesday 22 October 2008 10:17:43 Martin Sandve Alnæs wrote:
>> >> > > >> >> 2008/10/22 Johan Hake <hake@xxxxxxxxx>:
>> >> > > >> >> > On Wednesday 22 October 2008 09:32:31 Martin Sandve Alnæs
> wrote:
>> >> > > >> >> >> 2008/10/22 Johan Hake <hake@xxxxxxxxx>:
>> >> > > >> >> >> > On Tuesday 21 October 2008 23:23:27 Martin Sandve Alnæs
> wrote:
>> >> > > >> >> >> >> 2008/10/21 Johan Hake <hake@xxxxxxxxx>:
>> >> > > >> >> >> >> > On Tuesday 21 October 2008 22:34:04 Martin Sandve
>> >> > > >> >> >> >> > Alnæs
>> >>
>> >> wrote:
>> >> > > >> >> >> >> >> 2008/10/21 Johan Hake <hake@xxxxxxxxx>:
>> >> > > >> >> >> >> >> > On Tuesday 21 October 2008 21:37:13 Martin Sandve
>> >> > > >> >> >> >> >> > Alnæs
>> >>
>> >> wrote:
>> >> > > >> >> >> >> >> >> 2008/10/21 Anders Logg <logg@xxxxxxxxx>:
>> >> > > >> >> >> >> >> >> > On Tue, Oct 21, 2008 at 06:01:53PM +0100, Garth
>> >> > > >> >> >> >> >> >> > N. Wells
>> >> > > >> >
>> >> > > >> > wrote:
>> >> > > >> >> >> >> >> >> >> Anders Logg wrote:
>> >> > > >> >> >> >> >> >> >> > On Tue, Oct 21, 2008 at 04:45:01PM +0100,
>> >> > > >> >> >> >> >> >> >> > Garth N. Wells
>> >> > > >> >> >
>> >> > > >> >> > wrote:
>> >> > > >> >> >> >> >> >> >> >> I have a few questions and thoughts
>> >> > > >> >> >> >> >> >> >> >> regarding the new Function design
>> >> > > >> >> >> >> >> >> >> >>
>> >> > > >> >> >> >> >> >> >> >> * It's not clear to me what the intention is
>> >> > > >> >> >> >> >> >> >> >> with user-defined functions. The functions
>> >> > > >> >> >> >> >> >> >> >> Function::interpolate(...) never call
>> >> > > >> >> >> >> >> >> >> >> eval(..), so they can't pick up user-defined
>> >> > > >> >> >> >> >> >> >> >> values. Should Function::interpolate test
>> >> > > >> >> >> >> >> >> >> >> for the presence of a GenericVector to
>> >> > > >> >> >> >> >> >> >> >> decide whether or not the Function is
>> >> > > >> >> >> >> >> >> >> >> discrete or user-defined?
>> >> > > >> >> >> >> >> >> >> >
>> >> > > >> >> >> >> >> >> >> > Yes, sorry. I've missed this. I'll fix it.
>> >> > > >> >> >> >> >> >> >> >
>> >> > > >> >> >> >> >> >> >> >> * It would be useful to declare user-defined
>> >> > > >> >> >> >> >> >> >> >> functions without associating a
>> >> > > >> >> >> >> >> >> >> >> FunctionSpace. If we want to interpolate the
>> >> > > >> >> >> >> >> >> >> >> function, a FunctionSpace must then be
>> >> > > >> >> >> >> >> >> >> >> provided. Anyone see any problems with this?
>> >> > > >> >> >> >> >> >> >> >
>> >> > > >> >> >> >> >> >> >> > The reasoning here is that all Functions must
>> >> > > >> >> >> >> >> >> >> > always be associated with a FunctionSpace so
>> >> > > >> >> >> >> >> >> >> > that they may be correctly interpreted in
>> >> > > >> >> >> >> >> >> >> > forms and correctly plotted. When a Function
>> >> > > >> >> >> >> >> >> >> > is created in PyDOLFIN, it must always be
>> >> > > >> >> >> >> >> >> >> > associated with a certain FiniteElement (and
>> >> > > >> >> >> >> >> >> >> > in a while FunctionSpace). It would simplify
>> >> > > >> >> >> >> >> >> >> > the handling of Functions if they are always
>> >> > > >> >> >> >> >> >> >> > associated with a FunctionSpace.
>> >> > > >> >> >> >> >> >> >>
>> >> > > >> >> >> >> >> >> >> I agree that is makes life simple if every
>> >> > > >> >> >> >> >> >> >> function has a space, but it is a bit clunky
>> >> > > >> >> >> >> >> >> >> for declaring user-defined functions. The forms
>> >> > > >> >> >> >> >> >> >> must be declared first to extract the finite
>> >> > > >> >> >> >> >> >> >> element to create the function space. Could
>> >> > > >> >> >> >> >> >> >> look nasty when a lot of functions are
>> >> > > >> >> >> >> >> >> >> involved.
>> >> > > >> >> >> >> >> >> >>
>> >> > > >> >> >> >> >> >> >> We have a function Function::interpolate which
>> >> > > >> >> >> >> >> >> >> takes a function space V as an argument and it
>> >> > > >> >> >> >> >> >> >> interpolates the function u in V. What if we
>> >> > > >> >> >> >> >> >> >> permit undefined function spaces (which perhaps
>> >> > > >> >> >> >> >> >> >> only have a domain)? We would then interpolate
>> >> > > >> >> >> >> >> >> >> the user defined function u in the provided
>> >> > > >> >> >> >> >> >> >> space V.
>> >> > > >> >> >> >> >> >> >>
>> >> > > >> >> >> >> >> >> >> Garth
>> >> > > >> >> >> >> >> >> >
>> >> > > >> >> >> >> >> >> > Are user-defined functions ever used without
>> >> > > >> >> >> >> >> >> > being related to a particular element/function
>> >> > > >> >> >> >> >> >> > space?
>> >> > > >> >> >> >> >> >> >
>> >> > > >> >> >> >> >> >> > It don't think it will be very clumsy. The
>> >> > > >> >> >> >> >> >> > clumsy thing will be to (in C++) get from
>> >> > > >> >> >> >> >> >> > something compiled by a form compiler to a
>> >> > > >> >> >> >> >> >> > FunctionSpace.
>> >> > > >> >> >> >> >> >> >
>> >> > > >> >> >> >> >> >> > If we can make that operation smooth, then
>> >> > > >> >> >> >> >> >> > creating (user-defined) functions will be very
>> >> > > >> >> >> >> >> >> > simple and convenient. One just needs to supply
>> >> > > >> >> >> >> >> >> > the variable V holding the function space.
>> >> > > >> >> >> >> >> >> >
>> >> > > >> >> >> >> >> >> > The current way of extracting function space
>> >> > > >> >> >> >> >> >> > data from the form is not very nice (in C++).
>> >> > > >> >> >> >> >> >> > What would be the optimal way to initialize a
>> >> > > >> >> >> >> >> >> > FunctionSpace in C++? We could think of
>> >> > > >> >> >> >> >> >> > extending the code generation to generate code
>> >> > > >> >> >> >> >> >> > that makes this convenient.
>> >> > > >> >> >> >> >> >>
>> >> > > >> >> >> >> >> >> The current way of extracting function space data
>> >> > > >> >> >> >> >> >> from the form is not very nice in Python either,
>> >> > > >> >> >> >> >> >> since it doesn't work with compiled functions.
>> >> > > >> >> >> >> >> >> (Never mind that the current code is FFC-specific,
>> >> > > >> >> >> >> >> >> this will be the same with UFL).
>> >> > > >> >> >> >> >> >>
>> >> > > >> >> >> >> >> >> Using Python functors can easily make the assembly
>> >> > > >> >> >> >> >> >> slower than solving the linear system, so it's not
>> >> > > >> >> >> >> >> >> really interesting to do in real applications...
>> >> > > >> >> >> >> >> >>
>> >> > > >> >> >> >> >> >> To make a function object that is both of a C++
>> >> > > >> >> >> >> >> >> subclass of dolfin::Function and of the Python
>> >> > > >> >> >> >> >> >> class ufl.Function, we can't use the fixed
>> >> > > >> >> >> >> >> >> multiple inheritance
>> >> > > >> >> >> >> >> >> solution in the current PyDOLFIN.
>> >> > > >> >> >> >> >> >>
>> >> > > >> >> >> >> >> >> We would have to define a new class dynamically in
>> >> > > >> >> >> >> >> >> python, inheriting from both ufl.Function and the
>> >> > > >> >> >> >> >> >> freshly compiled C++ Function subclass. After all
>> >> > > >> >> >> >> >> >> this work cleaning up the Function class
>> >> > > >> >> >> >> >> >> hierarchy, is that really something you want?
>> >> > > >> >> >> >> >> >>
>> >> > > >> >> >> >> >> >> I'm not sure if that is even possible to do while
>> >> > > >> >> >> >> >> >> maintaining efficiency, with cross-language
>> >> > > >> >> >> >> >> >> inheritance and SWIG directors and all that.
>> >> > > >> >> >> >> >> >>
>> >> > > >> >> >> >> >> >> If anyone has another solution, I'm very
>> >> > > >> >> >> >> >> >> interested in hearing it! Otherwise, I'm all for
>> >> > > >> >> >> >> >> >> keeping the ufl.Function objects used in form
>> >> > > >> >> >> >> >> >> definition separated from dolfin.Function objects
>> >> > > >> >> >> >> >> >> used in assembly.
>> >> > > >> >> >> >> >> >
>> >> > > >> >> >> >> >> > I agree with Martin that we need to have a solution
>> >> > > >> >> >> >> >> > for PyDOLFIN users that does not depend on using
>> >> > > >> >> >> >> >> > python functors, as it will take forever for a
>> >> > > >> >> >> >> >> > complex form together with a moderate mesh to just
>> >> > > >> >> >> >> >> > assemble the form.
>> >> > > >> >> >> >> >> >
>> >> > > >> >> >> >> >> > Is it possible to let compile_functions compile a
>> >> > > >> >> >> >> >> > cpp function, with a FunctionSpace and all, instead
>> >> > > >> >> >> >> >> > of a mesh as it is today. Then after doing
>> >> > > >> >> >> >> >>
>> >> > > >> >> >> >> >> If you have a dolfin::FunctionSpace object already,
>> >> > > >> >> >> >> >> there's no reason compile_functions can't take this
>> >> > > >> >> >> >> >> instead of dolfin::Mesh. That's exactly the same and
>> >> > > >> >> >> >> >> no problem at all.
>> >> > > >> >> >> >> >>
>> >> > > >> >> >> >> >> > this compile_function extract the element, and
>> >> > > >> >> >> >> >> > instantiate a UFL/FFC/PyFunction-function, and
>> >> > > >> >> >> >> >> > "attach" the compiled version to it. This
>> >> > > >> >> >> >> >>
>> >> > > >> >> >> >> >> What I state above is that this "attachment" must be
>> >> > > >> >> >> >> >> done with dynamic creation of a new class with
>> >> > > >> >> >> >> >> multiple inheritance. And I am unsure whether this
>> >> > > >> >> >> >> >> will work out properly with SWIG directors etc. I
>> >> > > >> >> >> >> >> believe it _may_ work, but I don't dare to keep my
>> >> > > >> >> >> >> >> hopes up :-)
>> >> > > >> >> >> >> >
>> >> > > >> >> >> >> > Ok, I get it. For a moment I thought we could get away
>> >> > > >> >> >> >> > by defineing our own PyDOLFIN::Function class that
>> >> > > >> >> >> >> > could inherit from UFL/FFC, and then have a
>> >> > > >> >> >> >> > cpp_Function, but I realise this will not work.
>> >> > > >> >> >> >> >
>> >> > > >> >> >> >> >> See the attached python file for a prototype of
>> >> > > >> >> >> >> >> dynamic class creation with multiple inheritance
>> >> > > >> >> >> >> >> using pure python classes. (I think this is called
>> >> > > >> >> >> >> >> "aspect oriented programming" by some people)
>> >> > > >> >> >> >> >>
>> >> > > >> >> >> >> >> > can be used to define forms, but more important it
>> >> > > >> >> >> >> >> > can be handed to the python assembly that check if
>> >> > > >> >> >> >> >> > the function has a compiled version attached to it
>> >> > > >> >> >> >> >> > and send this to the cpp_assembler?
>> >> > > >> >> >> >> >>
>> >> > > >> >> >> >> >> If the "attachment" is anything other than
>> >> > > >> >> >> >> >> inheritance, it will have to be checked with manually
>> >> > > >> >> >> >> >> written python code _everywhere_ a dolfin::Function
>> >> > > >> >> >> >> >> is expected... We can't have one kind of functions
>> >> > > >> >> >> >> >> for assembly and one for other stuff.
>> >> > > >> >> >> >> >
>> >> > > >> >> >> >> > Ok, I guess we have three different cases:
>> >> > > >> >> >> >> >
>> >> > > >> >> >> >> > 1) PyFunctions inherting from both UFL/FFC and
>> >> > > >> >> >> >> > cpp_Function as today, taking a functionsspace in its
>> >> > > >> >> >> >> > constructor. This will work with both user defined and
>> >> > > >> >> >> >> > discrete functions, more or less as we have it today.
>> >> > > >> >> >> >> >
>> >> > > >> >> >> >> > 2) The special functions, MeshSize, etc, can also be
>> >> > > >> >> >> >> > defined in the same way as now, right?
>> >> > > >> >> >> >> >
>> >> > > >> >> >> >> > 3) Using compile_functions, that creates a multi
>> >> > > >> >> >> >> > inheritance object that can be sent to any function
>> >> > > >> >> >> >> > expecting a cpp_Function, without manually extending
>> >> > > >> >> >> >> > the python interface.
>> >> > > >> >> >> >>
>> >> > > >> >> >> >> I'm with you up to this point.
>> >> > > >> >> >> >>
>> >> > > >> >> >> >> > Could the last be done by letting compile_function
>> >> > > >> >> >> >> > create a muliti inheritance Function. Instantiate the
>> >> > > >> >> >> >> > cpp_one with the function space and by that creating a
>> >> > > >> >> >> >> > dummy cpp_function. Then "attach" the compiled
>> >> > > >> >> >> >> > function to a protected attribute and define eval, by
>> >> > > >> >> >> >> > overloading it in python. This will then just call the
>> >> > > >> >> >> >> > attached and compiled cpp_functions eval.
>> >> > > >> >> >> >>
>> >> > > >> >> >> >> What you describe here sounds like the envelope-letter
>> >> > > >> >> >> >> design that was just _removed_ from dolfin.
>> >> > > >> >> >> >
>> >> > > >> >> >> > Yes, but only for compiled functions in Python. No other
>> >> > > >> >> >> > places.
>> >> > > >> >> >> >
>> >> > > >> >> >> >> What I'm suggesting is that
>> >> > > >> >> >> >> compile_functions dynamically creates a Python class
>> >> > > >> >> >> >> that inherits from ufl.Function and the freshly compiled
>> >> > > >> >> >> >> C++ class, which is a dolfin::Function subclass. Then it
>> >> > > >> >> >> >> can construct an object of this new class, passing a
>> >> > > >> >> >> >> FunctionSpace object given by the user to the
>> >> > > >> >> >> >> dolfin::Function constructor, and an ufl.FiniteElement
>> >> > > >> >> >> >> to the ufl.Function constructor.
>> >> > > >> >> >> >
>> >> > > >> >> >> > This sounds doable. I realize now that this was what you
>> >> > > >> >> >> > were talking about in your previous emails, but I did not
>> >> > > >> >> >> > get it until now ;)
>> >> > > >> >> >> >
>> >> > > >> >> >> >> This of course requires that dolfin.FunctionSpace
>> >> > > >> >> >> >> is a Python subclass of dolfin::FunctionSpace with an
>> >> > > >> >> >> >> additional ufl.FiniteElement member variable. Using jit,
>> >> > > >> >> >> >> dolfin.FunctionSpace can compile the ufc::finite_element
>> >> > > >> >> >> >> and ufc::dof_map classes it needs from an
>> >> > > >> >> >> >> ufl.FiniteElement. And then there's the issue of reusing
>> >> > > >> >> >> >> dofmaps, where DofMapSet enters the play...
>> >> > > >> >> >> >
>> >> > > >> >> >> > Do we need to jit compile ufc::finite_elements and
>> >> > > >> >> >> > ufc::dof_maps from the created ufl.FiniteElement? What
>> >> > > >> >> >> > about the one that follows from the FunctionSpace?
>> >> > > >> >> >>
>> >> > > >> >> >> I was thinking about when _constructing_ the FunctionSpace.
>> >> > > >> >> >> Just like PyDOLFIN uses jit in Function.__init__ today.
>> >> > > >> >> >
>> >> > > >> >> > Ok, something like:
>> >> > > >> >> >
>> >> > > >> >> > # Note pseudo code...
>> >> > > >> >> > class FunctionSpace(cpp_FunctionSpace):
>> >> > > >> >> > def __init__(self,ufl_finite_element,mesh):
>> >> > > >> >> > ufc_finit_element = jit(ufl_finite_element)
>> >> > > >> >> > form = ufl.FiniteElement*ufl.TestFunction*ufl.dx
>> >> > > >> >> > dof_map = jit(form)
>> >> > > >> >> >
>> >> > > >> >> > cpp_FucntionSpace.__init__(mesh,ufc_FinitElement,dof_map)
>> >> > > >> >> > self._UFL_FiniteElement = ufl_finite_element
>> >> > > >> >> >
>> >> > > >> >> > def UFL_FiniteElement(self):
>> >> > > >> >> > return self._UFL_FiniteElement
>> >> > > >> >> >
>> >> > > >> >> > By this the the ufc_element, ufl_element, the dofmaps and
>> >> > > >> >> > the mesh, are cached in the FunctionSpace.
>> >> > > >> >> >
>> >> > > >> >> > The Function would then be something like:
>> >> > > >> >> >
>> >> > > >> >> > class Function(cpp_Function,ufl.Function):
>> >> > > >> >> > def __init__(self,function_space):
>> >> > > >> >> > cpp_Function.__init__(function_space):
>> >> > > >> >> >
>> >> > > >> >> > ufl.Function.__init__(function_space.UFL_FiniteElement())
>> >> > > >> >> >
>> >> > > >> >> > and dynamical created code in compile_functions()
>> >> > > >> >> >
>> >> > > >> >> > class MyFunction(MyCompiledFunction,ufl.Function):
>> >> > > >> >> > def __init__(self,function_space):
>> >> > > >> >> > MyCompiledFunction.__init__(function_space):
>> >> > > >> >> >
>> >> > > >> >> > ufl.Function.__init__(function_space.UFL_FiniteElement())
>> >> > > >> >>
>> >> > > >> >> Something like that, yes. This is close to the current
>> >> > > >> >> PyDOLFIN.
>> >> > > >> >>
>> >> > > >> >> But FunctionSpace might become a subclass of ufl.FunctionSpace
>> >> > > >> >> if we introduce that in UFL, and it should be possible to get
>> >> > > >> >> cached initialized and renumbered DofMaps from a DofMapSet.
>> >> > > >> >>
>> >> > > >> >> Since a DofMapSet will typically be initialized with a Form,
>> >> > > >> >> a Form depends on a Function, and a Function depends on
>> >> > > >> >> a FunctionSpace which should be initialized by the DofMapSet,
>> >> > > >> >> we have a cirular dependency right there.
>> >> > > >> >
>> >> > > >> > But won't you have this circular dependency in UFL already?
>> >> > > >>
>> >> > > >> In UFL this is simple:
>> >> > > >>
>> >> > > >> FiniteElement depends on nothing
>> >> > > >> Function depends on FiniteElement
>> >> > > >> Form depends on Function
>> >> > > >
>> >> > > > I ment for a potential FunctionSpace class in UFL.
>> >> > >
>> >> > > Then it is simply:
>> >> > >
>> >> > > FiniteElement depends on nothing
>> >> > > FunctionSpace depends on FiniteElement
>> >> > > Function depends on FunctionSpace
>> >> > > Form depends on Function
>> >> > >
>> >> > > >> The relation between UFL and UFC code is (at a certain level)
>> >> > > >> simple:
>> >> > > >>
>> >> > > >> ufc::* is generated by form compilers from ufl.* (equivalently
>> >> > > >> ffc.*) once generated, ufc::* depends on nothing
>> >> > > >>
>> >> > > >> In DOLFIN (C++) it is also simple:
>> >> > > >>
>> >> > > >> dolfin::* does not depend directly on ufl.* (equivalently
>> >> > > >> ffc.*) dolfin::* depends on ufc::*
>> >> > > >>
>> >> > > >> PyDOLFIN could (should!) be kept simple. I've been using PyDOLFIN
>> >> > > >> without the FFC-dependent multiple inheritance stuff all the time
>> >> > > >> with the dolfin.cpp_* classes.
>> >> > > >
>> >> > > > Me too.
>> >> > > >
>> >> > > >> I believe that's also how it must be
>> >> > > >> done if you have external UFC code, e.g. precompiled in a library
>> >> > > >> or manually written.
>> >> > > >
>> >> > > > Agree.
>> >> > > >
>> >> > > >> So no matter what, it should at least be possible to avoid
>> >> > > >> relying on the multiple inheritance and JIT in PyDOLFIN.
>> >> > > >
>> >> > > > and more or less have the possibilities we have today. I agree.
>> >> > > >
>> >> > > > Johan
>> >> > >
>> >> > > Seems at least we're on the same page here.
>> >> >
>> >> > I've been in meetings the whole day and it took me a while to get
>> >> > through the discussion... :-)
>> >> >
>> >> > I agree that life would be easier if we did not need to worry about
>> >> > integrating UFL, UFC, and DOLFIN, but I think we should. I don't think
>> >> > a user should need to worry about the relations between all the
>> >> > different flavours of for example the finite element abstractions. We
>> >> > have quite a few:
>> >> >
>> >> > ufl.FiniteElement
>> >> > ufc::finite_element
>> >> > dolfin::FiniteElement
>> >> > dolfin.FiniteElement
>> >> > FIAT.FiniteElement
>> >> > (ffc.FiniteElement)
>> >> > ...
>> >> >
>> >> > DOLFIN plays two roles here:
>> >> >
>> >> > 1. It functions as a user interface/problem-solving environment and as
>> >> > such should present a clean and simple interface where only one of
>> >> > the above flavours should be visible.
>> >> >
>> >> > 2. It provides a general assembler, and as such should provide an
>> >> > assembly algorithm that just works with ufc:: types (+ mesh and
>> >> > linear algebra).
>> >> >
>> >> > So, we need to provide (1) for general use (and make it efficient) but
>> >> > also allow (2) for experts.
>> >> >
>> >> > So far, I like Martin's idea with dynamic inheritance to solve (1).
>> >>
>> >> So you don't like the way we have it now, where a jit compiled function
>> >> can't be used in a form statement? Or are you fine with it? If you are
>> >> fine with it we do not need the dynamics inheritance.
>> >>
>> >> Johan
>> >
>> > I think that there should be an easier way to use jit-compiled
>> > functions. The optimal would be if one could do something like
>> >
>> > f = Function(V, cppstring)
>>
>> That should be possible to do with some Python tricks (metaclasses).
>
> Isn't the above example only possible with an envelope design? I.e. you
> compile the string and get a cpp_function.
>
> A metaclass kicks in when you creates a python class. You could e.g.
>
> __metaclass__ = compiler_class_builder
> MyFunction(Function):
> cppstring = "whatever"
>
> and the metaclass compiler_class_builder can compile the cppstring while
> createing the class, and the instantiation would be:
>
> f = MyFunction(V)
>
> That still does not help us using that class for dynamical inheritance.
>
> We could use:
>
> f = CompiledFunction(V,cppstring)
>
> which resembles what we have today. Here CompiledFunction is a function not a
> class. Maybee still not what we want?
>
> Johan
Using CompiledFunction like this is close enough if we can't use metaclasses.
But then again, it's much faster to compile multiple functions simultaneously
like compile_functions can do today.
I haven't actually used metaclasses for anything useful, but the point is
that you can return an object of a different class than Function with
the syntax "f = Function(...)", right?
Since Function here is a manually implemented Python class, it can
use the metaclass mechanism to call up the dynamic class creation
if it gets a cppstring and return an object of this class instead.
--
Martin
Follow ups
References