• =?UTF-8?Q?=22uplevel=22_in_=22proc=22_=e2=86=92_missing_more_genera?= =

    From aotto1968@21:1/5 to All on Tue Jul 19 14:22:03 2022
    Hi,

    an *uplevel-proc* is an *proc* which evaluate the entire content
    *uplevel* → example:

    proc Format_Return_Error_Check {hdl err} {
    uplevel "Format_Error_Check $hdl $err ; set retM void"
    }

    This simulate a *CPP*-Macro like behavior in *TCL*.

    The easy solution to just lice a normal *proc*-body like:

    proc Format_Return_Error_Check {hdl err} {
    upvar retM retM
    Format_Error_Check $hdl $err
    set retM void
    }

    is not really a solution because the "upvar" in a sub-*proc* like *Format_Error_Check* is broken because *Format_Return_Error_Check*
    return an extra call-frame.

    solution:

    It should be possible to create a *proc* witch *not* add an extra
    *level* to the call-frame, a good name would be *macro* :

    macro Format_Return_Error_Check {hdl err} {
    Format_Error_Check $hdl $err
    set retM void
    }

    The following features should be present:

    1) A *macro* argument variable (hdl err) is *only* visible in the macro-body
    2) A other variable (retM) is from the calling-call-frame
    3) A *macro* deos NOT add a call-frame → an *upvar* in
    *Format_Error_Check* should call he calling-call-frame and not the macro-body-frame

    mfg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From heinrichmartin@21:1/5 to All on Tue Jul 19 23:56:31 2022
    On Tuesday, July 19, 2022 at 2:22:08 PM UTC+2, aotto1 wrote:
    Hi,

    an *uplevel-proc* is an *proc* which evaluate the entire content
    *uplevel* → example:

    proc Format_Return_Error_Check {hdl err} {
    uplevel "Format_Error_Check $hdl $err ; set retM void"
    }

    This simulate a *CPP*-Macro like behavior in *TCL*.

    Tcl has quite some nice features that can help to prevent duplicate code beyond putting it in a proc. Here are some that are crossing my mind.

    1. uplevel

    If you stick to your pattern, you are looking for [catch {uplevel 1 {...}} result options], then [dict incr options -level; return {*}$options $result].
    You could even write your own proc "macro" that adds this wrapper to the code before actually creating the proc.

    2. upvar

    As uplevel has a performance penalty (cannot be optimized), upvar'ing well-known or passed variable names should be preferred over uplevel. The catch-wrapper is still needed for generic code.

    3. inject code

    Sometimes, I am using [proc name args [format {} $inject1 ...]]. I am using it for one-time-setup/config and also to prevent duplicate code.
    Pro: Tcl sees a constant proc body and can fully optimize it.
    Con: An extra level of escaping, but % is normally not a factor.

    4. rewrite code

    Just recently, I was injecting a code fix to a foreign proc while initializing my code. This pattern could be extended to rewrite "macros".

    apply {{} {
    set name this_proc
    # build args like for proc
    set args [lmap arg [info args $name] {
    if {[info default $name $arg default]} {
    list $arg $default
    } else {
    list $arg
    }
    }]
    set body [info body $name]
    # re-write to allow $client with parameters
    # (braces around proc make my code doc scanner ignore this one)
    {proc} $name $args [string map {{invoke $client } {invoke {*}$client }} $body]
    log warn "$name was re-written!"
    }}

    Pro: Tcl sees a constant proc body and can fully optimize it.
    Con (for non-Tclers): Might not feel like the natural way of coding ;-)

    5. eval

    Instead of uplevel, do uplevel without context change: eval.

    6. packages/libs

    Iirc, there are also a few Tcl packages that hook in to do magic to your code. Others may have names at hand.

    HTH
    Martin

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Gollwitzer@21:1/5 to All on Thu Jul 21 16:18:14 2022
    Am 20.07.22 um 08:56 schrieb heinrichmartin:
    On Tuesday, July 19, 2022 at 2:22:08 PM UTC+2, aotto1 wrote:


    This simulate a *CPP*-Macro like behavior in *TCL*.


    6. packages/libs

    Iirc, there are also a few Tcl packages that hook in to do magic to your code. Others may have names at hand.


    Try this: https://wiki.tcl-lang.org/page/Sugar


    Christian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerald Lester@21:1/5 to All on Sat Jul 23 11:27:35 2022
    On 7/19/22 07:22, aotto1968 wrote:
    Hi,

    an *uplevel-proc* is an *proc* which evaluate the entire content
    *uplevel* → example:

      proc Format_Return_Error_Check {hdl err} {
        uplevel "Format_Error_Check $hdl $err ; set retM void"
      }

    This simulate a *CPP*-Macro like behavior in *TCL*.

    The easy solution to just lice a normal *proc*-body like:

      proc Format_Return_Error_Check {hdl err} {
        upvar retM retM
        Format_Error_Check $hdl $err
        set retM void
      }

    is not really a solution because the "upvar" in a sub-*proc* like *Format_Error_Check* is broken because *Format_Return_Error_Check*
    return an extra call-frame.

    solution:

    It should be possible to create a *proc* witch *not* add an extra
    *level* to the call-frame, a good name would be *macro* :

      macro Format_Return_Error_Check {hdl err} {
        Format_Error_Check $hdl $err
        set retM void
      }

    The following features should be present:

    1) A *macro* argument variable (hdl err) is *only* visible in the
    macro-body
    2) A other variable (retM) is from the calling-call-frame
    3) A *macro* deos NOT add a call-frame → an *upvar* in
    *Format_Error_Check* should call he calling-call-frame and not the macro-body-frame

    mfg

    Create a TIP with a sample implementations.



    --
    +----------------------------------------------------------------------+
    | Gerald W. Lester, President, KNG Consulting LLC |
    | Email: [email protected] | +----------------------------------------------------------------------+

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerald Lester@21:1/5 to heinrichmartin on Sat Jul 23 13:37:46 2022
    On 7/20/22 01:56, heinrichmartin wrote:
    On Tuesday, July 19, 2022 at 2:22:08 PM UTC+2, aotto1 wrote:
    Hi,

    an *uplevel-proc* is an *proc* which evaluate the entire content
    *uplevel* → example:

    proc Format_Return_Error_Check {hdl err} {
    uplevel "Format_Error_Check $hdl $err ; set retM void"
    }

    This simulate a *CPP*-Macro like behavior in *TCL*.

    Tcl has quite some nice features that can help to prevent duplicate code beyond putting it in a proc. Here are some that are crossing my mind.

    1. uplevel

    If you stick to your pattern, you are looking for [catch {uplevel 1 {...}} result options], then [dict incr options -level; return {*}$options $result].
    You could even write your own proc "macro" that adds this wrapper to the code before actually creating the proc.

    2. upvar

    As uplevel has a performance penalty (cannot be optimized), upvar'ing well-known or passed variable names should be preferred over uplevel. The catch-wrapper is still needed for generic code.

    3. inject code

    Sometimes, I am using [proc name args [format {} $inject1 ...]]. I am using it for one-time-setup/config and also to prevent duplicate code.
    Pro: Tcl sees a constant proc body and can fully optimize it.
    Con: An extra level of escaping, but % is normally not a factor.

    4. rewrite code

    Just recently, I was injecting a code fix to a foreign proc while initializing my code. This pattern could be extended to rewrite "macros".

    apply {{} {
    set name this_proc
    # build args like for proc
    set args [lmap arg [info args $name] {
    if {[info default $name $arg default]} {
    list $arg $default
    } else {
    list $arg
    }
    }]
    set body [info body $name]
    # re-write to allow $client with parameters
    # (braces around proc make my code doc scanner ignore this one)
    {proc} $name $args [string map {{invoke $client } {invoke {*}$client }} $body]
    log warn "$name was re-written!"
    }}

    Pro: Tcl sees a constant proc body and can fully optimize it.
    Con (for non-Tclers): Might not feel like the natural way of coding ;-)

    5. eval

    Instead of uplevel, do uplevel without context change: eval.

    6. packages/libs

    Iirc, there are also a few Tcl packages that hook in to do magic to your code. Others may have names at hand.

    HTH
    Martin

    And then there is the Object Orient features.

    --
    +----------------------------------------------------------------------+
    | Gerald W. Lester, President, KNG Consulting LLC |
    | Email: [email protected] | +----------------------------------------------------------------------+

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)