Skip to content

Commit

Permalink
Add rator and rands transform options to etuplize
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonwillard committed Mar 26, 2022
1 parent 35d760c commit c8a45ea
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 7 deletions.
36 changes: 29 additions & 7 deletions etuples/dispatch.py
Expand Up @@ -102,8 +102,15 @@ def apply_ExpressionTuple(rator, rands):


@dispatch(object)
def etuplize(x, shallow=False, return_bad_args=False, convert_ConsPairs=True):
"""Return an expression-tuple for an object (i.e. a tuple of rand and rators).
def etuplize(
x,
shallow=False,
return_bad_args=False,
convert_ConsPairs=True,
rator_transform_fn=lambda x: x,
rands_transform_fn=lambda x: x,
):
r"""Return an expression-tuple for an object (i.e. a tuple of rand and rators).
When evaluated, the rand and rators should [re-]construct the object. When
the object cannot be given such a form, it is simply converted to an
Expand All @@ -112,12 +119,18 @@ def etuplize(x, shallow=False, return_bad_args=False, convert_ConsPairs=True):
Parameters
----------
x: object
Object to convert to expression-tuple form.
Object to convert to expression-tuple form.
shallow: bool
Whether or not to do a shallow conversion.
Whether or not to do a shallow conversion.
return_bad_args: bool
Return the passed argument when its type is not appropriate, instead
of raising an exception.
Return the passed argument when its type is not appropriate, instead
of raising an exception.
rator_transform_fn: callable
A function to be applied to each rator/CAR element of each constructed
`ExpressionTuple`. The returned value is used in place of the input, and
the function is not applied to existing `ExpressionTuple`\s.
rands_transform_fn: callable
The same as `rator_transform_fn`, but for rands/CDR elements.
"""

Expand All @@ -133,7 +146,12 @@ def etuplize_step(
elif (
convert_ConsPairs and x is not None and isinstance(x, (ConsNull, ConsPair))
):
yield etuple(*x)
yield etuple(
*(
(rator_transform_fn(rator(x)),)
+ tuple(rands_transform_fn(e) for e in rands(x))
)
)
return

try:
Expand All @@ -148,13 +166,17 @@ def etuplize_step(
else:
raise TypeError(f"x is neither a non-str Sequence nor term: {type(x)}")

op = rator_transform_fn(op)
args = etuple(*tuple(rands_transform_fn(a) for a in args))

if shallow:
et_op = op
et_args = args
else:
et_op = yield etuplize_step(op, return_bad_args=True)
et_args = []
for a in args:

e = yield etuplize_step(
a, return_bad_args=True, convert_ConsPairs=False
)
Expand Down
18 changes: 18 additions & 0 deletions tests/test_dispatch.py
Expand Up @@ -93,6 +93,24 @@ def test_etuplize():
assert type(etuplize(node_2)[-1]) == tuple
assert etuplize(node_2, shallow=True) == etuple(op_1, node_1, 3, ())

def rands_transform(x):
if x == 1:
return 4
return x

assert etuplize(node_2, rands_transform_fn=rands_transform) == etuple(
op_1, etuple(op_2, 4, 2), 3, ()
)

def rator_transform(x):
if x == op_1:
return op_2
return x

assert etuplize(node_2, rator_transform_fn=rator_transform) == etuple(
op_2, etuple(op_2, 1, 2), 3, ()
)


def test_unification():
from cons import cons
Expand Down

0 comments on commit c8a45ea

Please sign in to comment.