I want to check if the result from a request is having any issue. I categorize it into two: i) server error, ii) something else that is not a success. The third category is, result actually being a success. However, in the third category, I don't want to do anything.
So, my desirable code is:
if res.status().is_server_error() {
panic!("server error!");
} else if !(res.status.is_success()){
panic!("Something else happened. Status: {:?}", res.status());
} else{
pass;
}
I am aware of other ways to achieve this result: using match, ifs instead of if else if. But I wanted to learn what is the corresponding keyword of pass, like we have in Python. My aim is: if result is successful, just move along, if not, there are two ways to handle that panic.
Behold!
if predicate {
do_things();
} else {
// pass
}
Or even better
if predicate {
do_things();
} // pass
Or as I’ve recently taken to calling it the implicit + pass system
if predicate {
do_things();
}
In all seriousness there is no pass and no need for a pass in rust. As for why it exists in python, check out this answer
Python needs pass because it uses indentation-based blocks, so it requires some syntax to "do nothing". For example, this would be a syntax error in a Python program:
# syntax error - function definition cannot be empty
def ignore(_doc):
# do nothing
count = process_docs(docs, ignore) # just count the docs
The ignore function has to contain a block, which in turn must contain at least one statement. We could insert a dummy statement like None, but Python provides pass which compiles to nothing and signals the intention (to do nothing) to the human reader.
This is not needed in Rust because Rust uses braces for blocks, so one can always create an empty block simply using {}:
// no error - empty blocks are fine
fn ignore(_doc: &Document) {
// do nothing
}
let count = process_docs(docs, ignore); // just count the docs
Of course, in both idiomatic Python and Rust, one would use a closure for something as simple as the above ignore function, but there are still situations where pass and empty blocks are genuinely useful.
Related
I have a rust program that has a function
‘is_input_sanitized’ that takes an input
String m, and checks if the input is free of special characters.The method is being used on a separate function in the following way.
let a = match is_input_sanitized(m) {
Ok(m) => m,
Err(_) => { return Err("error"); },
};
I am trying to convert this snippet into using ‘unwrap_or_else’ which will return an error when the input is not sanitized.I have read the documentation and have not been able to decipher a proper way to achieve this. Is this conversion possible?
unwrap_or_else is for extracting Result values. It sounds to me like you don't want to extract the result, so much as make a new one and propagate errors. You have two different things you want to do here. The first is that you want to change the error from whatever it started as (indicating by your _ in the pattern match) to something you control, and the second is that you want to return errors.
Replacing the error can be done with map_err, which takes a function (such as a closure) and applies that function to the error if the Result is an Err. If the result is Ok, then it returns the current Result unmodified.
The second problem, returning on Err, is exactly what the question mark operator was invented for.
Chaining results using match can get pretty untidy; luckily, the ? operator can be used to make things pretty again. ? is used at the end of an expression returning a Result, and is equivalent to a match expression, where the Err(err) branch expands to an early return Err(From::from(err)), and the Ok(ok) branch expands to an ok expression.
So what you're looking for is
let a = is_input_sanitized(m).map_err(|_| "error")?;
I'm trying to make an if statement comparing a String variable and a String to match exact values (without using match). Here is my code:
if &guess.trim().parse() == String::from("quit") { // TODO: Fix this
println!("Goodbye! The secret number was: {} and you attempted to guess it {} times!", secret_number, tries);
break;
}
guess is a String::new() which has been assigned a value through user input (io::stdin().read_line(&mut guess).expect("Unable to read line");)
When I run the code, I get an error from the above code snippet:
Does anyone know why I'm getting this error and how to fix it?
I have tried converting "quit" to String::from("quit") but it seems that the error is to do with the == and I'm not sure what &Result<_, _> is. Thanks!
In this situation parse() was superfluous, but in most other situations you resolve the error "something not implemented for Result" by extracting the actual value from the Result and using that rather than the Result itself. Your options for that are:
the ? operator to extract the value and propagate the error (if one occurred) to the caller,
the unwrap() or expect() methods to panic in case of error, and
pattern matching with match or if let, to handle the error case locally.
See the book chapter on Result for details.
Using if guess.trim() == "quit" fixed my problem. Thank you #eggyal!
How can I know if I actually need to return an l-value when using FALLBACK?
I'm using return-rw but I'd like to only use return where possible. I want to track if I've actually modified %!attrs or have only just read the value when FALLBACK was called.
Or (alternate plan B) can I attach a callback or something similar to my %!attrs to monitor for changes?
class Foo {
has %.attrs;
submethod BUILD { %!attrs{'bar'} = 'bar' }
# multi method FALLBACK(Str:D $name, *#rest) {
# say 'read-only';
# return %!attrs{$name} if %!attrs«$name»:exists;
# }
multi method FALLBACK(Str:D $name, *#rest) {
say 'read-write';
return-rw %!attrs{$name} if %!attrs«$name»:exists;
}
}
my $foo = Foo.new;
say $foo.bar;
$foo.bar = 'baz';
say $foo.bar;
This feels a bit like a X-Y question, so let's simplify the example, and see if that answers helps in your decisions.
First of all: if you return the "value" of a non-existing key in a hash, you are in fact returning a container that will auto-vivify the key in the hash when assigned to:
my %hash;
sub get($key) { return-rw %hash{$key} }
get("foo") = 42;
dd %hash; # Hash %hash = {:foo(42)}
Please note that you need to use return-rw here to ensure the actual container is returned, rather than just the value in the container. Alternately, you can use the is raw trait, which allows you to just set the last value:
my %hash;
sub get($key) is raw { %hash{$key} }
get("foo") = 42;
dd %hash; # Hash %hash = {:foo(42)}
Note that you should not use return in that case, as that will still de-containerize again.
To get back to your question:
I want to track if I've actually modified %!attrs or have only just read the value when FALLBACK was called.
class Foo {
has %!attrs;
has %!unexpected;
method TWEAK() { %!attrs<bar> = 'bar' }
method FALLBACK(Str:D $name, *#rest) is raw {
if %!attrs{$name}:exists {
%!attrs{$name}
}
else {
%!unexpected{$name}++;
Any
}
}
}
This would either return the container found in the hash, or record the access to the unknown key and return an immutable Any.
Regarding plan B, recording changes: for that you could use a Proxy object for that.
Hope this helps in your quest.
Liz's answer is full of useful info and you've accepted it but I thought the following might still be of interest.
How to know if returning an l-value ... ?
Let's start by ignoring the FALLBACK clause.
You would have to test the value. To deal with Scalars, you must test the .VAR of the value. (For non-Scalar values the .VAR acts like a "no op".) I think (but don't quote me) that Scalar|Array|Hash covers all the l-value super-types:
my \value = 42; # Int is an l-value is False
my \l-value-one = $; # Scalar is an l-value is True
my \l-value-too = #; # Array is an l-value is True
say "{.VAR.^name} is an l-value is {.VAR ~~ Scalar|Array|Hash}"
for value, l-value-one, l-value-too
How to know if returning an l-value when using FALLBACK?
Adding "when using FALLBACK" makes no difference to the answer.
How can I know if I actually need to return an l-value ... ?
Again, let's start by ignoring the FALLBACK clause.
This is a completely different question than "How to know if returning an l-value ... ?". I think it's the core of your question.
Afaik, the answer is, you need to anticipate how the returned value will be used. If there's any chance it'll be used as an l-value, and you want that usage to work, then you need to return an l-value. The language/compiler can't (or at least doesn't) help you make that decision.
Consider some related scenarios:
my $baz := foo.bar;
... (100s of lines of code) ...
$baz = 42;
Unless the first line returns an l-value, the second line will fail.
But the situation is actually much more immediate than that:
routine-foo = 42;
routine-foo is evaluated first, in its entirety, before the lhs = rhs expression is evaluated.
Unless the compiler's resolution of the routine-foo call somehow incorporated the fact that the very next thing to happen would be that the lhs will be assigned to, then there would be no way for a singly or multiply dispatched routine-foo to know whether it can safely return an r-value or must return an l-value.
And the compiler's resolution does not incorporate that. Thus, for example:
multi term:<bar> is rw { ... }
multi term:<bar> { ... }
bar = 99; # Ambiguous call to 'term:<bar>(...)'
I can imagine this one day (N years from now) being solved by a combination of allowing = to be an overloadable operator, robust macros that allow overloading of = being available, and routine resolution being modified so the above ambiguous call could do something equivalent to resolving to the is rw multi. But I doubt it will actually come to pass even with N=10. Perhaps there is another way but I can't think of one at the moment.
How can I know if I actually need to return an l-value when using FALLBACK?
Again, adding "when using FALLBACK" makes no difference to the answer.
I want to track if I've actually modified %!attrs or have only just read the value when FALLBACK was called.
When FALLBACK is called it doesn't know what context it's being called in -- r-value or l-value. Any modification comes after it has already returned.
In other words, whatever solution you come up with will being nothing to do per se with FALLBACK (even if you have to use it to implement some other aspect of whatever it is you're trying to do).
(Even if it were, I suspect trying to solve it via FALLBACK itself would just make matters worse. One can imagine writing two FALLBACK multis, one with an is rw trait, but, as explained above, my imagination doesn't stretch to that making any difference any time soon, if ever, and could only happen if the above imaginary things happened (the macros etc.) and the compiler was also modified to pay attention to the two FALLBACK multi variants, and I'm not at all meaning to suggest that that even makes sense.)
Plan B
Or (alternate plan B) can I attach a callback or something similar to my %!attrs to monitor for changes?
As Lizmat notes, that's the realm of Proxys. And thus your next SO question... :)
"When you've found the treasure, stop digging!"
I'm wanting to use more functional programming in Groovy, and thought rewriting the following method would be good training. It's harder than it looks because Groovy doesn't appear to build short-circuiting into its more functional features.
Here's an imperative function to do the job:
fullyQualifiedNames = ['a/b/c/d/e', 'f/g/h/i/j', 'f/g/h/d/e']
String shortestUniqueName(String nameToShorten) {
def currentLevel = 1
String shortName = ''
def separator = '/'
while (fullyQualifiedNames.findAll { fqName ->
shortName = nameToShorten.tokenize(separator)[-currentLevel..-1].join(separator)
fqName.endsWith(shortName)
}.size() > 1) {
++currentLevel
}
return shortName
}
println shortestUniqueName('a/b/c/d/e')
Result: c/d/e
It scans a list of fully-qualified filenames and returns the shortest unique form. There are potentially hundreds of fully-qualified names.
As soon as the method finds a short name with only one match, that short name is the right answer, and the iteration can stop. There's no need to scan the rest of the name or do any more expensive list searches.
But turning to a more functional flow in Groovy, neither return nor break can drop you out of the iteration:
return simply returns from the present iteration, not from the whole .each so it doesn't short-circuit.
break isn't allowed outside of a loop, and .each {} and .eachWithIndex {} are not considered loop constructs.
I can't use .find() instead of .findAll() because my program logic requires that I scan all elements of the list, nut just stop at the first.
There are plenty of reasons not to use try..catch blocks, but the best I've read is from here:
Exceptions are basically non-local goto statements with all the
consequences of the latter. Using exceptions for flow control
violates the principle of least astonishment, make programs hard to read
(remember that programs are written for programmers first).
Some of the usual ways around this problem are detailed here including a solution based on a new flavour of .each. This is the closest to a solution I've found so far, but I need to use .eachWithIndex() for my use case (in progress.)
Here's my own poor attempt at a short-circuiting functional solution:
fullyQualifiedNames = ['a/b/c/d/e', 'f/g/h/i/j', 'f/g/h/d/e']
def shortestUniqueName(String nameToShorten) {
def found = ''
def final separator = '/'
def nameComponents = nameToShorten.tokenize(separator).reverse()
nameComponents.eachWithIndex { String _, int i ->
if (!found) {
def candidate = nameComponents[0..i].reverse().join(separator)
def matches = fullyQualifiedNames.findAll { String fqName ->
fqName.endsWith candidate
}
if (matches.size() == 1) {
found = candidate
}
}
}
return found
}
println shortestUniqueName('a/b/c/d/e')
Result: c/d/e
Please shoot me down if there is a more idiomatic way to short-circuit in Groovy that I haven't thought of. Thank you!
There's probably a cleaner looking (and easier to read) solution, but you can do this sort of thing:
String shortestUniqueName(String nameToShorten) {
// Split the name to shorten, and make a list of all sequential combinations of elements
nameToShorten.split('/').reverse().inject([]) { agg, l ->
if(agg) agg + [agg[-1] + l] else agg << [l]
}
// Starting with the smallest element
.find { elements ->
fullyQualifiedNames.findAll { name ->
name.endsWith(elements.reverse().join('/'))
}.size() == 1
}
?.reverse()
?.join('/')
?: ''
}
In the example below why must I place (let one) next to .Success for the code to work? Why is it not (let = one) or just (one)? I am trying to understand the syntax.
enum Status {
case Success(String)
case Failure(String)
}
let downloadStatus = Status.Failure("Network connection unavailable")
switch downloadStatus {
case .Success(let one):
println(one)
case .Failure(let two):
println(two)
}
This is known as value binding. The value contained in the enum value is temporarily bound to the variable in the case. If you use let the value will be bound to a constant and if you use var it will be bound to a variable.
let downloadStatus = Status.Failure("Network connection unavailable")
switch downloadStatus {
case .Success(let one):
println(one)
case .Failure(var two):
two += "!!!" // two is a var, so I can modify it
println(two)
}
I am trying to understand the syntax
There is nothing to understand. That simply is the syntax for extracting the associated value from an enum case. It's like the masks when you play Calvinball - no one is allowed to question them.
Now, you might object that this syntax is kind of clumsy and annoying. You have to go through the rigmarole of a switch statement just to pull out the associated value?!? That is a perfectly valid complaint, people have been making it since Swift was unveiled in June 2014, and the folks at Apple know that it's kind of weird and may change it in future. But for now, that's the syntax, and that's all there is to know about it.