# MLStyle's vs MacroTools' @capture

**URL:** <https://discourse.julialang.org/t/mlstyles-vs-macrotools-capture/102968>\
**Category:** New to Julia\
**Tags:** question, macros, mlstylejl\
**Created:** [August 18, 2023, 11:32pm UTC](https://discourse.julialang.org/t/mlstyles-vs-macrotools-capture/102968 "2023-08-18T23:32:28Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![deaminase](https://avatars.discourse-cdn.com/v4/letter/d/b2d939/32.png) [@deaminase](https://discourse.julialang.org/u/deaminase)\
**Post date:** [August 18, 2023, 11:32pm UTC](https://discourse.julialang.org/t/mlstyles-vs-macrotools-capture/102968/1 "2023-08-18T23:32:28Z")

</div>

Hey folks. I’ve been trying to figure out how to use `MLStyle.Modules.AST.@capture` for doing the same thing as `MacroTools.@capture(ex, fn_(args __; kws__ ) | fn_(args__))`

However, I can’t seem to come up with the syntax that does what `|` does in `MacroTools.@capture`. I assumed `||` would work since it seems to be used in regular MLStyle patterns, but it doesn’t seem like it:

```julia
In [20]: let ex = :(somefunction(param1, 666; a=5))
         @capture($fn($(args...);$(kw...)) || $fn($(args...)), ex)
         end
ERROR: matching non-exhaustive, at #= REPL[20]:2 =#

```

Both of those patterns work separately though, but only if the expression matches exactly:

```julia
In [24]: let ex = :(somefunction(param1, 666; a=5))
         @capture($fn($(args...);$(kw...)), ex)
         end
Dict{Symbol, Any} with 3 entries:
  :args => Any[:param1, 666]
  :fn => :somefunction
  :kw => Any[:($(Expr(:kw, :a, 5)))]

In [25]: let ex = :(somefunction(param1, 666))
         @capture($fn($(args...)), ex)
         end
Dict{Symbol, Any} with 2 entries:
  :args => Any[:param1, 666]
  :fn => :somefunction

```

So eg. the pattern with keywords won’t match a call that doesn’t have them

```julia
In [26]: let ex = :(somefunction(param1, 666))
         @capture($fn($(args...);$(kw...)), ex)
         end
ERROR: matching non-exhaustive, at #= REPL[26]:2 =#

```

Seems a bit inconvenient that `@capture` throws if it gets an expression that doesn’t match the template.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [August 19, 2023, 2:10am UTC](https://discourse.julialang.org/t/mlstyles-vs-macrotools-capture/102968/2 "2023-08-19T02:10:59Z")

</div>

@thautwarm would know best.

---

<div class="post-metadata">

**Author:** ![thautwarm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/thautwarm/32/37760_2.png) [@thautwarm](https://discourse.julialang.org/u/thautwarm)\
**Post date:** [August 23, 2023, 2:48pm UTC](https://discourse.julialang.org/t/mlstyles-vs-macrotools-capture/102968/3 "2023-08-23T14:48:30Z")

</div>

MacroTools is specific in this case, and pretty useful for maybe common usages. MLStyle instead keeps general (and sometimes useless) – although it might not be intentional for users to distinguish `:(f(a...))` and `:(f(a...;))`, the nature exists in Julia.

For the reason why your pattern `$fn($(args...);$(kw...))` does not match `f(a, b)` forms:

MLStyle holds the point that **deconstruction should only work like reverting the construction**.

```julia
julia> fn = :f
:f

julia> kws = []
Any[]

julia> args = [:a, :b]
2-element Vector{Symbol}:
 :a
 :b

julia> :($fn($(args...);$(kws...)))
:(f(a, b; )) # <- see the semicolon here, it is not `f(a, b)`

```

You can see that with the expression `:($fn($(args...);$(kws...)))` you create the value `:(f(a, b))`, which also suggests that the pattern `:($fn($(args...);$(kws...)))` can match `:(f(a, b; ))` but not `:(f(a, b))`.

If you insist on using one-line match for this, maybe

```julia
MLStyle.Modules.AST.@capture($( :($fn($(args...))) || :($fn($(args...);$(kw...))) ), ex)

```

---

<div class="post-metadata">

**Author:** ![deaminase](https://avatars.discourse-cdn.com/v4/letter/d/b2d939/32.png) [@deaminase](https://discourse.julialang.org/u/deaminase)\
**Post date:** [August 24, 2023, 1:01pm UTC](https://discourse.julialang.org/t/mlstyles-vs-macrotools-capture/102968/4 "2023-08-24T13:01:21Z")

</div>

> [@thautwarm](#):
>
> `MLStyle.Modules.AST.@capture($( :($fn($(args...))) || :($fn($(args...);$(kw...))) ), ex) `

Ah now I understand what I did wrong with my attempt, I didn’t interpolate the whole pattern: ` @capture($fn($(args...);$(kw...)) || $fn($(args...)), ex)`.

Thank you for taking the time to explain things to me @thautwarm

---

<div class="post-metadata">

**Author:** ![ShalokShalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shalokshalom/32/52462_2.png) [@ShalokShalom](https://discourse.julialang.org/u/ShalokShalom)\
**Post date:** [September 8, 2023, 12:09am UTC](https://discourse.julialang.org/t/mlstyles-vs-macrotools-capture/102968/5 "2023-09-08T00:09:07Z")

</div>

You might be interested:

> **[Expronicon | Expronicon](https://expronicon.rogerluo.dev/)**
>
> Collective tools for metaprogramming in Julia.

This library builds up on MLStyle.
