Skip to content

Commit 73d3da0

Browse files
committed
added defslot documentation to rewrite.md
1 parent 1feb709 commit 73d3da0

File tree

2 files changed

+57
-34
lines changed

2 files changed

+57
-34
lines changed

docs/src/manual/rewrite.md

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ r1(sin(2z))
2525

2626
The `@rule` macro takes a pair of patterns -- the _matcher_ and the _consequent_ (`@rule matcher => consequent`). If an expression matches the matcher pattern, it is rewritten to the consequent pattern. `@rule` returns a callable object that applies the rule to an expression.
2727

28-
`~x` in the example is what is a **slot variable** named `x`. In a matcher pattern, slot variables are placeholders that match exactly one expression. When used on the consequent side, they stand in for the matched expression. If a slot variable appears twice in a matcher pattern, all corresponding matches must be equal (as tested by `Base.isequal` function). Hence this rule says: if you see something added to itself, make it twice of that thing, and works as such.
28+
`~x` in the example is what is a **slot variable** named `x`. In a matcher pattern, slot variables are placeholders that match exactly one expression. When used on the consequent side, they stand in for the matched expression. If a slot variable appears twice in a matcher pattern, all corresponding matches must be equal (as tested by `Base.isequal` function).
2929

3030
If you try to apply this rule to an expression with triple angle, it will return `nothing` -- this is the way a rule signifies failure to match.
31-
```jldoctest rewrite
32-
r1(sin(3z)) === nothing
31+
```julia
32+
r1(sin(3z))
3333

3434
# output
35-
true
35+
nothing
3636
```
3737

3838
Slot variable (matcher) is not necessary a single variable
@@ -44,25 +44,47 @@ r1(sin(2*(w-z)))
4444
2cos(w - z)*sin(w - z)
4545
```
4646

47-
but it must be a single expression
47+
Rules are of course not limited to single slot variable
4848

4949
```jldoctest rewrite
50-
r1(sin(2*(w+z)*(α+β))) === nothing
50+
r2 = @rule sin(~x + ~y) => sin(~x)*cos(~y) + cos(~x)*sin(~y);
51+
52+
r2(sin(α+β))
5153
5254
# output
53-
true
55+
sin(β)*cos(α) + cos(β)*sin(α)
5456
```
5557

56-
Rules are of course not limited to single slot variable
57-
58+
Let's say you want to catch the coefficents of a second degree polynomial in z. You can do that with:
5859
```jldoctest rewrite
59-
r2 = @rule sin(~x + ~y) => sin(~x)*cos(~y) + cos(~x)*sin(~y);
60+
c2d = @rule ~a + ~b*z + ~c*z^2 => (~a, ~b, ~c)
6061
61-
r2(sin(α+β))
62+
c2d(3 + 2z + 5z^2)
63+
# output
64+
(3, 2, 5)
65+
```
66+
Great! But if you try:
67+
```julia
68+
c2d(3 + 2z + z^2)
6269

70+
#output
71+
nothing
72+
```
73+
the rule is not applied. This is because in the input polynomial there isnt a multiplication in front of the `z^2`. If you want to solve this you must use **defslot variables**, with syntax `~!a`:
74+
```jldoctest rewrite
75+
c2d = @rule ~!a + ~!b*z + ~!c*z^2 => (~a, ~b, ~c)
76+
77+
c2d(3 + 2z + z^2)
6378
# output
64-
sin(β)*cos(α) + cos(β)*sin(α)
79+
(3, 2, 1)
6580
```
81+
They work like normal slot variables, but if not present take a default value depending on the operation they are in, in the above example `~b = 1`. Currently defslot variables can be definied in:
82+
83+
Operation | Default value
84+
----------|--------------
85+
multiplication `*` | 1
86+
addition `+` | 0
87+
2nd argument of `^` | 1
6688

6789
If you want to match a variable number of subexpressions at once, you will need a **segment variable**. `~~xs` in the following example is a segment variable:
6890

src/rule.jl

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -248,24 +248,6 @@ If an expression matches LHS entirely, then it is rewritten to the pattern in th
248248
Slot, DefSlot and Segment variables on the RHS will substitute the result of the
249249
matches found for these variables in the LHS.
250250
251-
If the RHS is a single tilde `~`, then the rule returns a a dictionary of
252-
[slot variable, expression matched].
253-
254-
_Example:_
255-
256-
```julia
257-
julia> r = @rule (~x + (~y)^(~m)) => ~
258-
~x + (~y) ^ ~m => (~)
259-
260-
julia> r(a + b^2)
261-
Base.ImmutableDict{Symbol, Any} with 5 entries:
262-
:MATCH => a + b^2
263-
:m => 2
264-
:y => b
265-
:x => a
266-
:____ => nothing
267-
```
268-
269251
**Slot**:
270252
271253
A Slot variable is written as `~x` and matches a single expression. `x` is the name of the variable. If a slot appears more than once in an LHS expression then expression matched at every such location must be equal (as shown by `isequal`).
@@ -310,7 +292,7 @@ julia> r(sin(2a)^2 + cos(a)^2)
310292
311293
**DefSlot**:
312294
313-
A DefSlot variable is written as `~!x`. Works like a normal slot, but can also take additional values if not present in the expression.
295+
A DefSlot variable is written as `~!x`. Works like a normal slot, but can also take default values if not present in the expression.
314296
315297
_Example in power:_
316298
```julia
@@ -337,10 +319,11 @@ julia> r_sum(x)
337319
```
338320
339321
Currently DefSlot is implemented in:
340-
Operation | Default value
322+
323+
Operation | Default value<br>
341324
----------|--------------
342-
* | 1
343-
+ | 0
325+
\\* | 1
326+
\\+ | 0
344327
2nd argument of ^ | 1
345328
346329
**Segment**:
@@ -410,6 +393,24 @@ true
410393
Note that this is syntactic sugar and that it is the same as something like
411394
`@rule ~x => f(~x) ? ~x : nothing`.
412395
396+
**Debugging Rules**:
397+
Note that if the RHS is a single tilde `~`, then the rule returns a a dictionary of all [slot variable, expression matched], this is useful for debugging.
398+
399+
_Example:_
400+
401+
```julia
402+
julia> r = @rule (~x + (~y)^(~m)) => ~
403+
~x + (~y) ^ ~m => (~)
404+
405+
julia> r(a + b^2)
406+
Base.ImmutableDict{Symbol, Any} with 5 entries:
407+
:MATCH => a + b^2
408+
:m => 2
409+
:y => b
410+
:x => a
411+
:____ => nothing
412+
```
413+
413414
**Context**:
414415
415416
_In predicates_: Contextual predicates are functions wrapped in the `Contextual` type.

0 commit comments

Comments
 (0)