Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to assign (already-declared) variables in a @match #41

Open
rben01 opened this issue Feb 12, 2024 · 4 comments
Open

How to assign (already-declared) variables in a @match #41

rben01 opened this issue Feb 12, 2024 · 4 comments

Comments

@rben01
Copy link

rben01 commented Feb 12, 2024

I have a match that looks like this:

markup::define! {
	Test() {
		@let x = Some(1);
		@let y;
		@match x {
			Some(n) => { y = n },
			None => { y = -1 },
		}
	}
}

The error I get is

error: expected one of: `;`, curly braces, string literal
   --> src/lib.rs:127:19
    |
127 |             Some(n) => { y = n },
    |                            ^

The easiest fix is to simply write @let _ = match { ... }, as this “reenables” some Rust syntax that is seemingly not allowed within @match. But then this leads to a clippy warning, which I can't figure out how to silence because #[allow(clippy::let_unit_value)] isn't allowed in define!. (I could silence the warning at a coarser scope, but don't want to.)

I've tried various things, mostly mucking around with moving an @ sign here and there, and removing the let (so just _ = match { ... } and @_ = match { ... }, at least one of which feels like it should be legal, but no such luck). I can't figure out how to just assign a variable as a statement inside a @match. Various other solutions lead to the trait bound (): markup::Render is not satisfied (i.e., an assignment itself cannot be rendered — fair enough).

Does markup support a way to accomplish this (maybe y @= n?), or to more generally include arbitrary rust code in define!? I'd also reached for ${ ... } as a way to say “the stuff in the {} is to be run but not rendered” but that didn't work either.

Edit: I've wrapped the whole match in a @fn, which gives me access to all the Rust syntax I need, but this seems like overkill.

@fanelfaa
Copy link

if you just want to set the @let y variable you can do like this:

markup::define! {
    Test() {
		@let x = Some(1);
		@let y = match x {
			Some(n) => n,
			None => -1,
		};
                @y
	}
}

@rben01
Copy link
Author

rben01 commented Feb 24, 2024

Thanks, but my issue is that I'd like to assign multiple variables. My plan is to pre declare the variables and then assign in the match. If I used a @let, I'd need to use a tuple to do the assignment, which gets unwieldy (especially when the assignment logic is determined at different levels of nested matches).

@Kijewski
Copy link
Contributor

I'd propose to simply remove @let variable; patterns. You can always refactor your match statements to return a tuple, so that all variables are assigned afterwards.

@rben01
Copy link
Author

rben01 commented Feb 26, 2024

My issue is that I would like to replicate the following:

let x = Some(1_u32);
let y;
let z;

match x {
    Some(n) => {
        y = "some";
        z = match n {
            0 => "zero",
            1..=5 => "small",
            6..=10 => "medium",
            11.. => "big"
        };
    }
    None => {
        y = "none";
        z = "n/a"
    }
}

Were I to convert to using tuples, I would have to include "some" in every branch of z's match in the Some(n) branch, which is a bit annoying (and unnecessary in standard Rust).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants