[ROOT] Comments on TFormula/Compile/DefinedValue

From: Ole Hansen (ole@jlab.org)
Date: Tue Jun 10 2003 - 23:38:03 MEST


I have lost a bit of time recently due to some features of the TFormula 
class which do not seem to be adequately documented.  So I thought I'd 
summarize them here for everyone's reference.  These comments
refer to ROOT 3.05/04, but should apply equally to virtually all ROOT
versions back to 2.x.

- TFormula violates a common good C++ programming practice: Never call a 
  virtual function from a constructor!  TFormula calls the virtual method 
  Compile() in its non-default constructor.  While this is convenient,
  it causes the usual problems associated with such style, viz. unexpected
  and/or incorrect behavior and the need for code duplication in derived
  classes. The source code comments are outright misleading and really 
  should be changed!  Compile() calls Analyze(), which calls 
  DefinedVariable().  DefinedVariable()'s documentation reads 
  "This member function can be  overloaded in derived classes".  
  Good luck doing so - it does not work unless one also re-implements the 
  TFormula constructor in the derived class and calls Compile() from 
  there.  This would be ok (unless  one is a style perfectionist) if 
  only it was properly documented.
  Documentation improvements would be highly welcome.

- DefinedVariable() is supposed to work in conjunction with 
  DefinedValue().  However, it seems that some initialization
  is missing in TFormula::Compile() to make this work reliably.
  While Compile() resets virtually everything else,
  it does _not_ reset the two member variables fNval and 
  fAlreadyFound which control the behavior of the DefinedVariable/
  DefinedValue mechanism.  As a result, re-compiling an object derived
  from TFormula that uses this mechanism may produce unpredicable 
  results.  For instance, suppose DefinedVariable("x") returns 0 when the
  object is constructed. Then some data changes (e.g. a new configuration 
  is loaded) and DefinedVariable("x") now returns 1.  The application 
  recompiles all formulas as a result of the configuration changes, which 
  should take care of things.  Mysteriously, however, some formulas now fail to
  produce sensible results. The reason is that during recompilation the 
  object may think that a variable is already defined when it isn't, 
  or use incorrect indices for variables during evaluation (in the example, 
  DefinedValue(0) might be called to get the value of "x" when 
  the call should be DefinedValue(1)).  Whether or not this occurs depends 
  on the particulars of how DefinedVariable/DefinedValue are implemented 
  and on the expression used.  That fNval and fAlreadyFound are not reset 
  in Compile() looks like a bug that has gone unnoticed so far.
  If it is, could it be corrected?  Until it is, people need to work
  around it by implemeting a Compile() method in the derived class to 
  reset those status variables.

Best regards,

Ole Hansen
Jefferson Lab
  
  



This archive was generated by hypermail 2b29 : Thu Jan 01 2004 - 17:50:12 MET