What is the cleanest way to convert &str types to numeric types? - type-conversion

I find myself reading large CSV files and collecting the numerical elements into a Vec<&str>. Thereafter I have to convert them to numeric types and the simplest way I've found to do that is to implement a function like this:
fn to_u32(str: &str) -> u32
{
let str_num: Option<u32> = str.parse();
match str_num
{
Some(num) => num,
None => panic!("Failed to read number"),
}
}
This seems like a fairly common operation so I've sifted through the reference docs but haven't found anything that matches it. Is there a cleaner way to do this?

The Option type has a large variety of adapter methods which can be used to munge the data around more nicely than repeated matchs.
For example, there's unwrap and expect for just extracting the data out of a Some, panicking if the Option is None. The expect method is actually the closest to your written code: str.parse().expect("Failed to read number.").
However, it can often makes sense to use other the functions listed there, to propagate errors, avoiding the hard "crash" of a panic and allowing users (or yourself) to handle errors more centrally and with more control. It also often makes sense to use Result for this, which gives you the chance to pass along more information in the error case, and also allows one to use the try! macro, that said, one can easily define an equivalent of try! for Option:
macro_rules! option_try {
($e: expr) => {
match $e {
Some(x) => x,
None => return None
}
}
}

Well, you can use unwrap() to avoid pattern matching, but you should do it sparingly - with unwrap() you can't handle the actual parse error, so if the string does not represent a number, it'll panic:
let str_num: u32 = str.parse().unwrap();
if let is also an option:
if let Some(str_num) = str.parse::<u32>() {
// ...
}
You can also use unwrap_or() if you want to specify some default value:
let str_num: u32 = str.parse().unwrap_or(42);
Or you can use unwrap_or_default() which employs Default instance for u32:
let str_num: u32 = str.parse().unwrap_or_default();

Related

How to collect mongodb::Cursor into a Vec in rust

I'm trying to use the .find() method in mongodb. The output yeilds a mongodb::Cursor. I'm unable to convert the cursor into a vector so that I can wrap them in a json and send it to my front-end. This is the following idea I've tried
The following error message is:
the trait bound `Vec<user_model::User>: Extend<Result<user_model::User, mongodb::error::Error>>` is not satisfied\nthe following other types implement trait `Extend<A>`
I've already included and use futures::StreamExt; and use futures::TryFutureExt; and tried out .try_next() and .map() instead of .collect(), still cant parse it
Converting an element in the cursor to a User might fail. You may only collect into a Vec of Result with .collect().
let serial: Vec<Result<User, _>> = users.collect().await;
The easy way to get to Vec<User> here would be to use .try_collect(). Just make sure to handle the Err correctly and not just use unwrap as I've done here.
let serial: Vec<User> = users.try_collect().await.unwrap();
Here is how I managed this in one of my projects.
I simply iterate over the cursor calling next and push each item in a vector. I used the Document type to collect the results.
Using a match for each result allows to handle the errors properly, because extraction may fail.
let mut results: Vec<Document> = Vec::new();
while let Some(result) = cursor.next().await {
match result {
Ok(document) => {
results.push(document);
}
_ => {
return HttpResponse::InternalServerError().finish();
}
}
}

Converting Pascal's variant record to Swift

I am converting a program written in Pascal to Swift and some Pascal features do not have direct Swift equivalents such as variant records and defining sets as types. A variant record in Pascal enables you to assign different field types to the same area of memory in a record. In other words, one particular location in a record could be either of type A or of type B. This can be useful in either/or cases, where a record can have either one field or the other field, but not both. What are the Swift equivalents for a variant record and a set type like setty in the Pascal fragment?
The Pascal code fragment to be converted is:
const
strglgth = 16;
sethigh = 47;
setlow = 0;
type
setty = set of setlow..sethigh;
cstclass = (reel,pset,strg);
csp = ^constant; /* pointer to constant type */
constant = record case cclass: cstclass of
reel: (rval: packed array [1..strglgth] of char);
pset: (pval: setty);
strg: (slgth: 0..strglgth;
sval: packed array [1..strglgth] of char)
end;
var
lvp: csp
My partial Swift code is
let strglgth = 16
let sethigh = 47
let setlow = 0
enum cstclass : Int {case reel = 0, pset, strg}
var lvp: csp
Any advice is appreciated. Thanks in advance.
Variant records in Pascal are very simular to unions in C.
So this link will probably be helpful:
https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_structs_and_unions_in_swift
In case the link ever goes dead, here's the relevant example:
union SchroedingersCat {
bool isAlive;
bool isDead;
};
In Swift, it’s imported like this:
struct SchroedingersCat {
var isAlive: Bool { get set }
var isDead: Bool { get set }
init(isAlive: Bool)
init(isDead: Bool)
init()
}
That would be more like a functional port. It does not seem to take care of the fact that Variant records are actually meant to use the same piece of memory in different ways, so if you'd have some low-level code that reads from a stream or you have a pointer to such a structure, this might not help you.
In that case you might want to try just reserving some bytes, and write different getters/setters to access them. That would even work if you'd have to port more complex structures, like nested variant types.
But overall, if possible, I'd recommend to avoid porting such structures too literally, and use idioms that match Swift better.

How to Define Generic “Invalid“ Values for Different Types

In my app, I am using Integers, Doubles, Floats, and CGFloats to represent a number of different values. According to my app’s semantic, these values may become “invalid“, a state which I represent using a reserved value, i. e. -1. The simplest approach to make this usable in code would be this:
anIntVariable = -1
aFloatVariable = -1
aDoubleVariable = -1.0
...
To get away from this convention driven approach and increase readability and adaptability I defined a number of extensions:
extension Int {
static var invalid = -1
}
extension Float {
static var invalid = -1.0
}
extension Double {
static var invalid = -1.0
}
...
So the above code would now read:
anIntVariable = .invalid
aFloatVariable = .invalid
aDoubleVariable = .invalid
...
It does work. However, I’m not really happy with this approach. Does anyone of you have an idea for a better way of expressing this?
To add some complexity, in addition to simple types like Int, Float, or Double, I also use Measurement based types like this:
let length = Measurement(value: .invalid, unit: UnitLength.baseUnit())
Extra bonus point if you find a way to include “invalid“ measurements in your solution as well...
Thanks for helping!
Some Additional Thoughts
I know I could use optionals with nil meaning “invalid”. In this case, however, you’d have additional overhead with conditional unwrapping... Also, using nil as “invalid” is yet another convention.
It isn’t better or worse, just different. Apple uses “invalid” values in its own APIs, i. e. the NSTableViewmethod row(for:) will return -1 if the view is not in the table view. I agree, however, that this very method perfectly illustrates that returning an optional would make a lot of sense...
I'd use optionals for that.
If you want lack of value and invalid value to be different states in your app, i'd suggest creating a wrapper for your values:
enum Validatable<T> {
case valid(T)
case invalid
}
And use it like that:
let validValue : Validatable<Int> = .valid(5)
let invalidValue : Validatable<Int> = .invalid
var validOptionalDouble : Validatable<Double?> = .valid(nil)
validOptionalDouble = .valid(5.0)
let measurement : Validatable<Measurement> = .invalid
etc.
You can then check for value by switch on that enum to access the associated value like this:
switch validatableValue {
case .valid(let value):
//do something with value
case .invalid:
//handle invalid state
}
or
if case .valid(let value) = validatableValue {
//handle valid state
}
etc

Unused variables and '_'

I am learning swift using learnxinyminutes.com
I'm having a hard time understanding a component of on of the examples on the site (below), namely the use of underscore in the let statements instead of variable names.
// Variadic Args
func setup(numbers: Int...) {
let _ = numbers[0]
let _ = numbers.count
}
I understand that swift wants you to use underscore if you never declare the variable, but 1) why would you want to declare variables you never use? And 2) is there a way to get those values out if you used _. And, 3) if so, how?
1) why would you want to declare variables you never use?
Generally you don't! There are some cases though where you might want to, such as the example Danny Buonocore gave. Another example might be this: say you want to check that a variable is non-nil before you do something, though you do not need that variable for the subsequent code. (A guard statement is probably more useful in these situations).
if let _ = titleString {
// Do something that doesn't use titleString, but where it being non-nil means this operation is valid
}
Another example is with Swift functions. Names for a second, third, etc. parameter must be identified whenever calling a function. For example:
func externalizedParameters(first: Int?, second: Int?) {
...
}
Which is called using externalizedParameters(5, second: 6).
But if you are doing something trivial, and the function name already makes it clear what the two parameters are, such as with a swap operation, you might not want to force the caller to explicitly state the name of the second parameter. In that case, you can use '_' because you don't care about the name of that externalized parameter:
func swap(first: Int?, _ second: Int?) {
...
}
This can then be called as swap(5, 6) as opposed to swap(5, second: 6).
2) is there a way to get those values out if you used _. & 3) if so, how?
No. You need to name the variable if you want to use the value.
One example would be a loop where you don't necessarily need the index.
for _ in 0..<10 {
}
In swift you can also externalize the names of the parameters. This allows the caller to pass by name, rather than order:
func myFunction(param1:String, param2:String) {
}
myFunction(param2: "second value", param1: "first value");
If you don't want to externalize the name of a parameter, you can include an underscore before it, like so:
func myFunction(param1:String, _ param2:String) {
}
In this case, you must pass the value to set param2 to as the second argument, and you cannot use the naming scheme seen in the first example.
If you need to use the value inside of a variable, declare it with a name and not _. The underscore says, I know this call returns a value but we're not going to use it, so it doesn't need a name. Swift emits warnings for unused function call results, so this is a way to suppress that warning.

SequenceType / GeneratorType That Can Also Throw?

I'm in the process of learning Swift and as an exercise, I'm writing a wrapper around SQLite. As I was experimenting, I realized that for queries that return rows (like SELECT), I could implement the SequenceType / GeneratorType protocols so that I can return a set of data for each sqlite3_step that I perform.
In practice, sqlite3_step either returns a row or is done, but in theory, it could error out. I'm not doing anything crazy with SQLite. It's just a simple data store for me, so I'm not rewriting schemas on the fly or potentially ripping the database out from under itself, but the fact remains that IN THEORY sqlite3_step could fail.
The question then is, is there a proper way to handle errors in the SequenceType / GeneratorType pattern? GeneratorType's next method doesn't support a throws parameter and returning nil just dictates the end of a sequence. Would there be a good way to handle the error and propagate it up the chain?
You have a few options, depending on what you're looking for.
If you need the Sequence to be lazy, you could use a ResultType kind of thing:
enum SQLiteRow<T> {
case Success(T), FailureTypeOne, FailureTypeTwo
}
Then, your next() method would return a SQLiteRow<T>?, where T is the type of your row.
This fits in nicely with for-loops, as you can use it like this:
for case let .Success(row) in queries {...
so the successful queries are bound to the row variable. This is only if you want to filter out the failed queries. If you wanted to stop everything, you could switch within the for loop, or have a function like this:
func sanitize<
S : SequenceType, T where
S.Generator.Element == SQLiteRow<T>
>(queries: S) -> SQLiteRow<[T]> {
var result: [T] = []
result.reserveCapacity(queries.underestimateCount())
for query in queries {
switch query {
case let .Success(x): result.append(x)
case .FailureTypeOne: return .FailureTypeOne
case .FailureTypeTwo: return .FailureTypeTwo
}
}
return SQLiteRow.Success(result)
}
That will take a sequence of possibly-failed queries, and give back either a sequence of successful queries (if none failed), or a failure type representing the first failure it came across.
However, the second option there isn't lazy. Another eager way to do it would be to use map, which (as of the latest beta) can take a closure which throws:
func makeQuery(x: String) throws -> String {
return x
}
let queries = ["a", "b", "c"]
do {
let successful = try queries.map(makeQuery)
} catch {
// handle
}
Unfortunately the lazy version of map doesn't throw, so you have to evaluate the whole sequence if you want to throw like this.