trace creates object in base namespace if called on function argument

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

trace creates object in base namespace if called on function argument

Antoine Fabri
Dear R-devel,

I don't think this is expected :

foo <- function() "hello"
trace2 <- function(fun) trace(fun, quote(print("!!!")))
base::fun
# Object with tracing code, class "functionWithTrace"
# Original definition:
# function() "hello"
#
# ## (to see the tracing code, look at body(object))

`untrace()` has the same behavior.

This is inconsistent with how debug works :

foo <- function() "hello"
debug2 <- function(fun) debug(fun)
debug2(foo)
isdebugged(foo)
# [1] TRUE

This can be worked around by defining :

trace2 <- function(fun) eval.parent(substitute(trace(fun,
quote(print("!!!")))

but I believe the current behavior is undesired and it'd be better to make
it behave as `debug()`, or to throw an error.

Best,

Antoine

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: trace creates object in base namespace if called on function argument

Antoine Fabri
Apologies there is one line missing in my last email, the code should be :

foo <- function() "hello"
trace2 <- function(fun) trace(fun, quote(print("!!!")))
trace2(foo) # <- THIS LINE WAS MISSING
base::fun

Best,

Antoine

Le mar. 25 août 2020 à 22:02, Antoine Fabri <[hidden email]> a
écrit :

> Dear R-devel,
>
> I don't think this is expected :
>
> foo <- function() "hello"
> trace2 <- function(fun) trace(fun, quote(print("!!!")))
> base::fun
> # Object with tracing code, class "functionWithTrace"
> # Original definition:
> # function() "hello"
> #
> # ## (to see the tracing code, look at body(object))
>
> `untrace()` has the same behavior.
>
> This is inconsistent with how debug works :
>
> foo <- function() "hello"
> debug2 <- function(fun) debug(fun)
> debug2(foo)
> isdebugged(foo)
> # [1] TRUE
>
> This can be worked around by defining :
>
> trace2 <- function(fun) eval.parent(substitute(trace(fun,
> quote(print("!!!")))
>
> but I believe the current behavior is undesired and it'd be better to make
> it behave as `debug()`, or to throw an error.
>
> Best,
>
> Antoine
>

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: trace creates object in base namespace if called on function argument

Tomas Kalibera
Please note that this is documented in ?trace. "fun" is matched to what,
it is a _name_ of the function to be traced, which is traced in the
top-level environment. I don't know why it was designed this way, but it
is documented in detail, and hence the expected behavior.

Debugging is often, and also in R, implemented in the core. Tracing is
implemented on top without specific support, it thus cannot do some
things debugging can do.

Tomas


On 8/26/20 3:31 AM, Antoine Fabri wrote:

> Apologies there is one line missing in my last email, the code should be :
>
> foo <- function() "hello"
> trace2 <- function(fun) trace(fun, quote(print("!!!")))
> trace2(foo) # <- THIS LINE WAS MISSING
> base::fun
>
> Best,
>
> Antoine
>
> Le mar. 25 août 2020 à 22:02, Antoine Fabri <[hidden email]> a
> écrit :
>
>> Dear R-devel,
>>
>> I don't think this is expected :
>>
>> foo <- function() "hello"
>> trace2 <- function(fun) trace(fun, quote(print("!!!")))
>> base::fun
>> # Object with tracing code, class "functionWithTrace"
>> # Original definition:
>> # function() "hello"
>> #
>> # ## (to see the tracing code, look at body(object))
>>
>> `untrace()` has the same behavior.
>>
>> This is inconsistent with how debug works :
>>
>> foo <- function() "hello"
>> debug2 <- function(fun) debug(fun)
>> debug2(foo)
>> isdebugged(foo)
>> # [1] TRUE
>>
>> This can be worked around by defining :
>>
>> trace2 <- function(fun) eval.parent(substitute(trace(fun,
>> quote(print("!!!")))
>>
>> but I believe the current behavior is undesired and it'd be better to make
>> it behave as `debug()`, or to throw an error.
>>
>> Best,
>>
>> Antoine
>>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: trace creates object in base namespace if called on function argument

Antoine Fabri
Hi Tomas,

The doc indeed describes `what` as "the name, possibly quote()d, of a
function to be traced or untraced".
This is a good argument not to change the function and make it behave more
like debug.

However the doc also tells us "A call to trace allows you to insert
debugging code (e.g., a call to browser or recover) at chosen places in any
function" and "The trace function operates by constructing a revised
version of the function (or of the method, if signature is supplied), and
assigning the new object back where the original was found". In the issue I
report a function was created in the base environment, which is not "where
the function was found". It's not clear to me what "where it was found"
would mean in that case, but I would assume the execution environment of
trace2, or maybe the calling environment (global in that case), or parent
of foo (global here again), but not the base namespace.

It would make sense to me to either have a traced fun in the execution
environment, or to have an error.

Best,

Antoine

Le mer. 26 août 2020 à 14:17, Tomas Kalibera <[hidden email]> a
écrit :

> Please note that this is documented in ?trace. "fun" is matched to what,
> it is a _name_ of the function to be traced, which is traced in the
> top-level environment. I don't know why it was designed this way, but it
> is documented in detail, and hence the expected behavior.
>
> Debugging is often, and also in R, implemented in the core. Tracing is
> implemented on top without specific support, it thus cannot do some
> things debugging can do.
>
> Tomas
>
>
> On 8/26/20 3:31 AM, Antoine Fabri wrote:
> > Apologies there is one line missing in my last email, the code should be
> :
> >
> > foo <- function() "hello"
> > trace2 <- function(fun) trace(fun, quote(print("!!!")))
> > trace2(foo) # <- THIS LINE WAS MISSING
> > base::fun
> >
> > Best,
> >
> > Antoine
> >
> > Le mar. 25 août 2020 à 22:02, Antoine Fabri <[hidden email]> a
> > écrit :
> >
> >> Dear R-devel,
> >>
> >> I don't think this is expected :
> >>
> >> foo <- function() "hello"
> >> trace2 <- function(fun) trace(fun, quote(print("!!!")))
> >> base::fun
> >> # Object with tracing code, class "functionWithTrace"
> >> # Original definition:
> >> # function() "hello"
> >> #
> >> # ## (to see the tracing code, look at body(object))
> >>
> >> `untrace()` has the same behavior.
> >>
> >> This is inconsistent with how debug works :
> >>
> >> foo <- function() "hello"
> >> debug2 <- function(fun) debug(fun)
> >> debug2(foo)
> >> isdebugged(foo)
> >> # [1] TRUE
> >>
> >> This can be worked around by defining :
> >>
> >> trace2 <- function(fun) eval.parent(substitute(trace(fun,
> >> quote(print("!!!")))
> >>
> >> but I believe the current behavior is undesired and it'd be better to
> make
> >> it behave as `debug()`, or to throw an error.
> >>
> >> Best,
> >>
> >> Antoine
> >>
> >       [[alternative HTML version deleted]]
> >
> > ______________________________________________
> > [hidden email] mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
>
>
>

        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: trace creates object in base namespace if called on function argument

Tomas Kalibera
Hi Antoine,

ok, I thought you were reporting that

 > foo <- function() "hello"
 > trace2 <- function(fun) trace(fun, quote(print("!!!")))
 > trace2(foo)
 > base::fun

in error did not trace "foo" in the top-level environment. This is,
however, expected, because "trace" is called with argument fun, so the
name of the function binding to replace is "fun" (not "foo"), and "fun"
does not exist in the top-level environment. You cannot wrap "trace"
like this.

If you meant to report that instead of throwing an error that an object
named "fun" was not found, this example inserts the instrumented code
into "base", that I also find surprising. The behavior I would have
expected is like with primitive tracing

 > foo <- function() "hello"
 > trace2 <- function(fun) trace(fun)
 > trace2(foo)
 > base::fun
Error in get(name, envir = ns, inherits = FALSE) : object 'fun' not found

If you are interested in this problem, feel free to investigate in more
detail (validate it is a bug via reading the documentation in detail,
reading the code, debugging, checking the commit history) and if it
turns out to be really a bug, feel free to submit a well-tested minimal
patch, via bugzilla.

Thanks,
Tomas


On 8/26/20 4:39 PM, Antoine Fabri wrote:

> Hi Tomas,
>
> The doc indeed describes `what` as "the name, possibly quote()d, of a
> function to be traced or untraced".
> This is a good argument not to change the function and make it behave
> more like debug.
>
> However the doc also tells us "A call to trace allows you to insert
> debugging code (e.g., a call to browser or recover) at chosen places
> in any function" and "The trace function operates by constructing a
> revised version of the function (or of the method, if signature is
> supplied), and assigning the new object back where the original was
> found". In the issue I report a function was created in the base
> environment, which is not "where the function was found". It's not
> clear to me what "where it was found" would mean in that case, but I
> would assume the execution environment of trace2, or maybe the calling
> environment (global in that case), or parent of foo (global here
> again), but not the base namespace.
>
> It would make sense to me to either have a traced fun in the execution
> environment, or to have an error.
>
> Best,
>
> Antoine
>
> Le mer. 26 août 2020 à 14:17, Tomas Kalibera <[hidden email]
> <mailto:[hidden email]>> a écrit :
>
>     Please note that this is documented in ?trace. "fun" is matched to
>     what,
>     it is a _name_ of the function to be traced, which is traced in the
>     top-level environment. I don't know why it was designed this way,
>     but it
>     is documented in detail, and hence the expected behavior.
>
>     Debugging is often, and also in R, implemented in the core.
>     Tracing is
>     implemented on top without specific support, it thus cannot do some
>     things debugging can do.
>
>     Tomas
>
>
>     On 8/26/20 3:31 AM, Antoine Fabri wrote:
>     > Apologies there is one line missing in my last email, the code
>     should be :
>     >
>     > foo <- function() "hello"
>     > trace2 <- function(fun) trace(fun, quote(print("!!!")))
>     > trace2(foo) # <- THIS LINE WAS MISSING
>     > base::fun
>     >
>     > Best,
>     >
>     > Antoine
>     >
>     > Le mar. 25 août 2020 à 22:02, Antoine Fabri
>     <[hidden email] <mailto:[hidden email]>> a
>     > écrit :
>     >
>     >> Dear R-devel,
>     >>
>     >> I don't think this is expected :
>     >>
>     >> foo <- function() "hello"
>     >> trace2 <- function(fun) trace(fun, quote(print("!!!")))
>     >> base::fun
>     >> # Object with tracing code, class "functionWithTrace"
>     >> # Original definition:
>     >> # function() "hello"
>     >> #
>     >> # ## (to see the tracing code, look at body(object))
>     >>
>     >> `untrace()` has the same behavior.
>     >>
>     >> This is inconsistent with how debug works :
>     >>
>     >> foo <- function() "hello"
>     >> debug2 <- function(fun) debug(fun)
>     >> debug2(foo)
>     >> isdebugged(foo)
>     >> # [1] TRUE
>     >>
>     >> This can be worked around by defining :
>     >>
>     >> trace2 <- function(fun) eval.parent(substitute(trace(fun,
>     >> quote(print("!!!")))
>     >>
>     >> but I believe the current behavior is undesired and it'd be
>     better to make
>     >> it behave as `debug()`, or to throw an error.
>     >>
>     >> Best,
>     >>
>     >> Antoine
>     >>
>     >       [[alternative HTML version deleted]]
>     >
>     > ______________________________________________
>     > [hidden email] <mailto:[hidden email]> mailing list
>     > https://stat.ethz.ch/mailman/listinfo/r-devel
>
>


        [[alternative HTML version deleted]]

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel