This question already has answers here:
How can I pull data out of an Option for independent use?
(3 answers)
Closed 1 year ago.
I have a function which takes 4 nullable BigUint parameters and return a tuple of Option type. I am calling this function in an iterative fashion and I am trying to figure how to handle None values as I want to treat them explicitly. I have the following uncompilable code:
use num_bigint::BigUint; // 0.4.0
fn add_one(
px: &Option<BigUint>,
py: &Option<BigUint>,
qx: &Option<BigUint>,
qy: &Option<BigUint>,
) -> (Option<BigUint>, Option<BigUint>) {
if px.is_none() && py.is_none() {
(*qx, *qy)
} else if px == qx {
(None, None)
} else {
(px + 1u32, py + 1u32)
}
}
With the error:
error[E0369]: cannot add `u32` to `&Option<BigUint>`
--> src/lib.rs:14:13
|
14 | (px + 1u32, py + 1u32)
| -- ^ ---- u32
| |
| &Option<BigUint>
error[E0369]: cannot add `u32` to `&Option<BigUint>`
--> src/lib.rs:14:24
|
14 | (px + 1u32, py + 1u32)
| -- ^ ---- u32
| |
| &Option<BigUint>
How do I evaluate Option to its corresponding type?
First, it's important to remember that an Option<T> is not a T. Even if it contains one, it's not itself one. It's a box which may or may not be empty. This is in contrast to a language like Kotlin where T? is actually a T or possibly null.
With that out of the way, it sounds like you want to take px and py and, if they contain values, add one to them, and if they don't then leave them empty. That's a perfect use case for map.
(px.map(|x| x+1u32), py.map(|x| x+1u32))
As a general piece of advice, in Java and Kotlin you're going to spend a lot of time using if statements and imperative logic to suss out your null values. In Rust, you're primarily going to do that using the standard library methods on Option. Get to know them; they're really quite helpful and encompass a lot of patterns you use frequently that, in other languages, might just be done with copious explicit null-checks.
Related
Problem
I've just caught my self writing dynamic assertion that depends on a constant usize::MAX.
I wrote:
u128::try_from(letters.len())
.expect("No suppor for platform with `max pointer value` >= 2**128.")
where letters.len() is an instance of usize.
Instead, I'd like my code to fail to compile on so rare (if existing) platforms with "pointers size >= 2**128".
I already know/read:
I've read a similar question (suggested by community).
It shows methods to assert concrete size of pointer.
eg. #[cfg(not(target_pointer_width = "64"))]
I want my code to be very flexible. It's enough for usize::MAX<=u128::MAX && usize::MIN>=u128::MIN to be true.
Small reflection (maybe solution)
After some thinking, I concoct a solution that works quite good, both in my head & on the currently tested Debian with x64 architecture and Rust 1.60.
Code: const _:()= assert!(usize::BITS<=u128::BITS);
Do you know any cleaner & edge-case-proof resolution?
assert!() is fine. assert!() is only available in const contexts since Rust 1.57.0, so if you need to support older versions you can use the static_assertions crate. The idea is to replace assert!() with the following constant expression:
const _: [(); 0 - (!(usize::BITS <= u128::BITS)) as usize] = [];
Now, if the expression evaluates to true, its negation evaluates to false, and false as usize is zero. So we're declaring a zero-length array and everything is fine.
However, if the expression evaluates to false, its negation is true, and true as usize == 1. 0usize - 1usize overflows - and that is an error.
The downside is that it generates a pretty obscure error message:
error[E0080]: evaluation of constant value failed
--> src/lib.rs:1:15
|
1 | const _: [(); 0 - (!(usize::BITS > u128::BITS)) as usize] = [];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
(I swapped the condition so it will be false).
I use a nifty class that evaluates string expressionsand converts them to their math equivalent :
# Taken out of context for MVCE
import ast
import operator as op
OPERATORS = {
ast.Add: op.add,
ast.Sub: op.sub,
ast.Mult: op.mul,
ast.Div: op.truediv,
ast.Pow: op.pow,
ast.BitXor: op.xor,
ast.USub: op.neg
}
def eval_expr(expr):
return eval_(ast.parse(expr, mode='eval').body)
def eval_(node):
if isinstance(node, ast.Num): # <number>
value = node.n
elif isinstance(node, ast.BinOp): # <left> <operator> <right>
value = OPERATORS[type(node.op)](eval_(node.left), eval_(node.right))
elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1
value = OPERATORS[type(node.op)](eval_(node.operand))
else:
raise TypeError(node)
return value
x = eval_expr("1 + 2")
print(x)
PyCharm code inspection highlights the instances of type(node.op) as problematic:
Expected type 'Type[Add | Sub | Mult | Div | Pow | BitXor | USub]' (matched generic type '_KT'), got 'Type[operator]' instead
Expected type 'Type[Add | Sub | Mult | Div | Pow | BitXor | USub]' (matched generic type '_KT'), got 'Type[unaryop]' instead
The class seems to function just fine, but my OCD wants to know how this could be refactored to avoid the inspection warnings. Or is this a PyCharm inspection gremlin?
The type checker is warning you that your dictionary that maps AST node types for operators to their implementations is incomplete. The type checker knows all of the possible types of node.op (which it seems to be describing as subtypes of the ast.operator and ast.unaryop parent types), and has noticed that your dictionary doesn't handle them all.
Since there are operators that you haven't included, it's possible for a parsable expression (like, say "2 << 5" which does a left shift, or "~31" which does a bitwise inversion) to fail to be handled by your code.
While I don't use PyCharm and thus can't test it for myself, you can probably satisfy its type checker by adding some error handling to your code, so that operator types you don't support will still be dealt with appropriately, rather than causing an uncaught exception (such as a KeyError from the dictionary) to leak out. For instance, you could use OPERATORS.get(type(node.op)) and then test for None before calling the result. If the operator type isn't in the dictionary, you'd raise an exception of your own.
This question already has answers here:
Is there currently anyway to concatenate two or more string literal types to a single string literal type in TypeScript right now?
(3 answers)
Closed 2 years ago.
I know its possible to create Type LayoutType = "Left" | "Right" | "Top" | "Bottom" | "VCenter", is it possible to create a type that would result in "Left,VCenter"? Or am I looking at creating a string literal for every possible type?
For this use case you could add a type Type LayoutTypes = LayoutType[]; which is an array which can accept multiple values that you specified for type LayoutType.
It is not possible in Typescript at the moment.
You can try use tuples
type LayoutType = ["Left" | "Right" | "HCenter", "Top" | "Bottom" | "VCenter"];
const layout: LayoutType = ["Left", "VCenter"]
Check it in Typescript Playground
This question already has an answer here:
How do I convert between numeric types safely and idiomatically?
(1 answer)
Closed 3 years ago.
I want the following
(2u128.pow(x)) as u64
but such that it succeeds for x < 64 and fails for x >= 64.
As you correctly pointed out yourself, you should use TryFrom, but you should also make sure the exponentiation itself doesn't overflow, by using u128::checked_pow instead of u128::pow:
use std::convert::TryFrom;
let x = 129;
let y = 2u128.checked_pow(x).expect("Number too big for exponentiation");
let z = u64::try_from(y).expect("Number too big for cast");
(playground link)
Okay, found the answer, there is TryFrom.
use std::convert::TryFrom;
u64::try_from(2u128.pow(x)).expect("Number too big for cast.")
from here which I somehow missed with my first search.
I have trouble writing a parameterized test with Spock, when one the parameter needs the pipe character, for instance because its a flag computation.
def "verify inferInputType()"() {
expect:
inputType == mPresenter.inferInputType(opt)
where:
opt | inputType
0 | 0
EDITTEXT_TYPE_ALPHANUM | InputType.TYPE_CLASS_TEXT
EDITTEXT_TYPE_NUM | InputType.TYPE_CLASS_NUMBER
EDITTEXT_TYPE_FLOAT | (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)
}
The test fails with the following error message :
Row in data table has wrong number of elements (3 instead of 2) # line 25, column 9.
EDITTEXT_TYPE_FLOAT | InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL
^
The only way I find to make it work is to wrap the parameter inside an closure, like that
EDITTEXT_TYPE_FLOAT | {InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL}()
But it's ugly, if someone has a better solution, please tell me.
You should be able to do:
InputType.TYPE_CLASS_NUMBER.or( InputType.TYPE_NUMBER_FLAG_DECIMAL )
Not sure if that is better ;-)