curryparty 0.3.0__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: curryparty
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Python playground to learn lambda calculus
5
5
  Author: Antonin P
6
6
  Author-email: Antonin P <antonin.peronnet@telecom-paris.fr>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "curryparty"
3
- version = "0.3.0"
3
+ version = "0.3.1"
4
4
  description = "Python playground to learn lambda calculus"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -20,4 +20,5 @@ dev = [
20
20
  "marimo>=0.18.4",
21
21
  "polars>=1.36.1",
22
22
  "ruff>=0.14.8",
23
+ "tuna>=0.5.11",
23
24
  ]
@@ -44,7 +44,7 @@ class Term:
44
44
  return Term(compose(self.nodes, other.nodes))
45
45
 
46
46
  def beta(self) -> Optional["Term"]:
47
- candidates = find_redexes(self.nodes)
47
+ candidates = find_redexes(self.nodes).first().collect()
48
48
  if len(candidates) == 0:
49
49
  return None
50
50
  _redex, lamb, b = candidates.row(0)
@@ -72,14 +72,14 @@ class Term:
72
72
  Generates an HTML representation that toggles visibility between
73
73
  a static state and a SMIL animation on hover using pure CSS.
74
74
  """
75
- candidates = find_redexes(self.nodes)
75
+ candidates = find_redexes(self.nodes).first().collect()
76
76
  if len(candidates) == 0:
77
77
  return self._repr_html_()
78
78
 
79
79
  _redex, lamb, b = candidates.row(0)
80
80
  new_nodes = beta_reduce(self.nodes, lamb, b)
81
- vars = find_variables(self.nodes, lamb)["id"]
82
- b_subtree = subtree(self.nodes, b)
81
+ vars = find_variables(self.nodes, lamb).collect()["id"]
82
+ b_subtree = subtree(self.nodes, b).collect()
83
83
  height = min(compute_height(self.nodes), compute_height(new_nodes)) * 2
84
84
  if count_variables(self.nodes) == 0:
85
85
  return "no width"
@@ -1,6 +1,5 @@
1
1
  import polars as pl
2
2
  from polars import Schema, UInt32
3
- from polars.functions.lazy import coalesce
4
3
 
5
4
  SCHEMA = Schema(
6
5
  {
@@ -21,7 +20,7 @@ def _shift(nodes: pl.DataFrame, offset: int):
21
20
  )
22
21
 
23
22
 
24
- def compose(f: pl.DataFrame, x: pl.DataFrame):
23
+ def compose(f: pl.DataFrame, x: pl.DataFrame) -> pl.DataFrame:
25
24
  n = len(f)
26
25
  return pl.concat(
27
26
  [
@@ -35,31 +34,32 @@ def compose(f: pl.DataFrame, x: pl.DataFrame):
35
34
  )
36
35
 
37
36
 
38
- def find_redexes(nodes: pl.DataFrame):
39
- parents = nodes.filter(pl.col("ref").is_null())
37
+ def find_redexes(nodes: pl.DataFrame) -> pl.LazyFrame:
40
38
  return (
41
- parents.join(nodes, left_on="id", right_on=pl.col("id") - 1, suffix="_child")
39
+ nodes.lazy()
42
40
  .filter(
43
41
  pl.col("arg").is_not_null(),
44
- pl.col("ref_child").is_null(),
45
- pl.col("arg_child").is_null(),
42
+ pl.col("arg").shift(-1).is_null(),
43
+ pl.col("ref").shift(-1).is_null(),
46
44
  )
47
- .select(redex="id", lamb="id_child", b="arg")
45
+ .select("id", lamb=pl.col("id") + 1, arg="arg")
48
46
  )
49
47
 
50
48
 
51
- def find_variables(nodes: pl.DataFrame, lamb: int):
52
- return nodes.filter(pl.col("ref") == lamb).select("id", replaced=True)
49
+ def find_variables(nodes: pl.DataFrame, lamb: int) -> pl.LazyFrame:
50
+ return nodes.lazy().filter(pl.col("ref") == lamb).select("id", replaced=True)
53
51
 
54
52
 
55
- def subtree(nodes: pl.DataFrame, root: int) -> pl.DataFrame:
53
+ def subtree(nodes: pl.DataFrame, root: int) -> pl.LazyFrame:
54
+ refs = nodes["ref"]
55
+ args = nodes["arg"]
56
56
  rightmost = root
57
57
  while True:
58
- ref = nodes["ref"][rightmost]
59
- arg = nodes["arg"][rightmost]
58
+ ref = refs[rightmost]
60
59
  if ref is not None:
61
- return nodes.filter(pl.col("id").is_between(root, rightmost))
60
+ return nodes.lazy().filter(pl.col("id").is_between(root, rightmost))
62
61
 
62
+ arg = args[rightmost]
63
63
  rightmost = arg if arg is not None else rightmost + 1
64
64
 
65
65
 
@@ -77,52 +77,60 @@ def beta_reduce(nodes: pl.DataFrame, lamb: int, b: int) -> pl.DataFrame:
77
77
  a = lamb + 1
78
78
 
79
79
  vars = find_variables(nodes, lamb)
80
+
80
81
  b_subtree = subtree(nodes, b)
81
82
 
82
83
  b_subtree_duplicated = b_subtree.join(vars, how="cross", suffix="_major")
83
- rest_of_nodes = nodes.join(b_subtree, on="id", how="anti").with_columns(
84
- arg=pl.col("arg").replace(redex, a)
84
+ rest_of_nodes = (
85
+ nodes.lazy()
86
+ .join(b_subtree, on="id", how="anti")
87
+ .with_columns(arg=pl.col("arg").replace(redex, a))
85
88
  )
86
89
 
87
90
  new_nodes = (
88
91
  pl.concat(
89
92
  [b_subtree_duplicated, rest_of_nodes],
90
- how="diagonal_relaxed",
93
+ how="diagonal",
91
94
  )
92
95
  .join(vars, left_on="id", right_on="id", how="anti")
93
96
  .join(vars, left_on="arg", right_on="id", how="left", suffix="_arg")
94
97
  .join(vars, left_on="ref", right_on="id", how="left", suffix="_ref")
95
98
  .filter(
96
- ~pl.col("id").is_between(redex, lamb),
99
+ ~(pl.col("id").eq(redex) | pl.col("id").eq(lamb)),
97
100
  )
98
101
  .select(
99
102
  bid=_generate_bi_identifier("id_major", "id"),
100
103
  bid_ref=_generate_bi_identifier("id_major", "ref"),
101
104
  bid_ref_fallback=pl.struct(major="ref", minor="ref"),
102
105
  bid_arg=_generate_bi_identifier(
103
- "id_major", "arg", minor_replacement=pl.when("replaced_arg").then(b)
106
+ # TODO: document and simplify to avoid "minor_replacement"
107
+ "id_major",
108
+ "arg",
109
+ minor_replacement=pl.when("replaced_arg").then(b),
104
110
  ),
105
111
  )
106
112
  .sort("bid")
107
113
  .with_row_index("id")
108
- )
114
+ ).cache()
109
115
 
110
116
  return (
111
117
  new_nodes.join(
112
118
  new_nodes.select(bid_ref="bid", ref="id"),
113
119
  on="bid_ref",
114
120
  how="left",
121
+ maintain_order="left",
115
122
  )
116
123
  .join(
117
124
  new_nodes.select(bid_ref_fallback="bid", ref_fallback="id"),
118
125
  on="bid_ref_fallback",
119
126
  how="left",
127
+ maintain_order="left",
120
128
  )
121
129
  .join(
122
130
  new_nodes.select(bid_arg="bid", arg="id"),
123
131
  on="bid_arg",
124
132
  how="left",
133
+ maintain_order="left",
125
134
  )
126
135
  .select("id", ref=pl.coalesce("ref", "ref_fallback"), arg="arg", bid="bid")
127
- .sort("id")
128
- )
136
+ ).collect()
File without changes