Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Syntactic Sugar for Templated Classes #13

Closed
kwabenantim opened this issue Mar 11, 2024 · 5 comments
Closed

Syntactic Sugar for Templated Classes #13

kwabenantim opened this issue Mar 11, 2024 · 5 comments
Assignees

Comments

@kwabenantim
Copy link
Member

kwabenantim commented Mar 11, 2024

Summary

Add a way to use instantiated C++ template classes from Python that looks a bit more like the C++ syntax.

For example:

# This:
simulation = OffLatticeSimulation2_2(cell_population)

# would become:
simulation = OffLatticeSimulation[2][2](cell_population)
# and this:
cell_population = VertexBasedCellPopulation2(mesh, cells)

# would become:
cell_population = VertexBasedCellPopulation[2](mesh, cells)
@kwabenantim
Copy link
Member Author

One possible solution with dicts:

OffLatticeSimulation = {2: {2: OffLatticeSimulation2_2}}

VertexBasedCellPopulation = {2: VertexBasedCellPopulation2}

@kwabenantim kwabenantim self-assigned this Mar 11, 2024
@kwabenantim
Copy link
Member Author

Perhaps override [] and use numpy-like indexing so we can have:

simulation = OffLatticeSimulation[2, 2](cell_population)

@mirams
Copy link
Member

mirams commented Mar 26, 2024

I like that, as long as it isn't too confusing in looking like an array, but makes a lot of sense compared to the ones above!

@kwabenantim
Copy link
Member Author

kwabenantim commented Sep 23, 2024

One possible solution could be:

class TemplateClassDict:
  def __init__(self, template_dict):
    self._dict = template_dict

  def __getitem__(self, key):
      return self._dict[key]

OffLatticeSimulation = TemplateClassDict(
  {
    (2, 2): OffLatticeSimulation_2_2,
    (3, 3): OffLatticeSimulation_3_3,
  }
)

Which can be used like

simulation = OffLatticeSimulation[2, 2](cell_population)

@kwabenantim
Copy link
Member Author

kwabenantim commented Oct 1, 2024

This has been implemented as:

class TemplateClassDict:

    def __init__(self, template_dict):
        self._dict = {}
        for arg_tuple, cls in template_dict.items():
            if not inspect.isclass(cls):
                raise TypeError("Expected class, got {}".format(type(cls)))
            if not isinstance(arg_tuple, Iterable):
                arg_tuple = (arg_tuple,)
            key = tuple(
                arg.__name__ if inspect.isclass(arg) else str(arg) for arg in arg_tuple
            )
            self._dict[key] = cls

    def __getitem__(self, arg_tuple):
        if not isinstance(arg_tuple, Iterable):
            arg_tuple = (arg_tuple,)
        key = tuple(
            arg.__name__ if inspect.isclass(arg) else str(arg) for arg in arg_tuple
        )
        return self._dict[key]

An example of this is:

CellsGenerator = TemplateClassDict(
  {
    ("AlwaysDivideCellCycleModel", "2"): CellsGenerator_AlwaysDivideCellCycleModel_2,
    ("AlwaysDivideCellCycleModel", "3"): CellsGenerator_AlwaysDivideCellCycleModel_3,
    ("BernoulliTrialCellCycleModel", "2"): CellsGenerator_BernoulliTrialCellCycleModel_2,
    ("BernoulliTrialCellCycleModel", "3"): CellsGenerator_BernoulliTrialCellCycleModel_3,
  }
)

Which can be used like:

gen = CellsGenerator["AlwaysDivideCellCycleModel", "2"]()  # recommended

# OR
gen = CellsGenerator["AlwaysDivideCellCycleModel", 2]()

# OR
gen = CellsGenerator[AlwaysDivideCellCycleModel, "2"]()

# OR
gen = CellsGenerator[AlwaysDivideCellCycleModel, 2]()

kwabenantim added a commit that referenced this issue Oct 8, 2024
kwabenantim added a commit that referenced this issue Oct 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants