|
From: Fredderic on 30 Jun 2008 16:29 On Mon, 09 Jun 2008 15:19:22 -0500, "Gerald W. Lester" <Gerald.Lester(a)cox.net> wrote: > George Peter Staplin wrote: >> From what I see they don't get byte compiled. Tcl_EvalEx is used, >> and it has no Tcl_Obj to use to cache the internal bytecode >> representation. > I think the reason has to do with the % substitution. One thing that I did last time I wrote a Tk app, was to write myself a small [wrap] function that takes the script you wish to bind, and sets it up as a [proc] with a unique name (eg. tk-binding-NNN, where NNN is an incrementing global counter). ie: [wrap {s} { ... bind script here ... }] might return: tk-binding-6 %s proc tk-binding-6 {s} { ... bind script here ... } You can also use [regexp] to extract a list of % substitution tokens, [regsub] to change them into regular variable references (or you could use [regexp -indices] and do it yourself), and [lsort -unique] to produce the appropriate argument list. I did that in a separate [wrap-auto] proc that in turn called the main [wrap] proc, since it does occasionally get a little over-zealous. But it was good being able to write your handler script right there, without having to worry about it being beastly inefficient. I've never looked into it any further than that, but it should be possible to pass in the name of the object so that the wrap function can destroy the procedure when the object itself gets destroyed. You can also apply [catch] and re-throw wrapping (or something similar), to get those [break]s through. (eg. return -level 0 -code {*}[tk-...]) Fredderic
From: Andreas Leitgeb on 1 Jul 2008 03:29 Fredderic <my-name-here(a)excite.com> wrote: > [wrap {s} { ... bind script here ... }] > might return: tk-binding-6 %s > proc tk-binding-6 {s} { ... bind script here ... } My first thought was: "why not use lambdas?", but this was quickly answered: "because they, too, would undergo %-substitution, thus the gain would be void. Most likely it's still better, to just place the code in a well-named, explicitly created procedure, and call that from bind :-)
From: Fredderic on 1 Jul 2008 14:28 On 01 Jul 2008 07:29:31 GMT, Andreas Leitgeb <avl(a)gamma.logic.tuwien.ac.at> wrote: > Fredderic <my-name-here(a)excite.com> wrote: >> [wrap {s} { ... bind script here ... }] >> might return: tk-binding-6 %s >> proc tk-binding-6 {s} { ... bind script here ... } > My first thought was: "why not use lambdas?", but this was > quickly answered: "because they, too, would undergo %-substitution, > thus the gain would be void. Yup... Basically no advantage at all. The [wrap] method pulls the actual script out of Tk's sight entirely, constraining the substitutions to the argument list to the newly-created proc. That reminds me of that annoying lambdaExpr "feature" where the byte-compiling is broken if you try to read the lambda's arguments list... I've got a number of cases where I'd like to be able to do: apply $lambda [dict mget $dict [lindex $lambda 0]] (dict mget returns the values corresponding to a list of keys) > Most likely it's still better, to just place the code in a > well-named, explicitly created procedure, and call that from > bind :-) Yeah, but not nearly as much fun. ;) Seriously, for one-liners I'd do it directly inline and accept the hit. For long handlers where you can't see both ends on a standard 24-line terminal, I'd do it exactly like that; define the proc and then use a bind line to attach it. However, I find the [wrap] method perfect for 3-10 line scripts, where you can take in the whole thing with a glance. One way to avoid having to pass the widgets name, might actually be to wrap the entire bind statement. I'm going by vague memory here, but the second argument will usually be the widgets name, and the last argument will be the script. So if you wrote the script in lambda-form, your [wrap] command could lift that off and do what it needs to do, lift off the second word to bind a destructor, and then just [uplevel] the statement as provided (of course, substituting the script lambda with the appropriate command). Fredderic
From: miguel on 1 Jul 2008 15:04 Fredderic wrote: > That reminds me of that annoying lambdaExpr "feature" where the > byte-compiling is broken if you try to read the lambda's arguments > list... I've got a number of cases where I'd like to be able to do: > > apply $lambda [dict mget $dict [lindex $lambda 0]] > (dict mget returns the values corresponding to a list of keys) Mmhhh ... maybe let [info args] and [info body] inspect lambdas too? Or add a [info lambda] that will return a copy of the lambda as list without shimmering the original? In the meantime: why don't you do that just once and cache it yourself, if you are so worried? if {![info exists arg($lambda)]} {set arg($lambda) [lindex $lambda 0]} apply $lambda [dict mget $dict $arg($lambda)] Another option is to create them with some redundancy set lambda2 [list $lamArgs [list $lamArgs $lamBody]] ... lassign $lambda2 lamArgs lambda apply $lambda [dict mget $dict $lamArgs]
From: Robert Heller on 1 Jul 2008 16:19 At Wed, 2 Jul 2008 04:28:29 +1000 Fredderic <my-name-here(a)excite.com> wrote: > > On 01 Jul 2008 07:29:31 GMT, > Andreas Leitgeb <avl(a)gamma.logic.tuwien.ac.at> wrote: > > > Fredderic <my-name-here(a)excite.com> wrote: > >> [wrap {s} { ... bind script here ... }] > >> might return: tk-binding-6 %s > >> proc tk-binding-6 {s} { ... bind script here ... } > > My first thought was: "why not use lambdas?", but this was > > quickly answered: "because they, too, would undergo %-substitution, > > thus the gain would be void. > > Yup... Basically no advantage at all. The [wrap] method pulls the > actual script out of Tk's sight entirely, constraining the > substitutions to the argument list to the newly-created proc. > > > That reminds me of that annoying lambdaExpr "feature" where the > byte-compiling is broken if you try to read the lambda's arguments > list... I've got a number of cases where I'd like to be able to do: > > apply $lambda [dict mget $dict [lindex $lambda 0]] > (dict mget returns the values corresponding to a list of keys) > > > > Most likely it's still better, to just place the code in a > > well-named, explicitly created procedure, and call that from > > bind :-) > > Yeah, but not nearly as much fun. ;) Seriously, for one-liners I'd do > it directly inline and accept the hit. For long handlers where you > can't see both ends on a standard 24-line terminal, I'd do it exactly > like that; define the proc and then use a bind line to attach it. > However, I find the [wrap] method perfect for 3-10 line scripts, where > you can take in the whole thing with a glance. > > One way to avoid having to pass the widgets name, might actually be to > wrap the entire bind statement. I'm going by vague memory here, but > the second argument will usually be the widgets name, and the last > argument will be the script. So if you wrote the script in > lambda-form, your [wrap] command could lift that off and do what it > needs to do, lift off the second word to bind a destructor, and then > just [uplevel] the statement as provided (of course, substituting the > script lambda with the appropriate command). One can also do interesting things using a SNIT widgetadaptor. And certainly with SNIT mega and meta widgets. > > > Fredderic > -- Robert Heller -- Get the Deepwoods Software FireFox Toolbar! Deepwoods Software -- Linux Installation and Administration http://www.deepsoft.com/ -- Web Hosting, with CGI and Database heller(a)deepsoft.com -- Contract Programming: C/C++, Tcl/Tk
|
Next
|
Last
Pages: 1 2 Prev: Tcl/Tk 8.5.3 RELEASED Next: Bugs awaiting fixes (wa Re: Tcl/Tk 8.5.3 RELEASED) |