Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example from Interfacing Docs doesn't do x+x = 2*x #218

Open
Potatoasad opened this issue Mar 2, 2021 · 2 comments
Open

Example from Interfacing Docs doesn't do x+x = 2*x #218

Potatoasad opened this issue Mar 2, 2021 · 2 comments

Comments

@Potatoasad
Copy link

The following seems like a very simple re-write but the pattern just isn't matched.
Here's a recreation using an example from the docs

module MinimumWorkingExample
for f  [:+, :-, :*, :/, :^] #Note, this is type piracy!
    @eval begin
        Base.$f(x::Union{Expr, Symbol}, y::Number) = Expr(:call, $f, x, y)
        Base.$f(x::Number, y::Union{Expr, Symbol}) = Expr(:call, $f, x, y)
        Base.$f(x::Union{Expr, Symbol}, y::Union{Expr, Symbol}) = (Expr(:call, $f, x, y))
    end
end

using SymbolicUtils

istree(ex::Expr) = ex.head == :call
operation(ex::Expr) = ex.args[1]
arguments(ex::Expr) = ex.args[2:end]
symtype(s::Expr) = Number

ex = 1 + (:x - 2)
subtractonerule = @rule(~x => ~x - 1)
subtractonerule(ex) |> display #Returns :((-)((+)(1, (-)(x, 2)), 1)), which is completely fine


ex = :x + :x
combinetermsrule = @rule(~x + ~x => 2*(~x))
combinetermsrule(ex) |> display # Returns nothing, should return something like :((*)(2, x))

end

I'm having some issues making this work and would really appreciate some help, and hope someone can point out what I'm doing wrong here.

If this really is a bug, I just want to help in pointing it out. Thanks!

@TymonKilich
Copy link
Contributor

It's probably because of constructor-level simplification.

Pattern like x + x = 2x probably isn't matched because it's autosimplified to 2x immediately when constructed.

julia> @rule(~x + ~x => 2*(~x))(a + a) == nothing
true

julia> a + a
2a

julia> @rule(2*(~x) => "match!")(a + a)
"match!"

I'm working on PR to include that information in manual and update examples.

@Potatoasad
Copy link
Author

Potatoasad commented Mar 4, 2021

Thanks! Really appreciate the reply. Does this mean that when designing an interface, we need our constructors to do this automatic simplification as well?

Because in the type piracy example from the docs, x + x doesn't automatically simplify to 2*x, and neither is that caught by the rules. I would expect one or the other to happen, but it's neither.

In the type piracy example rule I wrote at the beginning of this thread, If I just output it without rules, I get:

ex = :x + :x
println(ex)  #Outputs :((+)(x, x))

And the @rule(~x + ~x => 2*x) returns nothing on it too.

I've gotten some luck by simply doing something like struct SymWrapperOnMyType <: Symbolic{MyType}, and it works exactly like a symbol that I would've generated using @syms, but that doesn't look like the standard way of doing things and if I wanted to make changes to some overloaded operators, I feel like I would have to rewrite pretty much the whole types.jl file for my specific type.

Thank you for that PR, I feel like I've implemented exactly what is needed by the docs but the simplification is happening in only very few circumstances. There are definitely missing links I need to implement to get my expression tree to parse well, I hope that doc goes up soon so I can know exactly what to implement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants