Should this Perl 6 CATCH block be able to change variables in the lexical scope? - exception

I'm playing with resumable exceptions. In this example, I try to numify something that doesn't numify. I catch that and attempt to give the $value variable an appropirate value then resume execution:
try {
my $m = 'Hello';
my $value;
$value = +$m;
put "Outside value is 「{$value.^name}」";
CATCH {
when X::Str::Numeric {
put "「$m」 isn't a number!";
put "Inside value is 「{$value.^name}」";
$value = 0;
put "Inside value is now 「$value.」";
.resume;
}
default {
put "Unhandled type 「{.^name}」";
}
}
put "End of the block";
}
put "Got to the end.";
The CATCH block can see the lexical scope it is in, a resuming picks up where it left off. I expected that I'd be able to change $value and have the rest of the block use that value, but outside of the CATCH the value becomes a Failure:
「Hello」 isn't a number!
Inside value is 「Any」
Inside value is now 「0.」
Outside value is 「Failure」
End of the block
Got to the end.
What's up?

Inside of a try block, use fatal takes effect, to cause lazy exceptions returned from method or sub calls to throw immediately. Outside the lexical scope of a try block, note that:
my $value = +$m;
Would result in a Failure being assigned to $value. The try turns it into something more like:
my $value = force-failure(+$m);
Which you could imagine being defined as something like:
sub force-failure(Mu \f) { f.sink if f ~~ Failure; f }
(I'm hand-waving because the compiler spits out the code to do this inline and with a few optimizations).
In the case under consideration, the .sink triggers the exception to the thrown. The CATCH block runs. The .resume indicates that we do not wish to unwind the call stack as would normally happen with a CATCH block, so execution continues inside of force-failure, which then returns f - the Failure. This all happens prior to the assignment in the mainline code to $value; the Failure is therefore assigned, overwriting the value given by the CATCH block.
Unfortunately, you can't escape this with //= because that does the test before running the RHS (which is what we usually want it to do). However, it is possible to do:
my $numified = +$m;
my $value //= $numified;
Of course, this is all a bit of a contrived example, since the normal idiom would be to not have a try block at all, and to write it as:
my $value = +$m // 0;
Thus taking advantage of the Failure. In general, resumable exceptions need a good amount of care, because in many cases code will not be written expecting a resumption to take place. It turns out that the code generated for fatalizing a Failure is one such piece.

Related

How to understand tcl's return

I wanted to get the number of parameters of a proc from tcl and didn't want it to be printed in tclsh, so I used return
When I execute the following statement in the c environment
string tclCmd = "info args " + tclProcName + ";return";
Tcl_Eval(interp, tclCmd.c_str());
string res = Tcl_GetStringResult(interp);
The result of the execution is not printed in tclsh, but at the same time it is not possible to get the correct value
So I tried to write it like this:
string tclCmd = "info args " + tclProcName;
Tcl_Eval(interp, tclCmd.c_str());
string res = Tcl_GetStringResult(interp);
Tcl_Eval(interp, "return");
This works, but I don't understand why it doesn't print out immediately when Tcl_Eval is executed, and the return statement is still valid afterwards
The return command is not helpful at all there. It triggers an exception condition that comes out of Tcl_Eval as a return code of TCL_RETURN instead of TCL_OK (that is converted by the outer structure of a procedure, if that is relevant). Instead, you should call Tcl_ResetResult(interp); after you have finished with the return value (or have taken another reference to it) to put things back to how they were before your command implementation was invoked.

having difficulty to understand this while loop?

I have difficulty understanding this while loop:
The Condition
The condition:
while {1 == [string equal $result Completed]} {
could be written more shortly as:
while {$result eq "Completed"} {
That is, it means "do the body while $result is equal to the literal string Completed.
The Body
The body of the loop calls $mode run (what exactly that does isn't described here). Then it gets the result by calling $mode getRunResult and extracts the first word of the list, and assigns it to the variable result. The final step of the loop is to use switch to print a message whenever $result is either Error or SolverFailure (it also has clauses for Completed and StopCritera, but that's empty so nothing happens).
The Overall Effect
The loop calls $mode run until the first word of the result of $mode getRunResult after that run is not Completed.
$mode is a handle returned by pw::Application begin ExtrusionSolver $block, and $mode end is called after the loop terminates, presumably to clean things up.

While Iterator in groovy

I'm trying to create a loop to read, for example, 4200 users from 1000 to 1000 but I can't get it to cut when it reaches the end. I tried it with if, for and I couldn't do it.
I have programmed in JAVA but with Groovy I see that the structure is different.
urlUsers = urlUsers.concat("/1/1000");
List<UserConnectorObject> usersList = null;
while({
gesdenResponse = GesdenUtils.sendHttpRequest(urlUsers, "LOOKUP", null,
request.getMetaData()?.getLogin(), request.getMetaData()?.getPassword());
log.info("Users data in JSON: "+gesdenResponse.getOutput())
usersList = GesdenUtils.fromJSON(gesdenResponse.getOutput(), GesdenConstants.USER_IDENTITY_KEY);
usersList.size() == 10;
log.info("List size in JSON "+usersList.size());
}()) continue
Groovy has lots of loop structures, but it is crucial to separate the regular ones (lang built-ins) and the api functions which take closure as an argument
take closure - no plain way to escape
If you want to iterate from A to B users, you can use, for instance,
(10..20).each { userNo -> // Here you will have all 10 iterations
if ( userNo == 5) {
return
}
}
If something outrageous happens in the loop body and you cannot use return to escape, as loop boddy is a closure (separate function) and this resurn just exits this closure. Next iteration will happen just after.
use regular lang built-in loop structures - make use of break/continue
for (int userNo in 1..10) { // Here you will have only 5 iterations
if (userNo == 5) {
break
}
}
It looks like your closure always return falsy because there is no explicit return, and the last statement evaluated is the call to log.info(String) which returns void.
Use an explicit return or move/delete the log statement.

Is is possible to set the default values of parameters to be the return of a function? (TCL)

In TCL is it possible to have the default values of parameters be the return value of a function call?
proc GetParameterValue { } {
# calculation for value...
return value
}
proc TestFunction { {paramVal [GetParameterValue]} } {
puts $paramVal
}
TestFunction
This results in printing "[GetParameterValue]". Rather than calling the procedure GetParameterValue. Is this possible to do in TCL or do I need to redesign this bit of code?
The default values of parameters can only be constants that you compute at the time of declaration of the procedure (most commonly, they're literals which means you don't need to use list to do the construction):
proc TestFunction [list [list paramVal [GetParameterValue]]] {
...
}
To compute a default value at procedure call time, you have to move the calculation into the body of the procedure. There's a few ways to do the detection of whether to do the calculation, but they come down to three options: using a marker value, getting a count of words in the call, and taking full control of parsing.
Using a marker value
The trick to this is to find some value that is really unlikely to be passed in. For example, if this is to be a piece of text shown to the user, a value with nothing but an ASCII NUL in it is not going to occur; put that in the default then you can tell whether you've got the default and can substitute with what the complex code provides.
proc TestFunction {{paramVal "\u0000"}} {
if {$paramVal eq "\u0000"} {
set paramVal [GetParameterValue]
}
...
}
Getting a count of words in the call
This relies on the capabilities of the info level introspection command. In particular, info level 0 reports the full list of actual arguments to the current procedure. A bit of counting, and we can can know whether a real value was passed.
proc TestFunction {{paramVal "dummy"}} {
if {[llength [info level 0]] < 2} {
# Note that the command name itself is always present
set paramVal [GetParameterValue]
}
...
}
It's a totally general approach, so there's no worry about the case where someone provides an unexpected edge case, but it's more complicated when you have multiple arguments as you need to work out how many arguments should be present and so on yourself. That is simple in this case, but gets progressively more difficult as you have more arguments.
Taking full control of parsing
Ultimately, you can also decide to make a procedure that takes full control of the parsing of its arguments. You do that by giving it a single argument, args, and then you can use any approach you want to handle the actual argument list. (I tend to not put the formal argument list in parentheses in this case only but that's just my own style.)
proc TestFunction args {
if {[llength $args] == 0} {
set paramVal [GetParameterValue]
} elseif {[llength $args] == 1} {
set paramVal [lindex $args 0]
} else {
# IMPORTANT! Let users discover how to use the command!
return -code error -errorcode {TCL WRONGARGS} \
"wrong # args: should be \"TestFunction ?paramVal?\""
}
...
}
This is currently the only way to do anything truly advanced, e.g., to have optional arguments before mandatory ones. It's also pretty much what you'd have to do in C if you implemented the command there, though adjusted for a different language. The downside is that it is definitely more work than using the built-in basic argument parsing support code provided by the implementation of the proc command.
This is meant as a complement to Donal's thorough answer. In the past, I sometimes resorted to the assistance of [subst] for computed defaults:
proc GetParameterValue {} { return computedDefault }
proc TestFunction {{paramVal [GetParameterValue]}} {
puts [subst -novariables $paramVal]
}
TestFunction; # returns "computedDefault"
TestFunction "providedValue"
TestFunction {$test}
This avoids the need for (implementing) full control over arguments, and is piggybacking onto the built-in argument handler. It also allows for using anonymous procs rather than explicitly named ones for computing the defaults:
proc TestFunction {{paramVal "[apply {{} { return computedValue }}]"}} {
puts [subst -novariables ${paramVal}]
}
TestFunction; # returns "computedDefault"
TestFunction "providedValue"
TestFunction {$test}
It goes without saying that there are also some assumptions behind, which turn into important restrictions depending on one's application case:
You must keep some discipline in using brackets for the defaults in the argument lists, and placing [subst] at the usage sites of the argument variable.
It assumes that you have some control over the arguments, or that you can guarantee that certain special-purpose characters are not valid members of the arguments' value domain.
Watch:
TestFunction {[xxx]}
throws
invalid command name "xxx"
and must be sanitized to
TestFunction {\[xxx\]}

How to implement a basic Lua function in Conky?

I am trying to add a function to my Conky which prints the length of a string for debug purposes. The code, inside a file called test.lua, is pretty trivial:
function test(word)
return string.len(word)
end
...and I load it like this. In my conky.config section I have:
lua_load = '/home/xvlaze/test.lua',
lua_draw_hook_pre = 'test'
...in the conky.text section I have:
${lua test "fooo"}
...where test is the name of the function and fooo the string to test.
The expected result should be a printed 4 in Conky, but instead of that I get:
conky: llua_do_call: function conky_test execution failed: /home/xvlaze/test.lua:2: attempt to index a nil value (local 'string')
conky: llua_getstring: function conky_test didn't return a string, result discarded
I have browsed through the documentation, but I can't find anything. Does anybody know where the failure is?
Several guidances on how to implement functions in Conky:
First of all: YOU MUST USE conky_ BEFORE YOUR FUNCTION'S NAME.
Otherwise, you will get the following error when running your Conky:
attempt to call a nil value
Secondly: YOU MUST ALWAYS RETURN A VALUE.
I don't mind repeating it - it is crucial. Otherwise, you will get:
function foobar didn't return a string, result discarded
function_result
...in your terminal, and your Conky will be left empty of values related to your extra code. Nothing will be printed regarding your function.
Last but not least: YOU MUST ALWAYS CALL YOUR FUNCTION LIKE:
lua_load = '/path/to/function.lua',
-- Whatever content...
${lua function_name function_parameter1 function_parameterN} -- In case you use more than one parameter.
In summary, a dummy function template could be:
MAIN FILE (conky.conf):
conky.config = {
-- Whatever content... Lua styled comments.
lua_load = '/path/to/function.lua',
}
conky.text = [[
# Whatever content... In this section comments are started with '#'!
${lua function_name parameter}
]]
FUNCTION FILE:
function conky_function_name(parameter)
-- Whatever content... Remember this is Lua, not conky.text syntax. Always use '--' comments!
return whatever -- No return, no party. A function MUST always return something!
end