What is the syntax for an if-let statement? - syntax

I encountered this snippet in some example code. It works fine, but I got a linter error saying that it should be structured as an if-let statement.
match event {
glutin::Event::WindowEvent { event, .. } => match event {
glutin::WindowEvent::Closed => return glutin::ControlFlow::Break,
glutin::WindowEvent::Resized(w, h) => gl_window.resize(w, h),
_ => (),
},
_ => ()
}
This was my attempt to restructure it:
if let _ = glutin::Event::WindowEvent { event, .. } {
match event {
glutin::WindowEvent::Closed => return glutin::ControlFlow::Break,
glutin::WindowEvent::Resized(w, h) => gl_window.resize(w, h),
_ => (),
}
}
Oops, that's a syntax error. What would be the correct way to clear the linter warning?
After looking at the code more closely, I realized that I don't understand the syntax. glutin::Event::WindowEvent { event, .. } looks like the syntax for creating a new instance of WindowEvent but how can that be allowed inside a match statement?
Also, what does the .. mean? I'm familiar with ..Default::default(), but not the double dot by itself.

The syntax that eludes you is called destructuring.
This pattern allows to match certain fields in a struct, enum, or tuple. You therefore cannot just use if let with the destructuring on the right side of the binding.
The code you want is probably:
if let glutin::Event::WindowEvent { event, .. } = event {
match event {
glutin::WindowEvent::Closed => return glutin::ControlFlow::Break,
glutin::WindowEvent::Resized(w, h) => gl_window.resize(w, h),
_ => (),
}
}
There is a possible confusion between the right hand event variable and the one extracted from the pattern.
The use of event in the destructuring is made mandatory because it needs to use struct fields by name.

Directly quoting from The Book, second edition:
The if let syntax lets you combine if and let into a less verbose way to handle values that match one pattern and ignore the rest.
It also provides this example:
if let Some(3) = some_u8_value {
println!("three");
}
The correct syntax is if let «pattern» = «expression» { ... }, and not the opposite written in the question.
if let glutin::Event::WindowEvent { event, .. } = event {
// ...
}

Related

cypress: How can manage the application flow, if the element xpath is not present

I have the following scenario:
if the element is present, i have to do one activity and if not present will do another activity.
cy.xpath("//div[text()= 'button').its('length').then(res=> {
if (res > 0) {
return 1;
}
else {
cy.log ("Element is not present")
}
}
)} '''
if element is present = Code is working fine,
if the element xpath is not present = it try to search the element xpath (//div[text()= 'button') and throwing the error as 'Timed out retrying: Expected to find element: undefined, but never found it.'
if element is not present, Is there any way, i can handle the code ,
When using xpath you can (sort of) make it conditional by wrapping the xpath selector with count().
cy.xpath("count(//div[text()= 'button'])") // ok with async content
.then(count => {
if (count) {
//return 1; // not useful, returns a "chainer"
// ...but you can perform the required test here, e.g
cy.xpath("//div[text()= 'button']").click()
} else {
cy.log('not found')
}
})
The shorter syntax using built-in jQuery might be
const exists = !!Cypress.$("div:contains('button')").length
if (exists) {
cy.xpath("//div[text()= 'button']").click()
} else {
cy.log('not found')
}
Note that this is a partial match to 'button', where-as the xpath syntax is an exact match.
Also note - using Cypress.$ by-passes retry-ability, so it should not be used where the text is asynchronous.
From docs
This is a great way to synchronously query for elements when debugging from Developer Tools.
The implication is that it's more for debugging after the page has loaded.
The best practice is to try to construct the test and the app's data in such a way that you know that the button is present.
You can do something like this. With Cypress.$, you can validate the presence of the element with the help of the length attribute and then do further actions.
cy.get('body').then($body => {
const ele = $body.find('selector');
if (Cypress.$(ele).length == 0) {
//Do Something element is not present
}
else if (Cypress.$(ele).length > 0) {
//Do Something when element is present
}
})

rxjs BehaviorSubject that emits via distinctUntilChanged

I'm wanting to implement an Observable / Subject with 3 particular attributes
Remember last emitted value and be able to surface it via a getter (BehaviorSubject)
Only emit when value changes
It must have a strong type such that the getter is known to be available by a consumer (aka. BehaviorSubject.getValue())
I'm thinking of just extending BehaviorSubject but want to make sure I'm not introducing any potential gotchas based on my novice understanding.
export class DistinctUntilChangedBehaviorSubject<T, TValue> extends BehaviorSubject<T> {
constructor(
initialValue: T,
private _distinctKeySelector?: (value: T) => TValue,
private _comparer?: _Comparer<TValue, boolean>
) {
super(initialValue);
}
public subscribe() {
// I'm particularly interested in knowing if this has any gotchas.
// Mostly things like creating subscriptions that don't get disposed as expected.
return super.distinctUntilChanged(
this._distinctKeySelector,
this._comparer
).subscribe.apply(this, arguments);
}
}
So 2 questions:
Does this seem like a reasonable approach / are there any gotchas here?
Is there another preferred way of doing this?
I do not know really why, but I tend to prefer composition over extension.
So I would do something along these lines
import {BehaviorSubject} from 'rxjs';
export class BehaviourSubjectAugmented<T> {
bs: BehaviorSubject<T>;
constructor(initialValue: T, private comparer: (p: T, q: T) => boolean) {
this.bs = new BehaviorSubject(initialValue);
}
getValue() {
return this.bs.getValue();
}
asObservable() {
return this.bs.asObservable()
.distinctUntilChanged(this.comparer);
}
complete() {
return this.bs.complete();
}
next(value: T) {
return this.bs.next(value);
}
}
Turns out my original idea causes a call stack exceeded issue. I'm assuming that distinctUntilChanged must call subscribe internally thus causing infinite recursion.
I ended up finding a simpler way to get what I needed by simply adding a method to an ISubject instance.
function distinctUntilChangedBehaviorSubject(
initialValue: number
): ISubject<number> & { getValue(): number } {
const observer = new BehaviorSubject<number>(initialValue);
const observable = observer.distinctUntilChanged();
const subject: ISubject<number> = Subject.create(
observer,
observable
);
return Object.assign(
subject,
{
getValue: () => observer.getValue()
}
);
}

Representing enum variants with optional data in macro_rules

I'm trying to create a macro to help with some boilerplate enum code that I've been repetitively writing. I managed to implement a simple enum (i.e. no arguments) relatively easily using a basic macro_rule. e.g. An excerpt:
macro_rules! enum_helper {
($type:ident, { $( $name:ident ), * }) => {
enum $type {
$(
$name,
)+
}
impl FromSql for $type {
fn from_sql<R: Read>(_: &Type, raw: &mut R, _: &SessionInfo) -> Result<&type> {
// ... the implementation
}
// ... plus some other internal traits being implemented
}
}
enum_helper!(Step, {
Step1,
Step2
});
I was hoping to extend this macro to also support a mixed set of enum styles, primarily with only one typed argument e.g.
enum_helper!(Step, {
Step1,
Step2,
Step3(i64)
});
Is there a way to represent this "optional" argument using macro_rules? I suspect it involves using a tt however I'm still a bit lost with how tt works in a subnested environment.
Update 1
I'm using $name within some of the trait implementations for pattern matching. For example, I have some code similar to below:
match raw {
$(
$type::$name => { /* a result of some sort */ },
)+
}

Why can not I get my class methods defined as an array of instances of the index contains the variable?

That's what we have. It's Swift code:
class Process {
// Some methods and properties
}
class SomeClass {
var list: [Process]? = nil
// ...
func someFunc () {
// ...
if list !=nil {
for i in list! {
if list[i].
}
}
Inserting a point (.) in the last line, I do not get a list of methods and properties.
If I change the index i to digit, then I'll get a list of methods and properties of its class Process
How it's look like
What should I do to use a variable in the index I could use the methods of its class?
P.S. Sorry for my English, I used machine translation
With for x in y you don't have to subscript because x is not an index, it's the current iterator object:
func someFunc () {
if let list = list {
for item in list {
item.
} ^^^^ here auto-suggest will work
}
}
If the suggested methods don't work or don't make sense it's usually because you have a syntax error. Same for auto-indenting the code.
Here what you're doing is iterating the list, and expecting that to give you an index, when what it's really doing is giving you the objects in list.
So the code should simply be:
for i in list! {
if i.XXX ...
where XXX is whatever you're trying to test.

Call method on LINQ query results succinctly

I'd like to call MyMethod on each object from a LINQ Query, what is the best way to do this?
Currently I am using:
.Select(x => { x.MyMethod (); return x; }).ToArray();
ToArray() is needed for immediate execution.
Is there a simpler way to write this (without a foreach)
Thanks
You could specify your own reusable extension method that runs an Action<> on each element, and yield returns it.
IEnumerable<T> Do(this IEnumerable<T> vals, Action<T> action) {
foreach(T elem in vals) {
action(elem);
yield return elem;
}
}
Such method is included in the Rx library, under the System.Interactive namespace.
Then you can simply do
myCollection.Do(x => x.MyMethod()).ToArray();
xList already has the method you need: .ForEach(). It calls an Action on each list member.
List<x> fooList = ....Select(x => x).ToList();
fooList.ForEach(x => DoSomething(x));
I created an Apply extension method :
public static IEnumerable<T> Apply<T>(this IEnumerable<T> source, Action<T> action)
{
foreach(var item in source)
{
action(item);
yield return item;
}
}
You can use it as follows :
var results = query.Apply(x => x.MyMethod()).ToArray();
Actually, that's similar to the List<T>.ForEach method, excepts that it returns the items of the source so that you can continue to apply sequence operators on it
A for each is probably going to be the easiest way to do this, you could write an extension method that does the for each, but
You really wouldn't gain anything.
In my opinion, you don't need to call .To___ conversion methods since you are expecting side-effects only. Reactive Extension's Do() method would be a viable option.
By using Do() method, you have two advantages (as far as I'm concerned),
1) Defer execution (You can defer the immediate execution if you want).
2) Do() method has different overloads to let you have more controls over iteration.
For example: Do(onNext, OnError, OnCompeleted) overload
var deferQuery = query.Do(x => a.MyMethod(), ex => Console.WriteLine(ex.Message), () => Console.WriteLine("Completed"));
var immediateQuery = query.Do(x => a.MyMethod(), ex => Console.WriteLine(ex.Message), () => Console.WriteLine("Completed")).Run();

Resources