8451 / labrea

A framework for declarative, functional dataset definitions.
MIT License
11 stars 0 forks source link

Add ability to "map" over a series of options #4

Closed austinwarner-8451 closed 1 month ago

austinwarner-8451 commented 3 months ago

There are situations where evaluating a dataset (or other Evaluatable) multiple times with different inputs can be useful. Currently, this is only possible at the top-level, and cannot be expressed within labrea. The proposal is to create a Map type, that acts like the builtin map (or a list comprehension)

from labrea import dataset, Option, Map

@dataset
def square(x: float = Option('X')) -> float:
  return x**2

squares = Map(square).over({'X': Option('X_LIST')})

squares({'X_LIST': list(range(5))}) == [0, 1, 4, 9, 16]

Maps can be chained together to create nested lists

@dataset
def add(x: float = Option('X'), y: float = Option('Y')) -> float:
  return x + y

added_nested = Map(add).over({'X': Option('X_LIST')}).over({'Y': Option('Y_LIST')})

added_nested({'X_LIST': [1, 2], 'Y_LIST': [10, 20]}) == [[11, 12], [21, 22]]

Or we can map over multiple at once for a flattened list

added_flat = Map(add).over({'X': Option('X_LIST'), 'Y': Option('Y_LIST')})

added_flat({'X_LIST': [1, 2], 'Y_LIST': [10, 20]}) == [11, 21, 12, 22]

Similarly to Map, there should also be a DictMap that retains the options used to generate each result. This will require that the keys be hashable. Probably should use frozendict as the keys.

from labrea import DictMap

added_dict = DictMap(add).over({'X': Option('X_LIST'), 'Y': Option('Y_LIST')})

added_dict = {
  frozendict({'X': 1, 'Y': 10})): 11,
  frozendict({'X': 1, 'Y': 11})): 12,
  frozendict({'X': 2, 'Y': 20})): 21,
  frozendict({'X': 2, 'Y': 20})): 22
}
austinwarner-8451 commented 3 months ago

Worth considering here, if we are going to do add a Map type, would it make sense to also add Filter and Fold/Reduce types that recreate the builtin filter and functools.reduce?

austinwarner-8451 commented 2 months ago

Had the realization that this "Map" is not fully analogous to the built in map. I think I will rename it to Iterate.

In terms of filter/reduce, this is something that can be pretty easily accomplished with the .apply method proposed is #6

austinwarner-8451 commented 1 month ago

Coming in Labrea 2.0, will be named Map