Search code examples
returntclproc

Tcl return vs. last evaluated in proc - internals


When I write a proc in Tcl, which return value is actually the result of another proc I can do either of the following (see implicit example):

proc foo args {
...
...
bar $var1
}

Or I could do (see explicit example):

proc foo args {
...
...
return [ bar var1 ]
}

From an interface perspective, that is input vs. output, the two are identical. Are they, internally?
Or is there some added benefit to implicit vs. explicit return? Thanks.


Solution

  • In Tcl 8.6 you can inspect the bytecode to see how such procedures compare.

    If we define a pair of implementations of 'sum' and then examine them using tcl::unsupported::disassemble we can see that using the return statement or not results in the same bytecode.

    % proc sum_a {lhs rhs} {expr {$lhs + $rhs}}
    % proc sum_b {lhs rhs} {return [expr {$lhs + $rhs}]}
    
    % ::tcl::unsupported::disassemble proc sum_a
    ByteCode 0x03C5E8E8, refCt 1, epoch 15, interp 0x01F68CE0 (epoch 15)
      Source "expr {$lhs + $rhs}"
      Cmds 1, src 18, inst 6, litObjs 0, aux 0, stkDepth 2, code/src 0.00
      Proc 0x03CC33C0, refCt 1, args 2, compiled locals 2
          slot 0, scalar, arg, "lhs"
          slot 1, scalar, arg, "rhs"
      Commands 1:
          1: pc 0-4, src 0-17
      Command 1: "expr {$lhs + $rhs}"
        (0) loadScalar1 %v0     # var "lhs"
        (2) loadScalar1 %v1     # var "rhs"
        (4) add 
        (5) done 
    
    % ::tcl::unsupported::disassemble proc sum_b
    ByteCode 0x03CAD140, refCt 1, epoch 15, interp 0x01F68CE0 (epoch 15)
      Source "return [expr {$lhs + $rhs}]"
      Cmds 2, src 27, inst 6, litObjs 0, aux 0, stkDepth 2, code/src 0.00
      Proc 0x03CC4B80, refCt 1, args 2, compiled locals 2
          slot 0, scalar, arg, "lhs"
          slot 1, scalar, arg, "rhs"
      Commands 2:
          1: pc 0-5, src 0-26        2: pc 0-4, src 8-25
      Command 1: "return [expr {$lhs + $rhs}]"
      Command 2: "expr {$lhs + $rhs}"
        (0) loadScalar1 %v0     # var "lhs"
        (2) loadScalar1 %v1     # var "rhs"
        (4) add 
        (5) done 
    

    The return statement is really just documenting that you intended to return this value and it is not just a side-effect. Using return is not necessary but in my opinion it is to be recommended.