• Can all variables be global?

    From Luc@21:1/5 to All on Sat Dec 17 10:01:13 2022
    Tcl can do some pretty unusual and remarkable things, so it's worth asking:

    Is there some way to make all variables global? Automatically? Even inside procs? Maybe some introspection or everything-is-a-string Tcl sort of trick?

    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Luc on Sat Dec 17 14:16:37 2022
    Luc <no@no.no> wrote:
    Tcl can do some pretty unusual and remarkable things, so it's worth asking:

    Is there some way to make all variables global?

    What is the purpose? Do note that doing this is a recipie for
    unintended consequences at a distance problems that rapidly become
    nearly impossible to debug.

    Automatically?

    No, there is no way to 'automatically' (as in without you, the
    programmer, doing something to make it so) do so.

    Even inside procs?

    Not automatically (as in without you the programmer doing something to
    make it so).

    Maybe some introspection or everything-is-a-string Tcl sort of trick?

    If you really want every variable to be global, then prefix all your
    variables with ::

    They will all be global that way. The rest of us will sit back and
    watch the hilarity ensue.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to rich@example.invalid on Sat Dec 17 16:11:46 2022
    In article <tnkj05$3lupf$1@dont-email.me>, Rich <rich@example.invalid> wrote: >Luc <no@no.no> wrote:
    Tcl can do some pretty unusual and remarkable things, so it's worth asking: >>
    Is there some way to make all variables global?

    What is the purpose?

    Usually, when you ask "Is it possible to do <X>?" and the first response is "Why do you want to do <X>?", then you can assume that the answer to your question is "No".

    ...
    If you really want every variable to be global, then prefix all your >variables with ::

    That's actually quite useful. That you can make a variable global by
    prefixing the name with ::.

    I've always done it the old-fashioned (hard) way - of having to declare it global in every proc that uses it. Using :: looks like it would be a lot easier. Thanks.

    --
    1/20/17: A great day for all those people who are sick of being told
    they don't know how to spell "you're" (or "there").

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Luc on Sun Dec 18 05:50:07 2022
    Luc <no@no.no> wrote:
    On Sat, 17 Dec 2022 16:11:46 -0000 (UTC), Kenny McCormack wrote:

    Tcl can do some pretty unusual and remarkable things, so it's worth
    asking:

    Is there some way to make all variables global?

    What is the purpose?

    Usually, when you ask "Is it possible to do <X>?" and the first response
    is "Why do you want to do <X>?", then you can assume that the answer to
    your question is "No".

    ...
    If you really want every variable to be global, then prefix all your
    variables with ::

    That's actually quite useful. That you can make a variable global by
    prefixing the name with ::.

    I've always done it the old-fashioned (hard) way - of having to declare it >> global in every proc that uses it. Using :: looks like it would be a lot
    easier. Thanks.



    I am aware of the :: method. I was rather wondering if there might be something like, whenever a variable is created, apply this or that to it.

    Maybe it doesn't exist, but sounds a lot like a feature that Tcl would have.

    Look at the documentation of the 'trace' command. You might be able to
    cause every variable to be global with an execution trace attached to
    the 'set' command. This will take a performance hit compared to
    prefixing every access with ::. And it might very well cause some very
    odd side effects with one or more loaded modules/packages (because
    their own internal variables would also unexpectedly become globals and
    could conflict with the same variable names in other loaded
    modules/packages).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luc@21:1/5 to Kenny McCormack on Sun Dec 18 02:18:18 2022
    On Sat, 17 Dec 2022 16:11:46 -0000 (UTC), Kenny McCormack wrote:

    Tcl can do some pretty unusual and remarkable things, so it's worth
    asking:

    Is there some way to make all variables global?

    What is the purpose?

    Usually, when you ask "Is it possible to do <X>?" and the first response
    is "Why do you want to do <X>?", then you can assume that the answer to
    your question is "No".

    ...
    If you really want every variable to be global, then prefix all your >variables with ::

    That's actually quite useful. That you can make a variable global by prefixing the name with ::.

    I've always done it the old-fashioned (hard) way - of having to declare it global in every proc that uses it. Using :: looks like it would be a lot easier. Thanks.



    I am aware of the :: method. I was rather wondering if there might be
    something like, whenever a variable is created, apply this or that to it.

    Maybe it doesn't exist, but sounds a lot like a feature that Tcl would have.

    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mole Cool@21:1/5 to All on Sun Dec 18 03:11:28 2022
    Regarding 'everything-is-a-string' I don't want to start a discussion here, but in my point of view this is a misleading statement, and not 'True' for Tcl. The Beauty of Tcl is, that you don't need a format call to display the string, due to the fact
    that everything is hold in a Tcl_Obj (The display value, and the 'double' in C, and this is dynamic). Even in other languages, like C, Phyton, your source code is 'TEXT', a number like '10.25' is text in your source code. A SQL select is most of the time
    'Text' as well, HTML is text and so on ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mole Cool@21:1/5 to All on Sun Dec 18 03:00:40 2022
    I think as well that this is not a good idea, but I see 2 Options:

    1. Define you own set command like 'gset' and within that proc and with upvar you can archive that requirement (not tested by myself)
    2. Rename set and use your own set command, again use upvar.

    I think this will not work for everything in Tcl, 'array set' and other commands which will set a var may not do what you want.

    Because of what 'Rich' has commented, your own 'set -> set' command is probably a better idea :-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Mole Cool on Sun Dec 18 14:31:44 2022
    Mole Cool <molecool1058@googlemail.com> wrote:
    Regarding 'everything-is-a-string' I don't want to start a discussion
    here, but in my point of view this is a misleading statement,

    More correctly, it is an "age-old" statement that has come to be Tcl's "catchphrase" even still.

    and not 'True' for Tcl.

    For Tcl prior to 8.0 it was factually true -- everything was a string
    in pre 8.0 versions of Tcl.

    For Tcl 8.0 and forward, they maintain the fasade of "everything is a
    string" even though underlying reality differs in most cases.

    The Beauty of Tcl is, that you don't need a format call to display
    the string, due to the fact that everything is hold in a Tcl_Obj (The
    display value, and the 'double' in C, and this is dynamic).

    Except it is not because of the Tcl_Obj, it is because the Tcl_Obj
    system was designed to emulate the pre-8.0 Tcl 'everything is a string' semantics. In an alternate universe, the Tcl_Obj system could have
    just as easily pulled a Python and broke backwards compatibility and so
    trying to do 'puts $number' would abort with "Error: $number is not a
    string type" or some such error, forcing numbers to be output by "puts
    [format %d $number]" instead.

    Even in other languages, like C, Phyton, your source code is 'TEXT',
    a number like '10.25' is text in your source code. A SQL select is
    most of the time 'Text' as well, HTML is text and so on
    ...

    And so they are in your Tcl source, but how they are in the source, and
    how they are stored at runtime, can, and likely, does differ.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andreas Leitgeb@21:1/5 to Rich on Sun Dec 18 18:51:38 2022
    Rich <rich@example.invalid> wrote:
    Mole Cool <molecool1058@googlemail.com> wrote:
    Regarding 'everything-is-a-string' I don't want to start a discussion
    here, but in my point of view this is a misleading statement,
    More correctly, it is an "age-old" statement that has come to be Tcl's "catchphrase" even still.

    It is a "design principle" - still.

    It describes how it works like, but not how it is actually implemented.
    e.g. it says that after
    set a "1 2 3"
    set b [list 1 2 3]
    the values of $a and $b are "indistinguishable".

    And ditto do
    set a [string range [expr {sqrt(2)}] 4 5]
    set b [expr {6*7}]
    give the "same" "indistinguishable" result.

    Except it is not because of the Tcl_Obj, it is because the Tcl_Obj
    system was designed to emulate the pre-8.0 Tcl 'everything is a string' semantics.

    Tcl_Obj was just designed according to the "EIAS" principle.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From saitology9@21:1/5 to Luc on Sun Dec 18 20:14:34 2022
    On 12/17/2022 8:01 AM, Luc wrote:
    Tcl can do some pretty unusual and remarkable things, so it's worth asking:

    Is there some way to make all variables global? Automatically? Even inside procs? Maybe some introspection or everything-is-a-string Tcl sort of trick?



    Interesting question. As has been noted, ***don't do it***. Otherwise,
    it throws all concepts of software development, code modularization, abstraction, etc. into a spaghetti bowl.

    However, this being Tcl, here is a solution:
    First, a few examples of what becomes possible:

    # example 1
    % set who "you"
    % proc say_hi {greeting} {
    puts "$greeting, $who"
    }

    % say_hi "Good morning"
    Good morning, you

    # example 2
    % set x 10
    % set y 20
    % proc multiply {} {
    puts [expr $x * $y]
    }

    % multiply
    200

    % set x 100
    % multiply
    2000


    # here is the code to make it possible
    # the trick is to update or (create) proc arg's in the global scope
    # and then evaluating the proc body with uplevel.
    # I think it is possible to avoid renaming arg's

    proc new_proc {name args body} {
    set i 0
    set add_cmd ""
    set new_sig ""
    foreach x $args {
    # try to avoid name collusions
    incr i
    set new_arg "__x${i}__"

    set xname [lindex $x 0]
    if {[llength $x] == 1} {
    append new_sig "$new_arg "

    } else {
    append new_sig "\{$new_arg \"$xinit\"\} "
    }

    append add_cmd "set ::$xname \$$new_arg \n"
    }

    # reconstruct the proc
    set new_body "$add_cmd"
    append new_body "\n"
    append new_body "uplevel 1 \{$body\} \n"
    orig_proc $name $new_sig $new_body
    }


    rename proc orig_proc
    rename new_proc proc

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From saitology9@21:1/5 to All on Sun Dec 18 20:19:51 2022
    On 12/18/2022 8:14 PM, saitology9 wrote:

            } else {
                 append new_sig "\{$new_arg \"$xinit\"\} "
            }

    I skipped over a command in the snippet above, please add as follows:


    } else {
    set xinit [lindex $x 1]
    append new_sig "\{$new_arg \"$xinit\"\} "
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luc@21:1/5 to All on Mon Dec 19 04:24:38 2022
    Thank you for all the input. It is educational.

    The idea of creating a "gset" (set global) proc is something obvious
    I should have thought of. You see, Tcl always has a way.

    Making ALL variables global is of course bad especially if it affects
    variables that I didn't create myself. But in certain situations,
    it may make things easier to manage. Don't worry, I will be careful.

    Many thanks.

    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From heinrichmartin@21:1/5 to Luc on Mon Dec 19 00:50:50 2022
    On Monday, December 19, 2022 at 8:24:43 AM UTC+1, Luc wrote:
    The idea of creating a "gset" (set global) proc is something obvious

    Just note that there are other procs that create/set variables.
    Also, tempering with set (i.e. if you wanted to redirect built-in set) is hardly ever a good idea.

    As this thread (also) is about options in Tcl: one could redirect proc and rewrite the body.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerald Lester@21:1/5 to Luc on Mon Dec 19 08:43:45 2022
    On 12/17/22 07:01, Luc wrote:
    Tcl can do some pretty unusual and remarkable things, so it's worth asking:

    Is there some way to make all variables global? Automatically? Even inside procs? Maybe some introspection or everything-is-a-string Tcl sort of trick?


    Not just NO, but HELL NO -- and for good reason as others have pointed out.

    BTW, Tcl does not and will not have GOTOs either -- also for good reasons.

    --
    +----------------------------------------------------------------------+
    | Gerald W. Lester, President, KNG Consulting LLC |
    | Email: Gerald.Lester@kng-consulting.net | +----------------------------------------------------------------------+

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Gollwitzer@21:1/5 to All on Mon Dec 19 15:52:43 2022
    Am 19.12.22 um 15:39 schrieb Ralf Fassel:
    * saitology9 <saitology9@gmail.com>
    | # the trick is to update or (create) proc arg's in the global scope
    | # and then evaluating the proc body with uplevel.

    I would say that the proc's args should *not* go into the global
    namespace, since they do exist as locals inside the proc and cause no problem.

    I think you can circumvent this by putting the vars into a special
    namespace. Since all vars should be global, namespaces will not occur.



    At least *I* would certainly not want to override some arbitrary global variable which just happens to have the same name as the proc arg of
    some random function.

    However, this certainly will help to achieve the horror Rich predicted elsethread :-)

    Yes it is pure hell. There are a few "programming languages" like this
    (e.g. SPECS instrument control system) which have no local variables and
    it becomes hell whenever you decide to import a library written by
    someone else.

    I think there is still a "bug", though - the "uplevel 1" will not work
    when it is a nested procedure call. "uplevel #0" would do the trick to
    run the code at global scope. I haven't tested it, so might be wrong ;)

    Christian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralf Fassel@21:1/5 to All on Mon Dec 19 15:39:27 2022
    * saitology9 <saitology9@gmail.com>
    | # the trick is to update or (create) proc arg's in the global scope
    | # and then evaluating the proc body with uplevel.

    I would say that the proc's args should *not* go into the global
    namespace, since they do exist as locals inside the proc and cause no
    problem.

    At least *I* would certainly not want to override some arbitrary global variable which just happens to have the same name as the proc arg of
    some random function.

    However, this certainly will help to achieve the horror Rich predicted elsethread :-)

    R'

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luc@21:1/5 to Christian Gollwitzer on Mon Dec 19 12:45:12 2022
    On Mon, 19 Dec 2022 15:52:43 +0100, Christian Gollwitzer wrote:

    Yes it is pure hell. There are a few "programming languages" like this
    (e.g. SPECS instrument control system) which have no local variables and
    it becomes hell whenever you decide to import a library written by
    someone else.


    I'm pretty sure there is a very large number of programs/scripts out there
    that will never ever interact with any external libraries or packages or
    remote machines and will never be shared. That kind of use exists, it's very common and cannot (and should not) be prevented.

    What also cannot be prevented is that someone begins a script/program with
    some kind of inventory of all variables used in the program and making them
    all globals with the 'global' command. Any possible implementation of what
    I asked would merely automate something that already can be done although
    in a tedious manner.


    --
    Luc


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From saitology9@21:1/5 to Luc on Mon Dec 19 11:08:35 2022
    On 12/19/2022 10:45 AM, Luc wrote:

    What also cannot be prevented is that someone begins a script/program with some kind of inventory of all variables used in the program and making them all globals with the 'global' command. Any possible implementation of what
    I asked would merely automate something that already can be done although
    in a tedious manner.



    I haven't read all the replies in detail but perhaps it was the way you
    first expressed it: make every variable global.

    However, the construct to achieve a similar goal is useful and exists in
    some iconic languages including Lisp.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From saitology9@21:1/5 to Christian Gollwitzer on Mon Dec 19 11:01:16 2022
    On 12/19/2022 9:52 AM, Christian Gollwitzer wrote:

    I would say that the proc's args should *not* go into the global
    namespace, since they do exist as locals inside the proc and cause no
    problem.

    I think you can circumvent this by putting the vars into a special
    namespace. Since all vars should be global, namespaces will not occur.


    I agree. I thought that was the intention anyway. One can certainly hide
    the previous values of such variables in a list and restore them in a
    try-catch block.



    I think there is still a "bug", though  - the "uplevel 1" will not work
    when it is a nested procedure call. "uplevel #0" would do the trick to
    run the code at global scope. I haven't tested it, so might be wrong ;)


    You're probably right - I forgot that there was a deeper level than 1 :-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Soyka@21:1/5 to Luc on Mon Dec 19 11:10:07 2022
    On 12/19/2022 10:45 AM, Luc wrote:
    On Mon, 19 Dec 2022 15:52:43 +0100, Christian Gollwitzer wrote:

    Yes it is pure hell. There are a few "programming languages" like this
    (e.g. SPECS instrument control system) which have no local variables and
    it becomes hell whenever you decide to import a library written by
    someone else.


    I'm pretty sure there is a very large number of programs/scripts out there that will never ever interact with any external libraries or packages or remote machines and will never be shared. That kind of use exists, it's very common and cannot (and should not) be prevented.

    What also cannot be prevented is that someone begins a script/program with some kind of inventory of all variables used in the program and making them all globals with the 'global' command. Any possible implementation of what
    I asked would merely automate something that already can be done although
    in a tedious manner.


    How about defining a dictionary variable in the global scope whose keys
    are the global variable names? Without thinking too much it seems easy
    to use an editor command to then do the code modifications:

    s/globalVar/g["globalVar"]/g

    where "g" is the dictionary variable in global scope. It certainly
    reduces the likelihood of name collisions in the global namespace at the expense of reformatting the code.

    Although, now that I've suggested it, array and dictionary variables
    would be a fly in the soup. Well, for a few moments, it was an idea!

    -mike

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From saitology9@21:1/5 to Ralf Fassel on Mon Dec 19 11:03:38 2022
    On 12/19/2022 9:39 AM, Ralf Fassel wrote:

    I would say that the proc's args should *not* go into the global
    namespace, since they do exist as locals inside the proc and cause no problem.


    One can circumvent this by saving/restoring them but frankly I think
    this was the intended result.

    However, this certainly will help to achieve the horror Rich predicted elsethread :-)


    I agree. And it is fun as you said in another post.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralf Fassel@21:1/5 to All on Mon Dec 19 16:17:58 2022
    * Gerald Lester <Gerald.Lester@KnG-Consulting.net>
    | On 12/17/22 07:01, Luc wrote:
    | > Tcl can do some pretty unusual and remarkable things, so it's worth asking: | > Is there some way to make all variables global? Automatically? Even
    | > inside
    | > procs? Maybe some introspection or everything-is-a-string Tcl sort of trick?
    | >

    | Not just NO, but HELL NO -- and for good reason as others have pointed out.

    It is FUN however, in that it produces side effects you would not have
    dreamed of :-))) Would probably be a nice question in a job interview...

    R'

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerald Lester@21:1/5 to Luc on Mon Dec 19 11:00:45 2022
    On 12/19/22 09:45, Luc wrote:
    On Mon, 19 Dec 2022 15:52:43 +0100, Christian Gollwitzer wrote:

    Yes it is pure hell. There are a few "programming languages" like this
    (e.g. SPECS instrument control system) which have no local variables and
    it becomes hell whenever you decide to import a library written by
    someone else.


    I'm pretty sure there is a very large number of programs/scripts out there that will never ever interact with any external libraries or packages or remote machines and will never be shared. That kind of use exists, it's very common and cannot (and should not) be prevented.

    What also cannot be prevented is that someone begins a script/program with some kind of inventory of all variables used in the program and making them all globals with the 'global' command. Any possible implementation of what
    I asked would merely automate something that already can be done although
    in a tedious manner.

    The 'global' command would have to be done inside of each procedure.

    Doing 'global' at the global scope level has no effect.

    --
    +----------------------------------------------------------------------+
    | Gerald W. Lester, President, KNG Consulting LLC |
    | Email: Gerald.Lester@kng-consulting.net | +----------------------------------------------------------------------+

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Christian Gollwitzer@21:1/5 to All on Mon Dec 19 19:04:08 2022
    Am 19.12.22 um 16:45 schrieb Luc:
    On Mon, 19 Dec 2022 15:52:43 +0100, Christian Gollwitzer wrote:

    Yes it is pure hell. There are a few "programming languages" like this
    (e.g. SPECS instrument control system) which have no local variables and
    it becomes hell whenever you decide to import a library written by
    someone else.


    I'm pretty sure there is a very large number of programs/scripts out there that will never ever interact with any external libraries or packages or remote machines and will never be shared. That kind of use exists, it's very common and cannot (and should not) be prevented.

    I mentioned the SPECS thing exactly because this started as a language
    for scripts which does not require external libraries etc. It is a
    specialised language for driving scientific equipment to acquire data. A colleague had written some advanced measurement procedures in it, then
    wanted to integrate a new detector. The vendor of this detector provides
    SPECs macros - which then, of course, used variable names which collided
    with the script from my colleague. In the end, we threw everything
    overboard and switched to a more sane system. That was easier then to
    untangle the codes.


    What also cannot be prevented is that someone begins a script/program with some kind of inventory of all variables used in the program and making them all globals with the 'global' command. Any possible implementation of what
    I asked would merely automate something that already can be done although
    in a tedious manner.


    I'm still not sure I understand WHY you would want to have something
    like that. However, I'm quite sure that there are better solutions. One
    of them could be the use of an object system. There, you declare
    variables once, but you don't have to repeat the "variable x" or "global
    x" in each and every proc.

    E.g.:

    oo::class create testglobals {

    variable x
    variable y

    method setxy {x_ y_} {
    set x $x_
    set y $y_
    }

    method print {} {
    puts "x: $x y: $y"
    }
    }


    testglobals create B

    B setxy 3 4
    B print

    As you can see here, in both methods setxy and print, you can access the variables "x" and "y" without specially annotating them. However, since
    they are marked as a variable in the class declaration, you could some
    other variable "set i 7" in one of them without interfering with other
    parts of the code.

    Christian

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Luc@21:1/5 to Michael Soyka on Mon Dec 19 14:31:34 2022
    On Mon, 19 Dec 2022 11:10:07 -0500, Michael Soyka wrote:

    How about defining a dictionary variable in the global scope whose keys
    are the global variable names? Without thinking too much it seems easy
    to use an editor command to then do the code modifications:

    s/globalVar/g["globalVar"]/g

    where "g" is the dictionary variable in global scope. It certainly
    reduces the likelihood of name collisions in the global namespace at the expense of reformatting the code.
    ************************


    Yes, it's an interesting idea. I probably won't use it, but I'll probably
    have fun toying with it in a throwaway script. It's educational. Tcl is
    full of interesting tricks.


    **************************
    On Mon, 19 Dec 2022 11:00:45 -0600, Gerald Lester wrote:

    The 'global' command would have to be done inside of each procedure.
    Doing 'global' at the global scope level has no effect.


    Thanks. It's good to know.

    Still doable though. Only *more* tedious.

    --
    Luc


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