4 ms·
It would work if they basically copy the current value of the identifiers (i.e. by-value, not by-reference). Or by capturing the procedure context. You can synt
by lilyball 5y ago
It would work if they basically copy the current value of the identifiers (i.e. by-value, not by-reference). Or by capturing the procedure context. You can synthesize the variable capture by hand but that would indeed force everything into a string, which is a potential performance issue and would also break any sort of automatic lifetime management.
Even just making it easier to have lambdas reference variables from their creation scope while the creation scope is still on the stack would be an improvement. Today you can use [info level] and then construct a lambda body that uses [upvar #$level …] to reference variables from the original scope, but it's a PITA. Or you could cram the level into a temporary namespace variable to avoid having to manually construct a body string, but it's still a PITA.
- pooryorick 5y ago[list apply {args body} $value1 $value2 ...] can be used to capture values without actually generating a string because even though conceptually a list is a string, it's actually stored internally as a list.
- int_19h 5y agoThe basic problem is, how do you even know that something is a variable reference? Remember, everything is a string. This means that the body of the lambda is also a string. Now you can require that it's an eval'able string at the point of creation, and parse it to identify any $var references. But you can only do that for the topmost level of the lambda, because it can contain nested strings - and you don't know which of those strings are code, and which aren't (since it's really the command to which the string is passed that decides to treat something as code or not). Furthermore, if you process $ like that, this won't work for any other command that takes a variable name as an argument, and does something to it.
- rightbyte 5y ago> The basic problem is, how do you even know that something is a variable reference? Isn't that by convention? Like there is a "upvar" to grab values of the prior stack.
- int_19h 5y ago"upvar" is explicit, there's no guesswork involved there. But how would you handle a lambda with a body like this? if {$foo == 1} { puts $bar } else { puts $baz } given that all the {}s are just non-expanded string literals, and what makes them be interpreted as code is the implementation of "if"? Sure, you can hardcode "if"; but the whole point of Tcl is that syntax constructs like that can be easily implemented as a library, which breaks if you have to special-case them in lambdas for them to work. Now if you used upvar, this kinda sorta works, but only so long as the lambda is immediately invoked by the function that it was passed to. If you want to pass it on, you'd have to wrap it in another lambda. And, of course, this only works for lambdas that don't escape.