Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Dominoes
Sep 20, 2007

Yo dudes; learning Rust, and struggling with the borrow checker and unexpected ungulates.

Code:
Rust code:
pub fn trailing_ed(contents: String) -> String {
    // Change trailing ed to D, trailing es to S etc.
    let tail_letters = ["d", "x", "s", "l"];

    let mut result = &contents;
    // Could handle this loop with a more complex regex instead.
    for letter in tail_letters.iter() {
        let re_str = r"(e".to_string() + letter + r")\s+";
        let re = Regex::new(&re_str).unwrap();
        
        // let replacement = &letter.to_uppercase();
        result = re.replace_all(result, "test");

    }

    result.to_string()
}
Error:
code:
error[E0308]: mismatched types
  --> src\to_shorthand.rs:37:18
   |
37 |         result = re.replace_all(result, "test");
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found enum `std::borrow::Cow`
   |
   = note: expected type `&std::string::String`
              found type `std::borrow::Cow<'_, str>`
I dug a bit on cows; tried to match their Borrowed and Owned enum fields, with no luck. The official example:
code:
let re = Regex::new(r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})").unwrap();
let before = "2012-03-14, 2013-01-01 and 2014-07-05";
let after = re.replace_all(before, "$m/$d/$y");
assert_eq!(after, "03/14/2012, 01/01/2013 and 07/05/2014");
implies exploring the cow shouldn't be required. Something involving my loop is causing my code to break while the example doesn't.

Adbot
ADBOT LOVES YOU

Dominoes
Sep 20, 2007

Thank you; that explanation and code sorted it out entirely; needed to dissect the cow. Related: Now I'm tackling out the uppercase-conversion (Replaced by "test" in my previous example.

After changing the tail_letters iterator to chars instead of strings, this works:
code:
        let replacement: &str = &(letter.to_uppercase().to_string());

        if let Cow::Owned(s) = re.replace_all(&result, replacement) {
This does not:
code:
	// A string?
        let replacement = letter.to_uppercase().to_string();

	// converting the string to &str with &
        if let Cow::Owned(s) = re.replace_all(&result, &replacement) {
Nor does this:
code:
        let replacement = &(letter.to_uppercase().to_string());

        if let Cow::Owned(s) = re.replace_all(&result, replacement) {
Error:
code:
35 |         if let Cow::Owned(s) = re.replace_all(&result, replacement) {
   |                                   ^^^^^^^^^^^ the trait `for<'r, 's> std::ops::Fn<(&'r regex::Captures<'s>,)>` is not implemented for `std::string::String`
Why do I need to explicitly declare &str in this case? I added it to confirm that replacement was indeed an &str, yet it solved the problem.

Dominoes fucked around with this message at 00:39 on Mar 17, 2018

Dominoes
Sep 20, 2007

I'm counting one in each, excluding the type annotation. Ie to convert a String, as output by char.to_string(), to a &str, as required by re.replace_all.

Dominoes fucked around with this message at 01:19 on Mar 17, 2018

Dominoes
Sep 20, 2007

Thanks Viking - that makes sense!

Dominoes
Sep 20, 2007

Yo bros. Trying to do some matrix mult; ref the thread's title. Any wisdom from bros on how to make it compile?

Rust code:
fn project(cam: &Camera, node: &Node) -> Array1<f64> {
    // Project a 4d node onto a 2d plane.
    // [url]https://en.wikipedia.org/wiki/3D_projection[/url]

    let D_1 = array![
        [1., 0., 0.],
        [0., cam.theta[0].cos(), cam.theta[1].sin()],
        [0., -cam.theta[0].sin(), cam.theta[0].cos()]
    ];

    let D_2 = array![
        [cam.theta[1].cos(), 0., -cam.theta[1].sin()],
        [0., 1., 0.],
        [cam.theta[1].sin(), 0., cam.theta[1].cos()]
    ];

    let D_3 = array![
        [cam.theta[2].cos(), cam.theta[2].sin(), 0.],
        [-cam.theta[2].sin(), cam.theta[2].cos(), 0.],
        [0., 0., 1.]
    ];

    let D = D_1.dot(&(D_2.dot(&D_3)));

    //  d is the position of the node a in the coordinate system
    // defined by the camera, wiht origin in C and rotated by theta.
    let d = D.dot(&(node.a - &cam.c));

    let A = array![
        [1., 0., -cam.e[0] / cam.e[2], 0.],
        [0., 1., -cam.e[1] / cam.e[2], 0.],
        [0., 0., 1., 0.],
        [0., 0., -1. / cam.e[2], 1.],
    ];

    let f = A.dot(
        array![&d[0], &d[1], &d[2], 1.]
    );
error:
code:
error[E0308]: mismatched types
  --> src\main.rs:68:9
   |
68 |         array![&d[0], &d[1], &d[2], 1.]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found struct `ndarray::ArrayBase`
   |
   = note: expected type `&_`
              found type `ndarray::ArrayBase<ndarray::OwnedRepr<&f64>, ndarray::Dim<[usize; 1]>>`
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for mor...
If I remove the &s around d, I get:

code:
error[E0308]: mismatched types
  --> src\main.rs:68:9
   |
68 |         array![d[0], d[1], d[2], 1.]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found struct `ndarray::ArrayBase`
   |
   = note: expected type `&_`
              found type `ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-m
Also, anyone know how to hack SA's forum code to make good code syntax highlighting? poo poo's super out of date php and doesn't support rust etc. Basically, I don't get the & stuff and can't even do basic things in Rust. I suck. It's not Haskell-monad-level 'I'm too dumb for this'; more like, I'm missing something fundamental but will eventually get it. I could take the easy way out and do Python where the code just does what you ask, but I really want to learn this.

Dominoes fucked around with this message at 04:48 on Apr 22, 2018

Dominoes
Sep 20, 2007

Thanks for looking at it dude. getting this now:

code:
error[E0308]: mismatched types
  --> src\main.rs:68:16
   |
68 |         &(arr1([d[0], d[1], d[2], 1.]))
   |                ^^^^^^^^^^^^^^^^^^^^^^
   |                |
   |                expected &[_], found array of 4 elements
   |                help: consider borrowing here: `&[d[0], d[1], d[2], 1.]`
   |
   = note: expected type `&[_]`
              found type `[f64; 4]`
If I follow this warning and do:

code:
   let f = A.dot(
        &(arr1(&[d[0], d[1], d[2], 1.]))
    );
I get:

code:
93 |         .map(|node| project(camera, node)).collect();
   |                             ^^^^^^ cannot move out of captured outer variable in an `FnMut` closure
This is humbling me and I love it. Change &s until it compiles? I don't think I'm doing anything esp weird; just taking some dot products. Sorry dudes; I get that I posted a lot of code and error messages; so lost.

Dominoes fucked around with this message at 05:03 on Apr 22, 2018

Dominoes
Sep 20, 2007

Dudes; got it to compile; I'lll post what happened if you like, but I have no idea and don't think it'll be useful since I just moved &s around rando until it worked.

Dominoes
Sep 20, 2007

Thank you - that helps a lot!

Dominoes
Sep 20, 2007

Any advice on separating dependencies for WASM and binaries? I have a project that both runs locally with main.rs, and can be used as a library for WASM/JS using lib.rs. When I try to compile WASM, one or more of the dependencies that I need to run locally, but not web, prevents the WASM compilation. If I remove the crashing lib from Cargo.TOML temporarily, main.rs can't find it, which then prevents the compile. It appears that renaming main.rs, and commenting out the failing dependency works. Is there a more elegant solution?

How would you handle this?

Dominoes fucked around with this message at 10:34 on May 21, 2018

Dominoes
Sep 20, 2007

Nailed it. Went with the specify-dependencies approach for now; may switch to the separate lib approach later.

Dominoes
Sep 20, 2007

Another one: Is there a way to make Rust's wasm-bindgen work with types other than basic numbers/string, and ones you created in your code? Eg, I can make it accept custom structs with the #[wasm_bindgen] macro, but unable to apply it to say, a HashMap from the standard library, or an Array from the ndarray crate.

Dominoes fucked around with this message at 23:43 on May 21, 2018

Dominoes
Sep 20, 2007

Thanks; works!

Dominoes
Sep 20, 2007

Hey dudes. How do you enter values in scientific notation?

Rust code:
const ELECTRON_MASS: f64 = 9.109390 * (10.).powi(-31);

quote:

error[E0599]: no method named `powi` found for type `{float}` in the current scope

Dominoes
Sep 20, 2007

Ralith posted:

The syntax is the same as in most programming languages, e.g. 9.109390e-31.
Thanks dude; that worked.


Re: Linear's comment: It's interesting that a workaround would have been required if it were not for this shorthand.

Dominoes
Sep 20, 2007

I'm referring to why the code I initially posted isn't also a valid solution. I don't understand what's going on, since const test: f64 = 1. * 10.; works.

Dominoes fucked around with this message at 23:56 on Sep 27, 2018

Dominoes
Sep 20, 2007

Thanks dudes.

Dominoes
Sep 20, 2007

Helicity posted:

When does the borrow checker stop kicking me in the dick? It feels like since Rust emphasizes "correctness", what I'm trying to do, and have done in programs for years, is broken. I already had imposter syndrome - I don't need a language to tell me I suck.
Write code. Let the compiler tell you what you did wrong. If it hasn't already proposed the solution (which it often does!), move &s around until it works. Eventually you'll gain intuition about where to put them yourself.

Dominoes
Sep 20, 2007

Hey bros; question on Macros. I've read the 2018 book page on Macros and a few tutorials. I've never seen anything like this in my programming experience; this is beautiful, and completely appropriate for a use case I'm about to describe: I'd like to build a frontend framework using bindgen.

I'd like to make a custom syntax for making HTML elements, where I've defined an element to have attributes, style, a tag type, text, and children, most of which are optional. It looks like you can do a lot with macros; implement JSX/etc without regex and strings; make a whole new sub-language inside rust? There are no rules.

Struct I'd like to make a nice creation syntax for:
Rust code:
pub struct El {
    pub tag: Tag,
    pub children: Vec<El>,
    pub attrs: Attrs,  // Attrs and Style are thinly-wrapped HashMaps
    pub style: Style,
    pub text: Option<String>,
}
With creation syntax something like this:
Rust code:
// The tuples are due to lack of a HashMap literal syntax in rust... which I'm suspicious could also be fixed using macros.
!div[ [("alt", "a div")], [("color", "black"), ("display", "grid")] ]  // attrs, and style only

!h2[ [("alt", "a div")],  "text" ]  // attrs and text, which it could infer from types

!h2[ style=[("color", "black")] ,  "text" ]  // style and text
Should I use a declarative macro, or a procedural one? Are they effectively equivalent, but with the former using regex-like syntax, and the latter using something more akin to a normal function? It seems like I could accomplish this in either.

Dominoes fucked around with this message at 03:46 on Nov 19, 2018

Dominoes
Sep 20, 2007

Arcsech posted:

I don't know much about macros, but I just saw earlier today that someone beat you to this, you might be able to take a look at what they do: https://github.com/bodil/typed-html

It looks like they're using procedural macros? I think? I haven't really touched macros at all, I really should.
Thanks! Looks like there are several libs trying what I describe already; pressing anyway! I love JSX... Or thought I did. I loved being able to integrate HTML and styles with code logic, vice in separate templates. Not crazy about the syntax itself; going to try to keep this Rust-like, but with terse syntax.

There's a popular lib called Yew that uses something similar to that, but it uses stdweb, vice bindgen.

Any ideas on how to handle making proc macros a sep crate (as they evidently require) without being codependent with the main crate? It looks like in that and other examples, the proc_macro crate never refs the main crate; I think they're putting all the types that may need to be returned in it... which begs the question of what actually needs to be in the (main / outer) non proc-macro crate.

Dominoes fucked around with this message at 06:00 on Nov 19, 2018

Dominoes
Sep 20, 2007

Hey dudes. Running into an issue with passing closures around. I've distilled a somewhat-more detailed problem into the basics:
Playground

Rust code:
use std::boxed::Box;

struct Event {
    val: String
}

struct Element {
    events: Vec<Box<FnMut() -> Event>>
}

impl Element {
    fn add(&mut self, handler: impl FnMut() -> Event + 'static) {
        self.events.push(Box::new(handler));
    }
}

// If you comment this out and use the add method above, it works.
fn create(event: Event) -> Element {
    let mut el = Element { events: Vec::new() };
    el.events.push(Box::new(|| event));
    el
}


fn main() {
    // error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
    let event = Event { val: "test".into() };
    let el = create(event);
    
    // let mut el = Element { events: Vec::new() };
    // el.add(|| event);
    
}
 
Essentially, the el.add() method, and the create() function should do the same thing, but the method works while the func doesn't. I'm building an API, and know how I want people to interact with it, so I'd like to get the function Actually a mischievous macro approach working. Any ideas on how to reflow this? For reasons not obvious in this example I don't wish to eschew the event type, but I suspect its existence, and reluctance to allow its contents to be stolen is the problem. If I could politely instruct it to die after the create method is run, the problem would be solved.

Dominoes
Sep 20, 2007

Thanks a lot! The trick was the clone + move you mentioned.

Dominoes
Sep 20, 2007

Looking for critique and suggestions for a web framework I'm working on. Repo. Mainly regarding the guide (Readme) and API. My goal is for this to be accessible to web programmers who are not familiar with Rust. Motivation was the messy JS tooling and ecosystem, and the poor documentation of existing Rust/WASM frameworks.

I hope to publish it on crates.io within the next few weeks. I have an API I like, and a basic virtual DOM is almost ready with plenty of room for optimization. I have a good deal of work to do on cleaning up how events trigger; struggling on that one. Simple clicks etc work, but anything involving accessing event parameters (like text input) is a WIP. Also need to either integrate, or document wasm-bindgen's fetch API, and how you'd use it with Serde to communicate with a server. And a router.

Dominoes fucked around with this message at 07:32 on Dec 9, 2018

Dominoes
Sep 20, 2007

rt4 posted:

I look forward to giving this a shot. I've been really frustrated with how the Yew project can't be bothered to write any useful docs and Elm just feels so tedious sometimes...
What in particular to you find tedious about Elm? I'd like to avoid that.

Dominoes
Sep 20, 2007

crazypenguin posted:

Is there a reason you're not having people use wasm-pack?
I couldn't get its --no-modules feature working, and, at least on my system, it strips compiler errors of their colors, and it dumps extra files into the pkg directory. I'll probably switch once sorted - hopefully it will preclude the need for the custom build script.

For the first issue, the command is apparently wasm-pack build --target nomodules, but I can't get it working.

Of note: Chat about no-modules

edit: Attempted again now: running into an error about failing to read Cargo.toml.
edit2: I should probably just submit issues/PRs instead of waiting; the maintainers seem like the type who'd appreciate it.

Dominoes fucked around with this message at 19:21 on Dec 9, 2018

Dominoes
Sep 20, 2007

I appreciate how in languages like Python and Rust, you can choose which functional concepts when you'd like (Often directly inspired by languages like Haskell), without the associated restrictions.

Dominoes
Sep 20, 2007

Clippy is really, really good! My experience with linters:

TSlint/Jslint, as supplied by Create-React-App: Mostly subjective style enforcement that makes the app a pain to transpile; ended up turning off most lints, then abandoning the tool.

Clippy: Makes consistently good recommendations to make code more readable, avoid traps, and teach about language features.

Dominoes
Sep 20, 2007

Hey dudes, published an initial v of my frontend-framework crate. Any suggestions/critique on API/docs etc would be appreciated. Or just making sure that you can get a hello-world working using the quickstart info.

There's a nasty bug lurking somewhere in the vdom.
edit: nasty bug fixed.

Dominoes fucked around with this message at 00:24 on Dec 15, 2018

Dominoes
Sep 20, 2007

Good call. Updated repo and quickstart.

Dominoes
Sep 20, 2007

I'm working on a WASM frontend crate, seed

Dominoes
Sep 20, 2007

Rust code:
struct Node {
    id: u32,
    s: [f64; 3],
    v: [f64; 3],
}

struct Edge {
    id: u32,
    nodes: [u32; 2],
}

struct Shape {
    edges: Vec<u32>
}
You could add faces using similar logic.

For your request, nesting the structs will work fine and may be more transparent. The id-based approach here is more generalizable to rendering arbitrary scenes.

Dominoes fucked around with this message at 05:06 on Aug 7, 2019

Dominoes
Sep 20, 2007

Rust's made me a lazy programmer. If I hosed something up (especially while refactoring), I step through each compiler error, and bam! It works. Thought about this after reading This controversial Jonathan Blow article - he cites dynamically-typed footguns as a reason for unit testing... got me thinking that Rust's compiler and type system accomplishes some of the same things as aggressive unit-testing, without the API inertia.

Dominoes
Sep 20, 2007

rt4 posted:

I've been thinking lately that Javascript is the language where I really need unit tests because I have no idea what the code on my screen actually does
I still can't get unit tests to work in JS!

Dominoes
Sep 20, 2007

Arcsech posted:

And you don’t need a PhD in math to make sense of it, unlike Haskell
Monad: (n) a proof by example that a concept can exist, but be impossible to explain using verbal or written language.

Dominoes
Sep 20, 2007

I have a diff trait question: How do you find trait bounds in lib docs? Usually the docs and compiler messages are clear, but I'm striking out on both counts. Example: here. At the top, it defines bounds on I2C, but not I2CInterface

Dominoes
Sep 20, 2007

Thank you; that sorts it out. Of note, some of the items in <> in that page are in the docs (and are linked), while most aren't. I'd assumed it not being in the docs meant it was a trait.

Dominoes
Sep 20, 2007

Used a lifetime for the first time today. It's always been a feature I've never needed to use, in my range of Rust projects. The case was trying to format strs using byte buffers in a no_std / no allocator environment. The resulting &'static str needed to be tied to the buffer arg.

Dominoes
Sep 20, 2007

Hey, just wanted to say, Rust owns.

It has warts; Async can DIAF, the all collection-related functional syntaxes are a mess (escape hatch: the for loop), and generics are IMO a choice of last resort, not first option.

The more dogmatic/idealistic parts of the community need to go away. (Ie the safety woke)

That said... Show me else where you can find a language that respects user time, battery life, electricity use etc, and is also memory-safe, relatively smooth experience, has the good parts of functional programming etc. Bottom line is, you could imagine a language better than Rust, but it's currently the best we've got. C and C++ have so many syntax and program-structure warts and traps, ADA is impractical for many uses, and almost all other languages are slow. (Which IMO is disrespectful and rude, and why computer programs still have noticeable impact lag, laptops are crap battery life etc even as hardware improves).

Dominoes fucked around with this message at 18:30 on Oct 25, 2022

Dominoes
Sep 20, 2007

Yea def. Rust's built in tooling is outstanding. C and C++ build systems are a relative disaster. Feels like it comes down to a project -sprcific recipe that may or may not work depending on OS state

Dominoes
Sep 20, 2007

StumblyWumbly posted:

Wait what? Is this just a reference to how efficiently it executes, or does Rust have some kind of sleep state support? I'm coming from a low port ARM microcontroller world, and Rust has been on my "maybe someday" list for a while.
I was referring to the former! I think generally on desktop PCs the OS handles the latter. Not sure if an application could (or should?) bypass that by firing off the correct reg writes or w/e.

You should try Rust on ARM. IMO well-suited to that domain. Which MCUs specifically?

Dominoes fucked around with this message at 14:53 on Oct 27, 2022

Adbot
ADBOT LOVES YOU

Dominoes
Sep 20, 2007

Nice! U5 is cutting edge. I made a Rust HAL for STM32 that works on most newer families. Intent is to support U5, but waiting on the PAC (named register definitions generated from SVD) to come out from the `stm32-rs` team on that. Hopefully is pretty similar to L5.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply