Menu

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

obsolete: 8.6b1.1
open
5
2011-10-01
2009-10-30
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
     
  • Alexandre Ferrieux

    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.

     
  • Alexandre Ferrieux

    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.

     
  • Donal K. Fellows

    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...

     
  • Donal K. Fellows

    • labels: 105658 --> 07. Variables
    • assigned_to: dkf --> msofer
     
  • Donal K. Fellows

    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