handcalcs icon indicating copy to clipboard operation
handcalcs copied to clipboard

Objects and namespaces for handcalcs

Open maruedt opened this issue 1 year ago • 0 comments

First of all, thank you for the very exciting concept of handcalcs and the implementation of the library. I have been playing around with it for the last couple of months and will start to use it for exercise solutions for the students.

During this initial phase, I had a few of problems mainly associated with the limitations of rendering latex code (e.g. $\dot{V}$, $\Delta h$) and clashes of Python programming syntax with handcalcs (e.g. using print statements, lambda). I think, most of these types of issues have already been raised previously (latex rendering #97, #101, #110, etc.; Python syntax clashes #106, #90, also how $\lambda$ is written #92) and can be dealt with. However, I have been thinking about how the library could be more easily adapted to those edge cases and I think, it could make sense to implement an OO intermittent framework between the user python code and the latex representation. Below, I put together my thoughts on the topic. Sorry, the text became a bit longer than I originally intended.

Symbol renderer object

My first proposal would be to implement a symbol rendering object, which stores the information on symbols in an object oriented way. I would argue that the symbol rendering object should have 3 properties associated to it:

  • Latex symbol definition (e.g. r'\dot{V}')
  • Numerical value (might also be something like an object (Numpy array, value/unit combination of pint/forallpeople))
  • Numerical display definition

While one might normally use the standard syntax (%%render, @handcalc), this syntax could be useful for symbols/values with special notations.

Example usage:

from handcalcs import SymbolRenderer

Vdot = SymbolRenderer(symbol=r'\dot{V}', value=2*ureg.m**3/ureg.s, numerical_display='{self.value.__str__}')
Vdot.render()

As far as I can see this type of OO syntax could work well for parameter definitions. I am however unsure, how complete expressions (calculations) would be handled most easily... Up to now, the most appropriate ideas I could think of were:

  • implement a method call for assigning equations, e.g. Vdot.assign(a + b).render(format='long') which is rendered as e.g. $\dot{V} = a + b=1 \mathrm{m^3}/\mathrm{s}+ 1 \mathrm{m^3}/\mathrm{s} = 2 \mathrm{m^3}/\mathrm{s}$. There are a number of variations to this concept, notably: assignment during initialization, assignment to property (Vdot.value = a+b).
  • to use SymbolRenderer as a context manager (which seems a bit elaborate)
  • to assign a string to the value property, which is evaluated and rendered during rendering of the SymbolRenderer (which however might affect autocompletion and seems rather unintuitive).

Namespaces

My second proposal is to implement a namespace/object which renders a line of code once a variable is assigned to the namespace:

from handcalcs import RenderedSpace
ex1 = RenderedSpace()

def fun():
    a = 1+2 # not rendered
    ex1.a = a # rendered

ex2 = RenderedSpace()
ex2.b = 2
ex2.c = 5
print(f'We now want to add a, b and c={ex2.c}')
ex2.d = ex2.a + ex2.b + ex2.c  # throws an error since we have forgotten to define ex2.a

This type of construct could be useful in a number of situations:

  • Allows to intermix 'normal' programming with lines of code which one would actually like to have rendered.
  • Makes it easier to scope variables correctly. An example where this might be useful is in education. Often you have multiple exercises per assignment with similar types of exercises and variable names. Up to now, I have been using functions to assert that one exercise does not spill into the next. However, a mechanism similar to the one shown above would be more convenient.
  • Especially neat seems to me the option to have a context manager based on the namespace:
with ex2('param'):  
    # rendered and stored in namespace ex2
    a = 1
    b = 2
    c = 3

print('this is not rendered')

with ex2('long'):
    # rendered and stored in namespace ex2
    d = a + b + c

What are your thoughts about the proposals? Would such an extension of handcalcs be feasible and how much would the internal structures have to be adjusted? I would be happy to get some feedback on the ideas.

maruedt avatar Jul 25 '22 14:07 maruedt