Tcl Script: Invalid command name return when executing proc body - return

In a Tcl script, I want to catch the return of a Tcl proc in order to execute some finalization actions.
For example my code could be as follows:
proc X10 { a } { return [expr $a * 10] }
proc procF {} {
set a 13
catch {[info body X10]} __result
return $__result
}
procF
The previous code gives me an error: invalid command name " return [expr $a * 10] "
Although that replacing info body X10 with return [expr $a * 10] works as expected. What I initially thought is that both of them are exchangeable and should give the same output. So, why the first gives an error and what is the difference between both of them ?

Your code is failing because you are getting the body of X10 and treating that as a command name. Tcl doesn't split things up automatically for you — you have to ask for it — and this is a critical language safety factor. You'd have to do something like this:
proc procF {} {
set a 13
catch {eval [info body X10]} __result
return __result
}
or this (because the first argument to catch is a script):
proc procF {} {
set a 13
catch [info body X10] __result
return __result
}
But I'd actually be inclined in your case (as presented exactly, and trying to interpret what you've said) to do:
proc procF {} {
set a 13
catch {X10 $a} __result
return __result
}
Note also that if you did this:
proc procF {} {
set a 13
catch {info body X10} __result
return __result
}
then the result would be the definition of X10 without it being evaluated.

Related

Groovy value is not apending in jenkins pipeline

artifactVersion = getVersion('build.gradle')
println artifactVersion[enter image description here][1]
def getVersion(String fileName) {
readFile(env.WORKSPACE+"/"+fileName).split("\n").each { line ->
if ((line =~ /version (.*)/).count > 0) {
echo line
def m = (line =~ /version (.*)/)[0]
echo m[1].replaceAll('"','').toString()
println m[1].replaceAll('-SNAPSHOT','').toString()
return m[1].replaceAll('-SNAPSHOT','').toString()
}
}
}
from getVersion api am getting the version 1.0 and that am attached in the console
but that 1.0 is not appending to the artifactVersion
One problem in your code is that the return in getVersion does not return out of the function.
The curly braces in list.each{ } create an anonymous function. Calling return inside will only return from the current iteration of the each function. A normal for loop or a combination of find/findAll and collect (map in other languages) would be better.
See also Groovy Closures and list methods.

Capture Success Message in Snowflake Stored Procedure

I have several Snowflake Stored Procedures and when they are successful, it has the custom message that I created displayed, I would rather be displaying the same message that Snowflake shows in the Query Results window.
For Example, I execute a Stored Proc with the COPY TO statements. I would like the Successful execution of this Stored Proc to show the number of Rows successfully Exported. Can they success information be captured and displayed as easily as the Error messages are?
Yes, you can do this using JavaScript stored procedures. When Snowflake runs a query that returns only a status message, it returns it as a table with a single column "status" and a single row with the status. You can return that value. You may want to consider what happens if there's a SQL error: handle it locally in the SP or throw the error so the calling session knows there was an error. Either way the status return will show an error message if there is one.
Here's a sample using JavaScript SP. It also has some helper functions that I use routinely to execute single value queries and non-query statements just looking for a return value:
create or replace procedure SampleSP()
returns string
language javascript
as
$$
try{
return ExecuteNonQuery("create table MY_NATION_TABLE as select * from SNOWFLAKE_SAMPLE_DATA.TPCH_SF1.NATION;");
}
catch(err){
return err;
}
// ----------------------------------------------------------------------------------
// Main function above; helper functions below
function ExecuteNonQuery(queryString) {
return ExecuteSingleValueQuery("status", queryString)
}
function ExecuteSingleValueQuery(columnName, queryString) {
var out;
cmd1 = {sqlText: queryString};
stmt = snowflake.createStatement(cmd1);
var rs;
try{
rs = stmt.execute();
rs.next();
return rs.getColumnValue(columnName);
}
catch(err) {
if (err.message.substring(0, 18) == "ResultSet is empty"){
throw "ERROR: No rows returned in query.";
} else {
throw "ERROR: " + err.message.replace(/\n/g, " ");
}
}
return out;
}
$$;
-- Run this twice to see the effect of an error. You can remove the try block
-- in the main function of the SP to generate a SQL error instead of just
-- returning a string with the error text
call SampleSP();

How catch exception using Iteratee.foreach in Future

I'm using Play Framework 2.2 and ReactiveMongo. I'm iterating trough all received entries from ReactiveMongo, and getting some property from single entry. Sometimes it throws Exception of inexistent property, how should I catch it, for now using simple "recover" doesn't work.
val cursor:Cursor[JsObject] = // QUERY FOR DATA
val processingData = cursor.enumerate().apply(Iteratee.foreach { doc =>
(doc \ "property")
}
processingData.map { data =>
Logger.info(s"$data")
None
}.recover {
case e =>
Logger.error(s"Error during parsing $e")
None
}
Iteratee.foreach always return Unit type, so value processingData will not contain data and enumerator apply some Iteratee only attach iteratee to emumerator, but don't run it. I think, this must solve your problem:
val cursor:Cursor[JsObject] = // QUERY FOR DATA
val getData = Enumeratee.mapM[JsObject]{doc =>
Future(doc \ "property") //use future to catch exception here
}
val processingData: Future[scala.List[JsObject]] = cursor.enumerate() &> getData .run Iteratee.getChunks

Printing using fmt::Display

I am trying to print an enum (or structure) using fmt::Display. Though the code compiles and gets to the display method, it doesn't print the value.
pub enum TestEnum<'a> {
Foo(&'a str),
Bar(f32)
}
impl<'b> fmt::Display for TestEnum <'b> {
fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
println!("Got this far");
match self{
&TestEnum::Foo(x) => write!(f,"{}",x),
&TestEnum::Bar(x) => write!(f,"{}",x),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_print() {
let cell = TestEnum::Str("foo");
println!("Printing");
println!("{}",cell); // No output here
}
}
I tried using {:?} and {} but to no avail.
This happens because Rust test program hides stdout of successful tests. You can disable this behavior passing --nocapture option to test binary or to cargo test command this way:
cargo test -- --nocapture
PS: your code is broken/incomplete
The test runner seems to divert the standard output; you should consider using assert!, assert_eq! or other panicky ways to test your assertions rather than printing in tests.
Besides, your code fails to compile due to mismatching names. I got it working as expected from main:
use std::fmt;
pub enum TestEnum<'a> {
Foo(&'a str),
Bar(f32)
}
impl<'b> fmt::Display for TestEnum <'b> {
fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
match self {
&TestEnum::Foo(x) => write!(f, "{}", x),
&TestEnum::Bar(x) => write!(f, "{}", x),
}
}
}
fn main() {
let cell = TestEnum::Foo("foo");
println!("Printing");
println!("{}", cell);
}
Test output is redirected to a buffer when the test succeeds as to not mangle up with the test "FAILED" or "ok" messages.
If you just want to test something while developing your test, you can always add a panic!() at the end of your test to make sure it keeps failing and outputting all logging. Or as #AndreaP notes in his answer, you can use cargo test -- --nocapture to display the standard output of all tests.
Usually a test should not write to stdout, but instead write to a buffer and check whether that buffer contains what it should:
let cell = TestEnum::Foo("foo");
let mut buf = Vec::new();
let _ = write!(buf, "{}\n", cell);
assert_eq!(&buf, b"foo\n");
If you truly want to output something, you need to write directly to stdout.
let _ = write!(io::stdout(), "{}\n", cell);
but this will mix with the test's output:
test tests::blub ... foo
ok
PlayPen

Stop code when a condition is true

I am trying to build a safety that will check for a condition that will either be true or false. This will be called multiple times through out a long bit of code. if the condition is true it will cause the rest of the code to stop. I cant seem to figure it out. Can someone point me in the right direction? By the way Exit will not work as it will close the whole program that I use.
proc _CheckEsc {} {
if {condition is true} {
return
}
return
}
proc testType {} {
set TestResult 0
while {$TestResult < 10} {
_CheckEsc;
incr TestResult
}
return;
}
You can make _CheckEsc stop it's caller by using some of the more advanced features of return. In particular, we can use it to make _CheckEsc act itself like a break or a return.
This mechanism is very much like throwing an exception in other languages (and in fact you can regard Tcl as having special exception classes for return, break and continue, except things are rather more complicated than that under the covers).
Making the caller's loop stop
proc _CheckEsc {} {
if {condition is true} {
return -code break
}
}
Making the caller return
proc _CheckEsc {} {
if {condition is true} {
return -level 2
# Or, if you want to return a value from the caller:
### return -level 2 "the value to return"
}
}
Note that the -level option isn't supported in Tcl 8.4 and before; that limits what you can do with it, but your use case works provided you do this instead:
proc _CheckEsc {} {
if {condition is true} {
return -code return
# Or, if you want to return a value from the caller:
### return -code return "the value to return"
}
}
Will something like this works for you?
proc _CheckEsc {} {
return {condition is true}; # I don't know what you have here
}
proc testType {} {
set TestResult 0
while {_CheckEsc && $TestResult < 10} {
incr TestResult
}
}
You can help us out by being more specific of what _CheckEsc does.

Resources