Better support for wrapper types

See this discussion for further discussion and, in particular, its recommendation of ForwardMethods.jl.

While sometimes I think about forwarding literally all methods, I usually end up deciding that’s too broad a brush. It also tends to break down. For example, if you wrap a <:Number, you might want sqrt to unwrap the value, apply sqrt and re-wrap it. But you don’t want to do this for another function like >=(0), since you want that to return a Bool.

While doing this only for all functions explicitly defined for the wrapped type sounds more sensible, recall that many methods are duck-typed, so that list is very incomplete (for example, it would miss any of the many methods that take arbitrary arguments and promote them).

If you aren’t using a package’s macro but instead defining forwards manually for an explicit list, metaprogramming can be useful:

# unary functions
for f in [:abs, :abs2, :sqrt, :exp, :log, :sin, :cos, :tan] # and many more
	@eval Base.$f(x::MyType) = MyType(Base.$f(x.value))
end

# binary functions
for f in [:+, :-, :*, :/, :^] # and many more
	@eval Base.$f(x::MyType, y::Number) = MyType(Base.$f(x.value, y))
	@eval Base.$f(x::Number, y::MyType) = MyType(Base.$f(x, y.value))
	@eval Base.$f(x::MyType, y::Number) = MyType(Base.$f(x.value, y.value))
end
7 Likes