Is it possible to initialize immutable variables with match in Rust? - variables

I have this piece of code where I try to convert command line arguments to integers. The problem is, the variables width and height should really be immutable, as I don't plan to change them. Is there any way I can use match like let width = {match....} and initialize them in one step as immutable variables rather than giving them a default value and mutating them? I believe this would be safer and more efficient.
let args: Vec<String> = env::args().collect();
let width_arg = &args[1];
let height_arg = &args[2];
let mut width = 0;
let mut height = 0;
match width_arg.parse::<i32>() {
Ok(w) => width = w,
Err(_) => ask_for_number(),
}
match height_arg.parse::<i32>() {
Ok(h) => height = h,
Err(_) => ask_for_number(),
}

Sure, match is an expression, so you should be able to rewrite it as follows:
let args: Vec<String> = env::args().collect();
let width_arg = &args[1];
let height_arg = &args[2];
let width = match width_arg.parse::<i32>() {
Ok(w) => w,
Err(_) => ask_for_number(),
};
let height = match height_arg.parse::<i32>() {
Ok(h) => h,
Err(_) => ask_for_number(),
};

Yes, just initialise the variable like so: let a = match b { /* your code here*/ };

Related

How to read stdin keys in rust with termion using dynamic char values?

I have the following code to read user input keys from terminal using termion
use std::io::{stdin, stdout};
use termion::event::Key;
fn main() {
let mut stdout = stdout().into_raw_mode().unwrap();
let stdin = stdin();
let char_from_config = 'e';
for c in stdin.keys() {
match c.unwrap() {
Key::Char('q') => {
break;
}
Key::Char('h') => {
// do something
}
Key::Char('l') => {
// do something else
}
_ => {}
}
stdout.flush().unwrap();
}
}
What I would want to do is to read not just Key::Char('q') but some other dynamic character value, which I collect from somewhere else, like Key::Char(char_from_config), but it doesn't work for some reason.
Is there a way to paste a variable containing char instead of an actual 'char' to match arms ?
When you write a match arm Key(c) => ..., c becomes part of a pattern that match will match against and if value matched this enum variant c will be equal to whatever this variant holds. You however want to say "match only if it's Key variant with this given value". You have two options how to do it.
You can either have const value (you probably don't want to do that):
const CHAR_FROM_CONFIG: char = 'e';
match ... {
Key(CHAR_FROM_CONFIG) => (),
_ => ()
}
Or use a match guard (you probably do want to do that):
let char_from_config = 'e';
match ... {
// c will match here any character, but this arm will succeed only
// when it will be equal to char_from_config
Key(c) if c == char_from_config => (),
_ => ()
}

Making a value dynamic in Spark AR via Script

Coming from this Question Tweening Colors on Spark AR via Script i now try to make start and end color dynamically bounded. I propably havn't swallowed the whole concept of reactive programming yet, but i tried to make a factory so the value is a function... yet its not working, or only with the initial values. Using the set function and restarting animation doesnt change a thing. What am i missing? Thank you and best regards!
const pink = [.99, .682, .721, 1];
const blue = [.0094, .0092, .501, 1];
const yellow = [0.9372, .7725, 0, 1];
function ColorFactory() {
this.sourceCol = pink;
this.targetCol = blue;
this.set = function (_col1, _col2) {
this.sourceCol = _col1;
this.targetCol = _col2;
}
this.get = function (id) {
switch (id) {
case 'source': return this.sourceCol;
default: return this.targetCol;
}
}
}
var colfac = new ColorFactory();
const timeDriver = Animation.timeDriver(timeDriverParameters);
const rotSampler = Animation.samplers.easeInQuad(0, 35);
const alphaSampler = Animation.samplers.linear(1, 0);
const colSampler = Animation.samplers.linear(colfac.get('source'), colfac.get('target'));
const colorAnimation = Animation.animate(timeDriver, colSampler);
timedriver.start();
//doesnt make change anything, same colors as before:
colfac.set(blue, yellow);
timedriver.reset();
timedriver.start();
So how could i make the set of colors dynamic? Anyone?
The only "good" option for you is to do something like this:
const colors = [];
const driver = A.timeDriver({ durationMilliseconds : 1000 });
// On NativeUI monitor selected index event
ui.selectedIndex.monitor.subscribe(
(val) => {
const sampler = A.samplers.linear(colors[val.oldValue, colors[val.newValue]);
const colorAnimation = A.animate(driver, sampler);
// bind here to shader
})

Modified Rust Book Guessing Game Query

I modified the code from the Rust Book's Guessing Game Tutorial to make it a little shorter; for a slide. Alas, I've introduced a bug, and it no longer executes correctly: the first input works as expected, but subsequent entries now yield no feedback.
What is the best way to guard against this situation?
use std::io;
use std::cmp::Ordering;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
let mut guess = String::new();
loop {
io::stdin().read_line(&mut guess)
.expect("Failed to read line");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
println!("You guessed: {}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
read_line will append the line to buffer, so your guess will accumulate all the inputs include newline characters! Moving let mut guess = String::new(); inside the loop solves the problem:
fn main() {
...
loop {
let mut guess = String::new();
...
}
}

how to get array sizes in object react-native

I used json.groupby on Json and it gives me arrays in object. But I dont know how to get that first array's lenght, second array's lenght ?
You need to map your keys of json object. So you can achieve each array.
let firstArrayLenght = 0;
let secondArrayLenght = 0;
Object.keys(yourJSON).map((key, index) => {
if (index === 0) {
firstArrayLenght = yourJSON[key].length;
} else if (index === 1) {
secondArrayLenght = yourJSON[key].length;
}
});
If you want all length of arrays, you can use;
let lengthsOfAllArray = [];
Object.keys(yourJSON).map((key, index) => {
lengthsOfAllArray.push(yourJSON[key].lenght);
});
or you can push as an object key value pair. So you can read which array has which lenght.
Object.keys(yourJSON).map((key, index) => {
let item = {
key,
lenght: yourJSON[key].lenght
};
lengthsOfAllArray.push(item);
});
If you want to get all sizes regarding the array length you can store its values on other array
let arrayLenghts = [];
Object.keys(jsonObj).map((key, index) => {
arrayLenghts[index] = jsonObj[key].length;
});
Then you can search on arrayLengths the size of all arrays inside your JSON object

How to send the index of a for loop into the promise of a function in a Vue Resource call?

I am looping through an object however in the asynchronous part the i variable is always five.
How can I maintain that value, or pass it into the function
getProductData: function() {
var vm = this;
for (var i = 0; i < vm.recommendationResponse['recommendedItems'].length; i++) {
var sku = vm.recommendationResponse['recommendedItems'][i]['items'][0]['id'];
vm.$http.get('http://127.0.0.1:8000/models/api/productimage/' + sku).then(response => {
// get body data
vm.recommendationResponse['recommendedItems'][i]['items'][0]['image_url'] = response.body['product_image_url'];
vm.recommendationResponse['recommendedItems'][i]['items'][0]['price'] = response.body['price'];
}, response => {
vm.recommendationResponse['recommendedItems'][i]['items'][0]['image_url'] = '';
vm.recommendationResponse['recommendedItems'][i]['items'][0]['price'] = '';
});
}
}
I I do something like this:
vm.$http.get('http://127.0.0.1:8000/models/api/productimage/' + sku).then((response, i) => ...
then i is undefined
Who do I keep the index of the loop or should I go about it a different way?
Always use let to initialize variables in for loop when dealing with async operations. Similar things goes to having for loops in intervals. By using let you make sure you always have a unique variable assigned to i.
for (let i = 0, recommendationlength = vm.recommendationResponse['recommendedItems'].length; i < recommendationlength; i++)
Little bonus, if you cache array length in the beginning you get a small performance boost :-)
You could use Array.prototype.forEach instead:
var vm = this;
vm.recommendataionResponse['recommendedItems'].forEach((item, i) => {
var sku = vm.recommendationResponse['recommendedItems'][i]['items'][0]['id'];
vm.$http.get('http://127.0.0.1:8000/models/api/productimage/' + sku).then(response => {
// get body data
vm.recommendationResponse['recommendedItems'][i]['items'][0]['image_url'] = response.body['product_image_url'];
vm.recommendationResponse['recommendedItems'][i]['items'][0]['price'] = response.body['price'];
}, response => {
vm.recommendationResponse['recommendedItems'][i]['items'][0]['image_url'] = '';
vm.recommendationResponse['recommendedItems'][i]['items'][0]['price'] = '';
});
})
This way, since there is a unique scope for each i value, each .then callback will be able to reference the correct value.