Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#4452 [info exists array(elem)] deletes array searches

obsolete: 8.6b1.1
open
miguel sofer
5
2011-10-01
2009-10-30
Joe Mistachkin
No

It seems the act of checking for an array element has the effect of deleting pending array searches.
Why does INST_EXIST_STK in TEBC call TclObjLookupVarEx with createPart2 non-zero?

Example:

set s [array startsearch tcl_platform]

#
# NOTE: Try this test with and without this [puts] line commented.
#
puts stdout [info exists tcl_platform([clock seconds])]; # improperly invalidates array search.

set result [list]
while {[array anymore tcl_platform $s]} {
if {[array nextelement tcl_platform $s] eq "user"} then {
lappend result user
}
}

set result; # should be "user"
catch {array donesearch tcl_platform $s}
catch {unset -nocomplain result s}

Discussion

  • miguel sofer
    miguel sofer
    2009-10-30

    The BC implementation has to mimic exactly the non-compiled implementation.

    As [info exists] triggers read traces on the array and the traces could well create new elements, the effect on searches is inevitable (or at least very hard to avoid).

    The comments at the start of TclVarTraceExists attempt an explanation:

    /*
    * The choice of "create" flag values is delicate here, and matches the
    * semantics of GetVar. Things are still not perfect, however, because if
    * you do "info exists x" you get a varPtr and therefore trigger traces.
    * However, if you do "info exists x(i)", then you only get a varPtr if x
    * is already known to be an array. Otherwise you get NULL, and no trace
    * is triggered. This matches Tcl 7.6 semantics.
    */

     
  • miguel sofer
    miguel sofer
    2009-10-30

    • labels: 105683 --> 105658
    • assigned_to: msofer --> dkf
     
  • Naively, I'd associate search cancellation with _writing_ into the array. Why are we being so shy ?

     
  • Jeffrey Hobbs
    Jeffrey Hobbs
    2009-10-30

    Because traces can modify anything at read or write time would be my guess.

     
  • Loud and clear, but why not wait for the code to actually do the modification instead of bailing out on mere suspicion ?

     
  • Joe Mistachkin
    Joe Mistachkin
    2009-11-02

    We should either fix the underlying issue (phantom array elements being created and destroyed, invalidating array searches) or at least document it. My opinion is that we should fix it if at all possible as having [info exists] invalidate array searches on any array element (i.e. this has nothing to do with env) violates the Principle of Least Surprise.

     
  • I agree in principle, but only if we can figure out a way to not cause any other surprises.

    Since this has been this way for a long time, there's no need to hurry. Longer term, I want to remove the assumption that arrays use hash tables so that we can, for example, map more directly onto getenv/setenv (or a BLT vector or a metakit DB) without having a spare-wheel hash in between. That's not about to happen for 8.6...

     
    • labels: 105658 --> 07. Variables
    • assigned_to: dkf --> msofer
     
  • For the record, TEBC sets createPart2 because that's what the code I was converting from did (i.e., I didn't change [info exists] at all). I do not know if that's the right thing to do.

    There does seem to be some complexity with traces, i.e., where a whole array trace creates the element. :-( Assigning the master of variables.

     
  • Poor Yorick
    Poor Yorick
    2013-02-14

    I've made some changes to TclCallVarTraces, which allows TclVarTraceExists to set createPart2 to 0 when calling TclLookupVar. This fixes the underlying issue described by mistachkin. The changes can be found here:

    https://ynform.org/fossil/tcl/info/45968549a8