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
Post a Comment