Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

#2595 trace cause extra evaluation of function arguments

None
open
nobody
None
5
2013-07-01
2013-06-18
Ian Dall
No

build_info(version="5.29.1",timestamp="2012-12-13 16:17:55",host="x86_64-redhat-linux-gnu",lisp_name="SBCL",lisp_version="1.1.2-1.fc18")

Consider the following definitions:

xf('f, 'var, val) := ev(f, [var:: val]);
xg(x) := sin(x);

and

y: %pi/2$
timer(xf)$ xf(xg(y), y, %pi/6); timer_info(); untimer(xf)$
xf(xg(y), y, %pi/6);

The first evaluation of xf() produces 1 whereas the second evaluation produces 1/2.

The same thing if you use trace() .. untrace().

It seems at the very least undesirable for trace and timer to alter the behaviour of the expressions that are being traced or timed.

Discussion

  • A simpler example:

    (%i39) fun ('var) := var;
    (%o39)                         fun('var) := var
    (%i40) x: 1$
    
    (%i41) fun(x);
    (%o41)                                 x
    (%i42) trace(fun)$
    
    (%i43) fun(x);
    1 Enter fun [1]
    1 Exit  fun 1
    (%o43)                                 1
    (%i44) untrace(fun);
    (%o44)                               [fun]
    (%i45) fun(x);
    (%o45)                                 x
    
     
  • More information on what's going on: Function application is normally done by expanding a function noun into its lambda form (usually stored as MEXPR on the symbol) and then calling MLAMBDA. MLAMBDA has special code to deal with functions that are defined with quoted variables (like 'var in fun above).

    When a function gets traced, what we do is remove the translation property and instead we call a trace handler which actually evaluates the function. Unfortunately, we call MEVALARGS on the arguments before we pass them through to the trace handler. (This is done in the 'subr case in MEVAL1 in mlisp.lisp)

    One possible fix is that we change the trace handlers to set an 'SUBR-NOEVAL property, which MEVAL1 looks for and, unlike with SUBR, doesn't evaluate the arguments beforehand.

    Comments from people more experienced in this sort of thing? MEVAL1 has already got a ridiculously huge COND statement. It would be nice to repurpose something that already exists... (MFEXPR*?)