tcl - Code that works in 8.4 is causing crash in 8.6, is there a better way to implement the functionality -


i have tcl utility makes easy ensure snippet of code run @ time control flow leaves current scope (of proc). crashes in tcl 8.6.6, i'm wondering if there "better" way implement functionality in tcl 8.6?

an example usage is:

proc test {file} {    set fh [open $file]    ::util::defer [list close $fh]    # ... bunch of stuff    # , if hit error    # [close $fh] evaluated return    # proc } 

it's worked great in tcl 8.4, , use on code.

as i'm still coming speed on functionality available in tcl 8.6, i'm asking how should ::util::defer proc written best take advantage of tcl 8.6?

here 8.4 implementation:

namespace eval ::util {} proc ::util::defer_impl {cmd args} {   uplevel 1 $cmd } proc ::util::defer {cmd} {   set vname _u_defer_var   # unique variable name   while {[uplevel 1 [list info vars $vname]] != ""} {     set vname ${vname}_   }   uplevel 1 [list set $vname $cmd]   # when variable unset, trigger call command   uplevel 1 [list trace add variable $vname unset [list ::util::defer_impl $cmd]]   # return chunk of code enabling user cancel if desired   return [list variable $vname unset [list ::util::defer_impl $cmd]] } 

edited add: appreciate answers. honest, have other syntactic sugar file handle, this:

proc test {file} {    set fh [::util::localfilehandle $file]    # stuff } 

i hoping more generic solution ::util::defer - because have 2 or 3 uses (at different locations) in same proc. yes, i'm leaving out error handling if doesn't exist or isn't readable.

note: have reported bug activestate , filed bug @ core.tcl.tk.

edited add buggy code: tcl code causes crash me, pared down essence (as opposed being full-blown ::util::defer).

# ---------------begin script------------------- package require itcl  proc ::try_uplevel {} {   return [uplevel 1 [list ::info vars _u_defer_var]] }  itcl::class ::test_class {   constructor {} {}    public proc test_via_proc {} {     ::try_uplevel   } }  ::test_class::test_via_proc # ---------------end script------------------- 

the pattern describe supported one; shouldn't crash (and indeed i can't reproduce crash 8.6.3 or tip of 8.6 support branch). problem has if have error during close (or other deferred script) won't report it, can see snippet (% prompt):

% apply {{} {     ::util::defer [list error boo]     puts hi }} hi %  

this part of why went quite bit of effort provide try command in 8.6. that, can this:

proc test {filename} {     set f [open $filename]     try {         # stuff $f     } {         close $f     } } 

it takes care of tricky things stitching errors thrown inside body , finally clause (the body exception info in -during option of finally clause's error exception info) if both places error can find out both.

% catch {     try {         error     } {         error b     } } x y 1 % puts $x b % puts $y -errorstack {inner {returnimm b {}}} -errorcode none -errorinfo {b     while executing "error b"} -errorline 5 -during {-code 1 -level 0 -errorstack {inner {returnimm {}}} -errorcode none -errorinfo {a     while executing "error a"} -errorline 3} -code 1 -level 0 

personally, i'd more inclined write this:

proc withreadfile {varname filename body} {     upvar 1 $varname f     set f [open $filename]     try {         return [uplevel 1 $body]     } {         close $f     } }  proc test {file} {     withreadfile fh $file {         # stuff $fh     } } 

your mileage may vary.


Comments

Popular posts from this blog

php - Permission denied. Laravel linux server -

google bigquery - Delta between query execution time and Java query call to finish -

python - Pandas two dataframes multiplication? -