33DynamicExpressions.jl v2.0 introduces support for n-arity operators (nodes with arbitrary numbers of children),
44which required some breaking changes to implement. This guide will help you migrate your code from v1.x to v2.0.
55
6- ## Breaking Changes Summary
6+ ## Summary
77
88- Types
99 - ` Node{T} ` is now ` Node{T,D} ` where ` D ` is the maximum degree
1010 - ` AbstractExpressionNode{T} ` is now ` AbstractExpressionNode{T,D} `
1111 - ` AbstractNode ` is now ` AbstractNode{D} `
12+ - Before, ` Node{T} ` had fields ` l::Node{T} ` and ` r::Node{T} ` .
13+ - Now, the type is ` Node{T,D} ` , and it has the field ` children::NTuple{D,Nullable{Node{T,D}}} ` .
1214- Accessors
1315 - You can now access children by index with ` get_child(tree, i) `
14- - ` tree.l ` should now be written as ` get_child(tree, 1) `
15- - ` tree.r ` should now be written as ` get_child(tree, 2) `
16+ - ` tree.l ` can now be written as ` get_child(tree, 1) `
17+ - ` tree.r ` can now be written as ` get_child(tree, 2) `
1618 - _ note: you can access multiple children with ` get_children(tree, Val(degree)) ` _
1719 - You can now set children by index with ` set_child!(tree, child, i) `
1820 - ` tree.l = child ` should now be written as ` set_child!(tree, child, 1) `
@@ -22,19 +24,31 @@ which required some breaking changes to implement. This guide will help you mig
2224 - ` Node{T}(; op=1, l=x) ` should now be written as ` Node{T}(; op=1, children=(x,)) `
2325 - ` Node{T}(; op=1, l=x, r=y) ` should now be written as ` Node{T}(; op=1, children=(x, y)) `
2426 - You may now use ` Node{T,D}(; op=1, children=(x,)) ` to specify degree other than the default of 2.
25- - Types
26- - Before, ` Node{T} ` had fields ` l::Node{T} ` and ` r::Node{T} ` .
27- - Now, the type is ` Node{T,D} ` , and it has the field ` children::NTuple{D,Nullable{Node{T,D}}} ` .
2827- OperatorEnum
29- - The ` OperatorEnum ` and ` GenericOperatorEnum ` now each use a single ` ops ` field, a tuple of tuples, indexed by arity.
30- - ` operators.unaops ` should now be written as ` operators.ops[1] `
31- - ` operators.binops ` should now be written as ` operators.ops[2] `
32- - However, the properties will be automatically aliased for the time being.
28+ - ` OperatorEnum ` (and ` GenericOperatorEnum ` ) now uses a single ` ops ` field: this is a tuple of tuples, indexed by arity.
29+ - ` operators.unaops ` is now written as ` operators.ops[1] ` , and ` operators.binops ` is now written as ` operators.ops[2] ` .
3330 - ` OperatorEnum(binary_operators=(+, -, *), unary_operators=(sin, cos)) ` can now be written as ` OperatorEnum(2 => (+, -, *), 1 => (sin, cos)) `
3431 - This API permits higher-arity operators: ` OperatorEnum(1 => (sin, cos), 2 => (+, -, *), 3 => (fma, max)) ` .
35- - (Note that the order you pass the pairs is not important.)
3632
37- ## Necessary Changes to Your Code
33+ ## Breaking Changes
34+
35+ The main breaking change is that ` Node{T} ` is now ` Node{T,D} ` where ` D ` is the
36+ ** maximum degree** of any possible node in the tree. ` node.degree ` is _ still_ the same as before,
37+ and is such that ` node.degree <= D ` .
38+
39+ Similarly, ` AbstractExpressionNode{T} ` is now ` AbstractExpressionNode{T,D} ` ,
40+ and ` AbstractNode ` is now ` AbstractNode{D} ` .
41+
42+ Before, ` Node{T} ` had fields ` l::Node{T} ` and ` r::Node{T} ` . Now, it has a single combined
43+ field ` children::NTuple{D,Nullable{Node{T,D}}} ` . This is a tuple of wrapped node objects,
44+ which should be accessed with ` get_child(tree, i) ` and set with ` set_child!(tree, child, i) ` .
45+ However, the old getters and setters will still function for binary trees (` .l ` and ` .r ` ).
46+
47+ You may now use ` Node{T,D}(; op=1, children=(x,)) ` to specify degree other than the default of 2.
48+ However, the default ` Node{T}(; op=1, children=(x,)) ` is still available and will result
49+ in type ` Node{T,2} ` .
50+
51+ ### Necessary Changes to Your Code
3852
3953The main breaking change that requires some modifications is patterns that
4054explicitly match ` tree.degree ` in conditional logic. The ` tree.degree == 0 `
@@ -137,3 +151,25 @@ y = Node{Float64,3}(; feature=2)
137151z = Node{Float64,3}(; feature=3)
138152tree = Node{Float64,3}(; op=1, children=(x, y, z))
139153```
154+
155+ # # OperatorEnum redesign (Non-Breaking)
156+
157+ ` OperatorEnum` (and ` GenericOperatorEnum` ) now uses a single ` ops` field: this is a tuple of tuples, indexed by arity.
158+ ` operators.unaops` is now written as ` operators.ops[1]` , and ` operators.binops` is now written as ` operators.ops[2]` .
159+
160+ However, the properties are aliased, so the old syntax will still work.
161+
162+ Along with this, there is a new API for constructing ` OperatorEnum` s :
163+
164+ ``` julia
165+ # operators = OperatorEnum(binary_operators=(+, -, *), unary_operators=(sin, cos)) # old
166+ operators = OperatorEnum(2 => (+, -, *), 1 => (sin, cos))
167+ ```
168+
169+ This API permits higher- arity operators:
170+
171+ ``` julia
172+ operators = OperatorEnum(1 => (sin, cos), 2 => (+, -, *), 3 => (fma, max))
173+ ```
174+
175+ (Note that the order you pass the pairs is not important.)
0 commit comments