From Option to iterator [duplicate] - iterator

This question already has answers here:
How to convert an Option<T> to an iterator of zero or one element?
(1 answer)
How can I iterate on an Option<Vec<_>>?
(4 answers)
Closed 4 years ago.
I have a function which consumes an iterator:
fn func<T: iter::Iterator<Item = char>>(i: T) {
//...
}
I need to write a function whose input is an Option<char> (type char is not important here, just for illustrative purpose), and depends on the value of input, it should create an empty or an once iterator. My solution is:
use std::iter;
fn option_iter(input: Option<char>) {
let i: Box<iter::Iterator<Item = char>> = if let Some(input) = input {
Box::new(iter::once(input))
} else {
Box::new(iter::empty())
};
}
I find this ugly because of type erasure by Box. I cannot use:
let i = if let Some(input) = input {
iter::once(input)
} else {
iter::empty()
};
func(i);
because the compiler complains the types of two branches are different. Is there any method which does not use Box for this situation?

Option has an iter method that does what you want.

Related

How to create a 2darray in kotlin of objects? [duplicate]

This question already has answers here:
2D Array in Kotlin
(11 answers)
Closed 1 year ago.
I am genuinely shocked on how hard it is to find a good explanation on how to create a 2d array in Kotlin for an object.
These are my attempts from what I have found neither here on stack and online neither work, why? how do I create a 2d array of objects not built into Kotlin!!!
var matrix : Array<Array<myObject?>> = null
//var arr2D = Array(10) { Array(10) { myObject(this) } }
for (i in 0 until 9) {
for (j in 0 until 9) {
matrix[i][j] = myObject(this)
}
}
It says "null can not be a value of a non-null type" so I guess I have to use an arrayofnulls(), but cannot find a source can someone help me or give me a source?
This is how you create a 2D Array in Kotlin with a user made object. ArrayofNulls allows you to set all indexes in the array to null and then just initialize them later with a for loop!
val matrix = Array(10) {
arrayOfNulls<myObject?>(
10
)
}

What is the cleanest way to return the error when matching a Result<T, E>? [duplicate]

This question already has answers here:
Is there any way of doing unwrap_or_return an Error (any error)
(1 answer)
What is this question mark operator about?
(4 answers)
Closed 2 years ago.
I'm calling a function that returns a Result<T, E> and I want to handle the Ok case but return the Err as is if an error is returned. What is the cleanest way to do this?
For example, I have:
fn example() -> Result<(), Error> {
match foo() {
Ok(v) => bar(v),
Err(e) => Err(e),
}
}
What are some alternate forms of writing this? It feels weird to re-wrap e in another Err in every call in the stack. Also, every call is basically 4 lines of boilerplate... I'm just looking for a way to simplify and make it more readable. My desire is to have it return the error if error, else process the result value.
Rust includes an 'error propagation' operator, ?. If the value of the Result it is called on is Ok it will unwrap and return the inner value. If the value is Err it will return from the function and pass the Err to the caller.
fn example() -> Result<(), Error> {
let v = foo()?;
bar(v);
}

how to make control flow based on nullable variable in Kotlin? [duplicate]

This question already has answers here:
Swift 'if let' statement equivalent in Kotlin
(16 answers)
Closed 4 years ago.
let say I have this variable
val number : Int? = 12
I want to make control flow based on the variable, if the variable is null then do something, otherwise do something else
in Swift I can make something like this:
if let number = number {
print(number)
} else {
// do something else
}
I actually can do like this
if number != null {
print(number!!) // I want to avoid exclamation mark like this
} else {
// do something else
}
but I want to avoid exclamation mark, like in print(number!!)
I previously though that I can do something like this
number?.let {
print(it)
} else {
// else block is not available in let in Kotlin
}
so how to solve this ?
The ?. means it will be executed only if the left side is not null.
The ?: operator executes the right side only if the left side is not null.
You may have something like:
theExpression().toCompute().theNumber?.let { number ->
print("This is my number $number
} ?: run {
print("There is no number")
}
Here we use T.let extension function for the then clause and run{ } (extension) function for the else clause.
Warning: The semantics is that you expected to return non-null value from the let {...} closure to avoid the `run {..} closure from being executed. Thus the code like:
number?.let { null } ?: run { 42 } === 42 (and not null)

Differences in for-loops. Swift v.s. Objective-C [duplicate]

This question already has answers here:
Removing from array during enumeration in Swift?
(9 answers)
Closed 6 years ago.
In this loop we have the potential to reduce the number of items in the loop while processing it. This code works fine in Obj-C, but the Swift loops don't get the message that an item has been removed and end up overflowing the array.
In Objective-C, we had:
for(int i = 4; i < staticBlocks.count; i++)
{
PlayerSprite* spr = [staticBlocks objectAtIndex:i];
[spr setPosition:CGPointMake(spr.position.x, spr.position.y-1)];
if(spr.position.y < -1000)
{
[staticBlocks removeObject:spr];
[spr removeFromParent];
}
if(spr.blockTypeIndex == Block_Type_Power_Up)
{
[spr update];
}
}
In Swift I know of these options:
//for i in 4.stride(to: staticBlocks.count, by: 1){ //crashes
//for i in 4..<staticBlocks.count{ //crashes
for var i = 4; i < staticBlocks.count; i += 1 { //works, but is deprecated
let spr = staticBlocks.objectAtIndex(i) as! PlayerSprite
spr.position = CGPointMake(spr.position.x, spr.position.y-1)
if(spr.position.y < -1000)
{
staticBlocks.removeObject(spr)
spr.removeFromParent()
//break
}
if(spr.blockTypeIndex == k.BlockType.PowerUp)
{
spr.update()
}
}
In this specific case, it really isn't a problem for me to use a break statement (which is currently commented out) to kill the loop and prevent the crash, but it doesn't seem like the proper fix. I assume there will come a time when I need to know how do do this correctly. Is there a non deprecated way to do a for loop, one which processes the count each pass?
A related, unanswered question.
Is the for loop condition evalutaed each loop in swift?
I don't know how to link to a specific answer, but this code did what I needed. Marking as duplicate now.
Removing from array during enumeration in Swift?
var a = [1,2,3,4,5,6]
for (i,num) in a.enumerate().reverse() {
a.removeAtIndex(i)
}
This is because in Swift you cannot remove items from an array while you are iterating over it.
From this question Removing from array during enumeration in Swift?
you can see that you should be using the filter function instead of using a for loop.
For example, don't do this:
for (index, aString: String) in enumerate(array) {
//Some of the strings...
array.removeAtIndex(index)
}
Do something like this:
var theStrings = ["foo", "bar", "zxy"]
// Filter only strings that begins with "b"
theStrings = theStrings.filter { $0.hasPrefix("b") }
(Code example from this answer)
Additionally, it should be noted that filter won't update the array, it will return a new one. You can set your array to be equal to that array afterwards.
An additional way to solve the issue, from the same question is to do this:
var a = [1,2,3,4,5,6]
for (i,num) in a.enumerate().reverse() {
a.removeAtIndex(i)
}
print(a)

How do I convert a list of Option<T> to a list of T when T cannot be copied? [duplicate]

This question already has an answer here:
How do I avoid unwrap when converting a vector of Options or Results to only the successful values?
(1 answer)
Closed 4 years ago.
How do I take a Vec<Option<T>>, where T cannot be copied, and unwrap all the Some values?
I run into an error in the map step. I'm happy to move ownership of the original list and "throw away" the Nones.
#[derive(Debug)]
struct Uncopyable {
val: u64,
}
fn main() {
let num_opts: Vec<Option<Uncopyable>> = vec![
Some(Uncopyable { val: 1 }),
Some(Uncopyable { val: 2 }),
None,
Some(Uncopyable { val: 4 }),
];
let nums: Vec<Uncopyable> = num_opts
.iter()
.filter(|x| x.is_some())
.map(|&x| x.unwrap())
.collect();
println!("nums: {:?}", nums);
}
Playground
Which gives the error
error[E0507]: cannot move out of borrowed content
--> src/main.rs:17:15
|
17 | .map(|&x| x.unwrap())
| ^-
| ||
| |hint: to prevent move, use `ref x` or `ref mut x`
| cannot move out of borrowed content
In Rust, when you need a value, you generally want to move the elements or clone them.
Since move is more general, here it is, only two changes are necessary:
let nums: Vec<Uncopyable> = num_opts
.into_iter()
// ^~~~~~~~~~~~-------------- Consume vector, and iterate by value
.filter(|x| x.is_some())
.map(|x| x.unwrap())
// ^~~------------------ Take by value
.collect();
As llogiq points out, filter_map is specialized to filter out None already:
let nums: Vec<Uncopyable> = num_opts
.into_iter()
// ^~~~~~~~~~~~-------- Consume vector, and iterate by value
.filter_map(|x| x)
// ^~~----- Take by value
.collect();
And then it works (consuming num_opts).
As pointed out by #nirvana-msu, in Rust 1.33 std::convert::identity was added which can be used instead of |x| x. From the documentation:
let filtered = iter.filter_map(identity).collect::<Vec<_>>();
You don't need to copy the Uncopyable at all, if you are OK with using a Vec of references into the original Vec:
let nums: Vec<&Uncopyable> = num_opts.iter().filter_map(|x| x.as_ref()).collect();
// ^ notice the & before Uncopyable?
This may not do the trick for you if you have to work with an API that requires &[Uncopyable]. In that case, use Matthieu M.'s solution which can be reduced to:
let nums: Vec<Uncopyable> = num_opts.into_iter().filter_map(|x| x).collect();