Overwriting Functions

183 views
Skip to first unread message

Curtis Vogt

unread,
Nov 28, 2015, 12:19:29 PM11/28/15
to julia-users
I've been working on a package Mocking.jl which allows developers to temporarily overwrite a method in order to facilitate testing. I've got everything working pretty well with the exception of the creation of a new macro which is suppose to ensure that Julia doesn't inline or optimize the call in such a way that the originally specified call can be overwritten:

julia> function myfunc(filename)

           readall(open(filename))

       end

myfunc (generic function with 1 method)


julia> myfunc("foo")

ERROR: SystemError: opening file foo: No such file or directory

 in open at ./iostream.jl:90

 in myfunc at none:2


julia> Base.open(name::AbstractString) = IOBuffer("bar")

WARNING: Method definition open(AbstractString) in module Base at iostream.jl:99 overwritten in module Main at none:1.

open (generic function with 8 methods)


julia> myfunc("foo")  # Open call within `myfunc` is not overwritten

ERROR: SystemError: opening file foo: No such file or directory

 in open at ./iostream.jl:90

 in myfunc at none:2


I can get this to work correctly with by adjusting the myfunc slightly:


julia> function myfunc(filename)

           readall([open([filename]...)]...)

       end

myfunc (generic function with 1 method)


julia> myfunc("foo")

ERROR: SystemError: opening file foo: No such file or directory

 in open at ./iostream.jl:90

 in open at iostream.jl:99

 in myfunc at none:2


julia> Base.open(name::AbstractString) = IOBuffer("bar")

WARNING: Method definition open(AbstractString) in module Base at iostream.jl:99 overwritten in module Main at none:1.

open (generic function with 8 methods)


julia> myfunc("foo")

"bar"


But this makes forces people to change their code and make it harder to read. Not to mention that this is just fooling the compiler into getting the behaviour I want. I would prefer to use a macro to get this behaviour and I managed to get the following horrible macro to work:



julia> macro fix(ex)

           name = gensym()

           :(@generated function $name() $ex end; $name())

       end


julia> function myfunc(filename)

           @fix readall(open(filename))

       end

myfunc (generic function with 1 method)


julia> myfunc("foo")

ERROR: SystemError: opening file foo: No such file or directory

 in open at ./iostream.jl:90

 in open at iostream.jl:99

 in #2###6995 at none:3

 in myfunc at none:2


julia> Base.open(name::AbstractString) = IOBuffer("bar")

WARNING: Method definition open(AbstractString) in module Base at iostream.jl:99 overwritten in module Main at none:1.

open (generic function with 8 methods)


julia> myfunc("foo")

"bar"


Does anyone have any suggestions on how I can improve this macro and get this behaviour? Bonus points if someone can tell me a good way of determining if the macro is being called from within a `Pkg.test(...)` process.

Eric Davies

unread,
Dec 5, 2015, 8:56:16 PM12/5/15
to julia-users
This took a while to show up and may have been missed.
Reply all
Reply to author
Forward
0 new messages