Is it a cleaner way to write the following code in rust? - rust

for x in strategies {
let mut flag = true;
for y in x {
if y {
flag = false;
break;
}
}
if flag {
// do something
}
}
I really hate the use of the flag, and it adds unnecessary branch instructions. I am thinking if there is a way that we can execute // do something if the inner loop exit normally and don't do it if it breaks.

In place of the inner loop, you can take the negation of Iterator::any applied over an identity method such as |y| y or std::convert::identity:
for x in strategies {
// if it's not the case that any are true
if !x.into_iter().any(|y| y) {
// do something
}
}
Equivalently, you can take Iterator::all applied over a negating method such as |y| !y or <bool as std::ops::Not>::not:
use std::ops::Not;
for x in strategies {
// if it is the case that all are false
if x.into_iter().all(Not::not) {
// do something
}
}
Either way, if x is already an Iterator, then the call to .into_iter() is superfluous and can be omitted.

Related

How to access rust variables outside the scope?

My code look like this
fn main() {
// some other codes goes here
let int = 1;
if int == 1 {
let x = "yes";
} else {
let x = "no";
}
if x == "yes" {
// some other codes goes here
println!("yes");
} else if x == "no" {
// some other codes goes here
println!("no")
}
}
When I run this I get this
error[E0425]: cannot find value `x` in this scope
--> src/main.rs:9:8
|
9 | if x == "yes" {
| ^ not found in this scope
error[E0425]: cannot find value `x` in this scope
--> src/main.rs:12:15
|
12 | } else if x == "no" {
| ^ not found in this scope
While searching for a solution I came across this post How do I access a variable outside of an `if let` expression? but could not able to understand the reason or its solution?
Easiest is by far to code it such that it is in scope in the first place.
You can assign variable with the result of a statement in a single assignment.
If you can make it as a one-liner, it also makes it arguably more readable.
If the actual processing is too long, nothing prevents you from just... making it a proper function.
let x = if int == 1 { "yes" } else { "no" };
// rest of the code accessing x.
Alternatively, the compiler will let you declare unassigned variables if you properly assign them later, with all the compile-time safety checks in place. Read the docs on RAII (Resource Acquisition Is Initialization) RAII Docs to see more how it works. In practice, it's just as simple as this:
let x;
if i == 1 {
x = "yes";
}
else {
x = "no";
}
// keep doing what you love
The compiler will error if there's a logic path where x doesn't get initialized, or if it gets initialized as a different type.
Notice you also do not need to declare it as mut, as the first value it gets will stay immutable. Unless you do want to change it afterwards, obviously.
You can't access a variable which is out of scope. But you use a workaround and set the variable in the same scope.
fn main(){
let int = 1;
let x = if int == 1 {
"yes"
} else {
"no"
};
if x == "yes" {
println!("yes");
} else if x == "no" {
println!("no");
}
}
In Rust each variable has a scope that starts where the variable in initialized. In you problem you try to use the variable x which is created inside of the if int == 1 and the if x == "yes", since if statements have a separate scope from the function main you cannot create a variable inside of your if statement and expect it not to be cleared when you leave scope. The simplest solution is to initialize the variable x where you want to have it used in if x == "yes", so let's say that we want the scope of x to start in main by putting let x; in main. In Rust you may have variable from the larger scope be visible to the scopes that are within that larger scope where the variable in initialized, so assigning the variable from the scope of an if statement is perfectly valid.
Please take a look at https://doc.rust-lang.org/rust-by-example/variable_bindings/scope.html for more information.
fn main() {
let x;
// some other codes goes here
let int = 1;
if int == 1 {
x = "yes";
} else {
x = "no";
}
if x == "yes" {
// some other codes goes here
println!("yes");
} else if x == "no" {
// some other codes goes here
println!("no")
}
}
But you could get rid of the two if statements and just use match:
fn main() {
let myint = 1;
match myint {
1 => {println!("yes")}
_ => {println!("no")}
}
}
The question
I believe you are asking what does this error mean?
To answer that, one must first answer, what is scope?
The answer
Scope, in lay terms, is the section of code where a variable exists.
So when the error says not found in this scope, it means the variable does not exist here.
An example
fn main() {
let a_bool = true;
let main_scope_x = 0;
if a_bool == true {
let if_scope_x = 1;
} // if_scope_x stops existing here!
println!("main x has the value {}", main_scope_x);
println!("if x has the value {}", if_scope_x); // this will cause an error, if_scope_x does not exist outside the if expression.
}
Further info
https://doc.rust-lang.org/stable/book/ch04-01-what-is-ownership.html
(Read the book! It's very good!)

set ignore case value in when expression on strings

I know how to check a string is in another string
like this code.
when (myString) {
in "FirstString" -> {
// some stuff
}
in "SecondString" -> {
// some stuff
}
else -> {
// some stuff
}
}
in keyword under the hood calls this method CharSequence.contains(other: CharSequence, ignoreCase: Boolean = false)
the question is this :
is there any way that in this case i can set ignoreCase = true ?
You can declare an ad-hoc local operator function contains for strings before when:
fun main() {
operator fun String.contains(other: String): Boolean = this.contains(other, ignoreCase = true)
when(myString) {
in "firstString" -> ...
}
}
This way that function will be invoked for in operator instead of the one declared in the standard library because it's located in the closer scope.
Note, however, that this trick works only if the original contains function is an extension. If it's a member function, it cannot be overridden with an extension.
You can use toLowerCase() function here :
when (myString.toLowerCase()) {
in "firststring" -> {
// some stuff
}
in "secondstring" -> {
// some stuff
}
else -> {
// some stuff
}
}
For the cases of when, if they're variables toLowerCase() needs to be called on each of them. But, if they're constants, simple using lower case strings will work - "firststring", "secondstring"

Can I get this Haxe switch statement to be a bit more dynamic?

It's not critical but I was wondering. Somewhere in my program I have a switch statement that gets called multiple times with an incremented value, so that all cases should be executed in order. Something like a custom made simple sequencer.
like this:
private function sequence_Crush(step:Int):Void
{
switch(step) {
case 1: {
action_loadCueFile();
seq.next(); //This calls the same function with an increased step
}
case 2: {
action_saveSettings();
seq.next();
}
/// EDIT: Some steps run ASYNC and an event triggers the next step in the sequence
/// like this:
case 3: {
events.once(ENGINE_EVENTS.cut_all_complete, seq.next);
cutTracks();
}
My Question is, Is there any way to replace the manually written numbers (1,2,3,4) on the cases and use a counter somehow, macros maybe? I have tried putting a dynamic counter, but the Haxe compiler complains.
What I tried:
var st:Int = 1;
switch(step) {
case (st++): { // 1
action_loadCueFile();
seq.next();
}
case (st++): { // 2
action_saveSettings();
seq.next();
}
//... etc
Build halted with errors (haxe.exe)
Case expression must be a constant value or a pattern, not an arbitrary expression
I am targeting JS and using Haxe 3.1.3. I have tried that in actionscript and javascript and it works fine. The reason I want to do that, is that if I want do add or remove a step, I have to re-organize manually every other case number.
p.s. I know there are other ways to sequence actions in order, but I like this one, as I have everything in one function and it's easy to see the order of execution in one glance
Thanks for reading :-)
Jason beat me to it by a few minutes...
Case expressions in Haxe must be either constant values or patterns.
But you can accomplish the desired behaviour in a few ways: (a) custom syntax like $next with macros; (b) macro conversion into if-else blocks (Jason's answer); (c) without macros and (mis)using pattern guards.
Custom syntax
A quick and dirty implementation of it follows; it only supports case $next: and there are no syntax checks.
When a case $next: is found, the macro checks if the previous case pattern was a single constant integer i and, in that case, rewrites the pattern to the value of i + 1.
Macro implementation:
// SequenceSwitch.hx
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.ExprTools;
class SequenceSwitch {
public
macro static function build():Array<Field> {
var fields = Context.getBuildFields();
for (f in fields)
switch (f.kind) {
case FFun(func) if (func.expr != null):
func.expr = ExprTools.map(func.expr, transf);
case _:
}
return fields;
}
static function transf(e:Expr):Expr {
return switch (e.expr) {
case ESwitch(expr, cases, def):
var ncases = [];
var prev:Array<Expr> = null;
for (c in cases) {
var cur = switch (c.values) {
case [{ expr : EConst(CIdent("$next")), pos : pos }] if (prev != null):
switch (prev) {
case [{ expr : EConst(CInt(i)) }]:
var next = { expr : EConst(CInt(Std.string(Std.parseInt(i) + 1))), pos : pos };
{ values : [next], guard : c.guard, expr : c.expr };
case _:
c;
}
case _:
c;
};
ncases.push(cur);
prev = cur.values;
}
{ expr : ESwitch(expr, ncases, def), pos : e.pos };
case _:
e;
}
}
}
Usage example:
// Text.hx
#:build(SequenceSwitch.build())
class Test {
static function main() {
sequenceCrush(1);
}
static function sequenceCrush(step:Int) {
switch (step) {
case 1:
trace("do one");
sequenceCrush(++step);
case $next:
trace("do two");
sequenceCrush(++step);
case $next:
trace("do three");
sequenceCrush(++step);
case _:
trace("terminate");
}
}
}
No macros/with guards
Similar behaviour could be achieved by (mis)using guards:
static function sequenceCrush_guards(step:Int) {
var st = 1;
switch (step) {
case next if (next == st++):
trace("do one");
sequenceCrush_guards(++step);
case next if (next == st++):
trace("do two");
sequenceCrush_guards(++step);
case next if (next == st++):
trace("do three");
sequenceCrush_guards(++step);
case _:
trace("terminate");
}
}
In Haxe 3 switch changed from the JS/Flash style simple matching, which was really not much more than a chain of if/elseif/else statements, to full on pattern matching, which has many more compile-time features, and one of those limitations is that you can't match against a variable, only against constants.
You could use a chain of if (step==st++) {} elseif (step==st++) {} else {} statements for pretty much the same effect. If you're really really addicted to the switch syntax, you could use a macro to get the "classic" switch behaviour. I happened to write one such macro some time ago, take a look at this GIST:
https://gist.githubusercontent.com/jasononeil/5429516/raw/ad1085082530760aa394765d5cd5ebd61a5dbecb/ClassicSwitch.hx
You could then code like this:
class Action
{
static function main()
{
for (currentStep in 0...5) {
var i = 0;
ClassicSwitch.from(switch (currentStep) {
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
case i++: trace( 'Do step $i' );
});
}
}
}
Which gives me the output:
Action.hx:14: Do step 1
Action.hx:15: Do step 2
Action.hx:16: Do step 3
Action.hx:17: Do step 4
Action.hx:18: Do step 5
If all (or most) of your actions are simple function calls you can alternatively use an array of functions:
var actions = [sequence_Crush.bind(1), // if you want to avoid action index = step - 1
action_loadCueFile,
action_saveSettings,
...];
private function sequence_Crush(step:Int):Void
{
while (step < actions.length)
{
actions[step++]();
}
}
You could also keep this recursive (actions[step++](); if (step < actions.length) { sequence_Crush(step)).

how to run predicates and assertions in alloy

I come from a C/C++ background and am trying to understand how are predicates/assertions run/checked in Alloy.
(a) If I have more than one predicates and I want to run both of them, when I run the first predicate how do I ensure that the conditions related to constraint in my other predicate remain static? I am simply puzzled on how do you run multiple predicates.
(b) Same for assertions. Do I have to run check of each assertion?
Thanks for any feedback on this.
You can have an arbitrary formula in your "run" commands, so in there you can conjoin as many predicates as you want. Here is an example:
one sig S {
x: Int
}
pred gt[n: Int] { S.x > n }
pred lt[n: Int] { S.x < n }
run { gt[2] and lt[4] }
With assertions, I think you have to check them one by one, e.g.,
one sig S {
x: Int
}
assert plus_1 { plus[S.x, 1] > S.x }
assert minus_1 { minus[S.x, 1] < S.x }
check plus_1
check minus_1
// doesn't compile: check { plus_1 and minus_1 }
However, you can turn your assertions into predicates, and then you can form arbitrary formulas from them in the body of a "check" command, e.g.,
one sig S {
x: Int
}
pred plus_1[] { plus[S.x, 1] > S.x }
pred minus_1[] { minus[S.x, 1] < S.x }
check { plus_1 and minus_1 }

how can I create a reference to a variable in specman?

I have the following code in specman:
var x := some.very.long.path.to.a.variable.in.another.struct;
while (x == some_value) {
//do something that uses x;
//wait for something
//get a new value for x
x = some.very.long.path.to.a.variable.in.another.struct;
};
Now, it seems wasteful to write the assignment to x twice; once during initialization and once during the loop.
What I really want to use is a reference to the long variable name, so that I could do:
var x := reference to some.very.long.path.to.a.variable.in.another.struct;
while (x == some_value) {
//do something that uses x;
//wait for something
//no need to update x now since it's a reference
};
Can this be done in specman?
specman/e generally uses references for structs and lists, so if your variable type is either of it your second example should work. For integer or boolean I don't know a way to use a reference for a variable. Anyway, two ideas which might help you:
Add a pointer to the other struct and bind it in a config file:
struct a { other_variable : uint; };
struct b {
other_struct : a;
some_func() is {
var x : uint = other_struct.other_variable;
while (x == some_value) {
x = other_struct.other_variable;
};
};
};
extend cfg {
struct_a : a;
struct_b : b;
keep struct_b.other_struct == struct_a;
};
UPDATE: You can find some more information on this technique in this Team Specman Post.
Wrap your while loop in a function, there you can pass parameters by reference (see help pass reference):
some_func(x : *uint) is {
while (x == some_value) {
// stuff ...
};
};
Hope this helps!
Daniel

Resources