Skip to content

Commit 6fbe6c9

Browse files
Merge pull request #783 from Bumblebee00/new_documentation
added defslot documentation to rewrite.md
2 parents 1feb709 + d893a5e commit 6fbe6c9

File tree

2 files changed

+65
-33
lines changed

2 files changed

+65
-33
lines changed

docs/src/manual/rewrite.md

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,34 @@ 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

38-
Slot variable (matcher) is not necessary a single variable
39-
38+
Slot variable (matcher) is not necessary a single variable:
4039
```jldoctest rewrite
4140
r1(sin(2*(w-z)))
4241
4342
# output
4443
2cos(w - z)*sin(w - z)
4544
```
4645

47-
but it must be a single expression
46+
And can also match a function:
47+
```julia
48+
r = @rule (~f)(z+1) => ~f
4849

49-
```jldoctest rewrite
50-
r1(sin(2*(w+z)*(α+β))) === nothing
50+
r(sin(z+1))
5151

5252
# output
53-
true
54-
```
53+
sin (generic function with 20 methods)
5554

55+
```
5656
Rules are of course not limited to single slot variable
5757

5858
```jldoctest rewrite
@@ -64,6 +64,37 @@ r2(sin(α+β))
6464
sin(β)*cos(α) + cos(β)*sin(α)
6565
```
6666

67+
Now let's say you want to catch the coefficients of a second degree polynomial in z. You can do that with:
68+
```jldoctest rewrite
69+
c2d = @rule ~a + ~b*z + ~c*z^2 => (~a, ~b, ~c)
70+
71+
c2d(3 + 2z + 5z^2)
72+
# output
73+
(3, 2, 5)
74+
```
75+
Great! But if you try:
76+
```julia
77+
c2d(3 + 2z + z^2)
78+
79+
#output
80+
nothing
81+
```
82+
the rule is not applied. This is because in the input polynomial there isn't a multiplication in front of the `z^2`. For this you can use **defslot variables**, with syntax `~!a`:
83+
```jldoctest rewrite
84+
c2d = @rule ~!a + ~!b*z + ~!c*z^2 => (~a, ~b, ~c)
85+
86+
c2d(3 + 2z + z^2)
87+
# output
88+
(3, 2, 1)
89+
```
90+
They work like normal slot variables, but if they are not present they take a default value depending on the operation they are in, in the above example `~b = 1`. Currently defslot variables can be defined in:
91+
92+
Operation | Default value
93+
----------|--------------
94+
multiplication `*` | 1
95+
addition `+` | 0
96+
2nd argument of `^` | 1
97+
6798
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:
6899

69100
```jldoctest rewrite

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)