Perl6 Exception handling print X::AdHoc message on the CATCH section - raku

Suppose I have the following code:
try {
X::Any.new(payload => 'Error !',message => "fff").throw;
# die "message";
CATCH {
# when X::HTTP { say $_.url(); }
when X::AdHoc { say $_; }
}
}
How can I print the message or the payload? I tried the following :
say $_.message ;
say $_.payload ;
but it didn't work.

X::AdHoc.new(payload=>"anything that got .Str").throw;
CATCH {
default {
printf('"%s", "%s", "%s"', .^name, .payload.^name, .message)
}
}
# OUTPUT«"X::AdHoc", "Str", "anything that got .Str"»

If your interested in a minimalist way...
A CATCH block turns its enclosing block into a try block so the "try { ... }" is redundant. Within the CATCH block you have an implicit perl6 switch statement with the exception object as the topic. This is why "when" and "default" keywords can be used. Finally, exception objects stringify to their message attribute which gives us;
CATCH {
default { .say }
}
Replace .say with .payload.say to get the payload.

Related

Elegant way to write when inside a for loop?

I can write something like this (elem here is an XML::Element but it doesn't really matter):
for $elem.nodes {
when XML::Element { ... }
when XML::Text { ... }
...
default { note qq{Ignoring unknown XML node "$_".} }
}
which looks nice, but doesn't give me a readable name for $_ inside the code using it, which is why I'd prefer to write this:
for $elem.nodes -> $child {
when XML::Element { ... }
when XML::Text { ... }
...
default { note qq{Ignoring unknown XML node "$child".} }
}
but this doesn't work because now $_ isn't set, and so I actually need to write
for $elem.nodes -> $child {
given $child {
when XML::Element { ... }
when XML::Text { ... }
...
default { note qq{Ignoring unknown XML node "$child".} }
}
}
which is a bit redundant and adds an extra level of indentation.
It's definitely not the end of the world, but am I missing some simple way to have both a readable variable name and avoid given?
You can bind the variable above the when statements, it's a little uglier but it does the job.
for $elem.nodes {
my $child = $_;
when XML::Element { say 'I am XML!' }
when XML::Text { say 'I am text!' }
default { say "I am default: $child" }
}
Edit: In Raku I think it is perfectly reasonable to stick to using $_ seeing as the idea of $_ has been around for quite some time.
for #a -> $x { {
when 2 { say "$x ... a" }
when 4 { say "$x ... b" }
} given $x }
naughty double curlies and a post-given?

RxJava how to handle Error without Quit flow

My scenario is like this:
During a flow ,if there is an error happened during an element processing (in this example element is "three"), I still want keep processing the others.
In this example: I want to print "1,2,4,5" however, it just print "1 ,2".
Observable<String> numbers = Observable.just("1", "2", "three", "4", "5");
numbers.map(v->{
return Integer.parseInt(v);
}).onErrorResumeNext(error->{return Observable.just(-1);})
.filter(v-> {
System.out.println("filter value smaller than 0");
return v>0;
})
.subscribe(s -> {
System.out.println(s);
});
}
I checked doc, "onErrorResumeNext" will instead relinquish control to the Observable returned from resumeFunction.
Is there way to print "1,2,4,5"?
The flow stops because there is a crash in map. The only way to avoid the flow being stopped is to not let map crash in your example. Put the parseInt into a try-catch and return -1 from the catch part.
Observable<String> numbers = Observable.just("1", "2", "three", "4", "5");
numbers.map(v -> {
try {
return Integer.parseInt(v);
} catch (NumberFormatException ex) { // <--------------------------------------
return -1;
}
})
.filter(v -> {
System.out.println("filter value smaller than 0");
return v > 0;
})
.subscribe(s -> {
System.out.println(s);
});

Why can't my validator of element-ui-form be called?

Here are codes:
**validateCode:[{validator:(rule, value, callback)=>{
if (!value) {
callback(new Error('you have to input code'))
} else if(this.radioValue=="mobile"){
validatingCo(this.user.mobile,value).then((res)=>{
if(!res.code==20000){
return callback(new Error('the code is wrong or expired'))
} else{
callback()
}
})
}
else{
validatingCo(this.user.email,value).then((res)=>{
if(!res.code==20000){
return callback(new Error('the code is wrong or expired'))
} else{
callback()
}
})
}
}, trigger:'blur'}]
Unfortunately, it didn't execute and no error.
I want to know how to handle it.
I think the problem might be caused by this line:
if(!res.code==20000){
// Some stuff here
}
It should probably read:
if(res.code!=20000){
// Some stuff here
}
!res.code will always evaluate to either true or false. So !res.code==20000 will always be false. No matter the input the following error callback will never execute:
return callback(new Error('the code is wrong or expired'))
Here's a little demo to show that "bar" will always be printed out
function simple_if(number) {
if (!number == 20000) {
return "foo"
} else {
return "bar"
}
}
console.log(`res=20000. Expect 'bar': ${simple_if(2000)}`)
console.log(`res=3. Expect 'foo': ${simple_if(3)}`)
console.log(`res=0. Expect 'foo': ${simple_if(0)}`)

How to retrieve the underlying error from a Failure Error?

When trying to open a broken epub/ZIP file with epub-rs, the zip-rs crate error (which doesn't use Failure) is wrapped into a failure::Error by epub-rs. I want to handle each error type of zip-rs with an distinct error handler and need a way to match against the underlying error. How can I retrieve it from Failure?
fn main() {
match epub::doc::EpubDoc::new("a.epub") {
Ok(epub) => // do something with the epub
Err(error) => {
// handle errors
}
}
}
error.downcast::<zip::result::ZipError>() fails and error.downcast_ref() returns None.
You can downcast from a Failure Error into another type that implements Fail by using one of three functions:
downcast
downcast_ref
downcast_mut
use failure; // 0.1.5
use std::{fs, io};
fn generate() -> Result<(), failure::Error> {
fs::read_to_string("/this/does/not/exist")?;
Ok(())
}
fn main() {
match generate() {
Ok(_) => panic!("Should have an error"),
Err(e) => match e.downcast_ref::<io::Error>() {
Some(e) => println!("Got an io::Error: {}", e),
None => panic!("Could not downcast"),
},
}
}
For your specific case, I'm guessing that you are either running into mismatched dependency versions (see Why is a trait not implemented for a type that clearly has it implemented? for examples and techniques on how to track this down) or that you simply are getting the wrong error type. For example, a missing file is actually an std::io::Error:
// epub = "1.2.0"
// zip = "0.4.2"
// failure = "0.1.5"
use std::io;
fn main() {
if let Err(error) = epub::doc::EpubDoc::new("a.epub") {
match error.downcast_ref::<io::Error>() {
Some(i) => println!("IO error: {}", i),
None => {
panic!("Other error: {} {:?}", error, error);
}
}
}
}

How to check if function throw an error in DOH?

I'm trying to check if a function throws error, and made this:
define([
'doh/runner',
'app/Obj'
], function(
doh,
Obj
){
doh.register('Test Obj exception', [
function () {
try {
new Obj(); // should throw error
} catch(e) {
doh.t(e, 'should give an error if no parameters given');
}
}
]);
Obj.js file:
...
constructor: function (args){
if (!args) { throw 'Error' }
...
}
...
But maybe where is some right method for this thing in Doh ? Can someone explain? Thanks
You want doh.assertError()
Example:
doh.assertError(TypeError, this.field, "setValue",
[{
CreatedOn: "March 10th, 2014"
}],
"setValue() on an invalid format should throw a TypeError");
This example test shows that DOH catches and displays an error correctly.
This gist is the test, and contains this code:
var Obj = function () {
if (arguments.length < 1) {
throw 'Error - There are ' + arguments.length + ' arguments';
}
};
define(["doh/runner"], function(doh){
var tests = [
function () {
new Obj(); // wrong call
}
];
doh.register('Test Obj exception', tests);
});
The screenshot shows the 1 error, and the error msg from the Error thrown: