soooooo I had this like, weird structure in Rust that was a struct that held an Option> and I used a match statement on the From implementation to determine whether it was a 'real' instance of the struct that contained all the real values, or whether i...
-
just a little like... always a little weirded out when that happens.
-
Xandra Granade 🏳️⚧️replied to Asta [AMP] last edited by
@aud It's amazing how much a well-designed type system lets you separate different bits of code.
-
Asta [AMP]replied to Xandra Granade 🏳️⚧️ last edited by [email protected]
@[email protected] right? although interestingly, I realized this means if I want to use the struct defined within the enum in a match statement, I have to unpack each variable within the match itself rather than having a single variable to use : (
-
@[email protected] well, actually, I only have to unpack the ones I want, which isn't too bad but in this case I want literally all of them.
-
Xandra Granade 🏳️⚧️replied to Asta [AMP] last edited by
@aud Is it possible to use the @ operator to name the match pattern, `Foo { .. } @ foo` or something?
-
Asta [AMP]replied to Xandra Granade 🏳️⚧️ last edited by [email protected]
@[email protected] hmmm... so hilariously I didn't realize that operator existed
(me earlier: "time to put Rust on my CV!")
But also... I'm not sure it does work here, although I'm still playing around with it. I can definitely use it but it doesn't seem to match what I want (which is basically packing all the internal struct fields into a variable).
https://doc.rust-lang.org/beta/book/ch18-03-pattern-syntax.html
The use case they have there (search for bindings) is definitely useful, although not quite what I'd like in my case.
What I would like is something like this:
(where Object has a field called id). This doesn't seem to work. Neither does:match self { Object::Object { obj } => { if obj.id.is_some() { ds.field("id", &self.id().unwrap()); }
that one is sort of easy; I'm just like... pointing to the struct variant rather than a real thing. But even if I try and add anything such as...match self { obj @ Object::Object => { if obj.id.is_some() { ds.field("id", &self.id().unwrap()); }
The error complaining aboutmatch self { obj @ Object::Object { .. } => { if obj.id.is_some() { ds.field("id", &self.id().unwrap()); }
obj
just pointing to a struct variant goes away, but I still can't access the fields.
I'm guessing I have little choice except to basically unpack all the struct fields.
Still, really cool stuff with the@
operator. -
@[email protected] ... also ignore all the unclosed braces. hah.
-
Xandra Granade 🏳️⚧️replied to Asta [AMP] last edited by
@aud I apologize for the distraction, but is there a bit you can throw into a pastebin or Rust Playground or something? I'm really curious now, you've kind of nerdsniped me with this!
-
Asta [AMP]replied to Xandra Granade 🏳️⚧️ last edited by
@[email protected]
sure! Just gimme a second here... -
@[email protected] https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=69b24bbfcad69237ac308502691c0eb6
Okay! That's a cut down version of what I'm working on
(normally I never use the termObject
in a program, ever, for a trillion reasons, but this is from the ActivityStreams stuff I'm doing and there areObjects
everywhere) -
@[email protected] The 'goal' here (because my real
Object
has like, 33 fields) would be to not have to write something like:Object::Object { _contextAndType, id, attachment, attributedTo, audience, content, context, contentMap, name, nameMap, endTime, generator, icon, image, inReplyTo, location, preview, published, replies, startTime, summary, summaryMap, tag, updated, url, to, bto, cc, bcc, mediaType, duration, _extra, _extends }
in the match statement, but instead something much more concise -
@[email protected] Not only is this rather unreadable (I want readable code!) because it's just a lot, but maintenance would be a nightmare (not that I expect ActivityPub/ActivityStreams to change)
-
Xandra Granade 🏳️⚧️replied to Asta [AMP] last edited by
@aud `fucksticks`, I love it! Thanks for posting that, I'll go take a look (she said, as a form of procrastination and sharing in something cool with adjacent nerds).
-
Asta [AMP]replied to Xandra Granade 🏳️⚧️ last edited by
@[email protected] thanks. I usually use song lyrics when I'm in a professional setting (or silly movie quotes; pretty sure I wrote a unit test at Cray that used lines from Blade Runner just because I could)...
... but here, it's fuck all the way! Interestingly, I'm still at only 5 instances of the word "fuck" in the codebase. -
Xandra Granade 🏳️⚧️replied to Xandra Granade 🏳️⚧️ last edited by
@aud Oh, I see the problem, yeah. The enum case is a struct variant, but that struct isn't its own named type. That makes it impossible to name in a pattern, since a match to that pattern then wouldn't have a type at all.
There was some discussion in RFCs for making enum variants types in their own right (https://github.com/rust-lang/rfcs/pull/2593#issuecomment-823429982), and I seem to recall there being a crate that had a macro for doing that...
-
Xandra Granade 🏳️⚧️replied to Xandra Granade 🏳️⚧️ last edited by
@aud It's a bit ugly, but if you define the struct externally to the enum, then the patterns work out great.
Rust Playground
A browser interface to the Rust compiler to experiment with the language
(play.rust-lang.org)
-
Asta [AMP]replied to Xandra Granade 🏳️⚧️ last edited by
@[email protected] aha! Yeah, I briefly did that... then realized it messed with my elegant change from earlier and would require rewriting the other functions
It's sort of a balance, isn't it, between getting as much out of the type system as possible and also retaining flexibility. As an unrelated example, in this code, currently anything that extends fromObject
in ActivityStreams (which is like 99% of it) is ... well, anObject
. I'm like... well, I didn't really retain much benefit from the type system in this case, did I.
I see why other crates have done it with traits now, but my brain just still kind of hates it and I think it makes it a lot harder to grok both the code and the ActivityStreams objects themselves.
I hardly think it's a code requirement, but I don't think you could easily learn ActivityStreams from the crates I've seen thus far. I would like for my own code to be able to do that for someone, however, if possible. I guess that's why I'm torturing the type system like this. -
Xandra Granade 🏳️⚧️replied to Xandra Granade 🏳️⚧️ last edited by
@aud @yosh's blog post on state machines from a few years ago goes into that a bit as well: https://yosh.is/writing/state-machines
-
Xandra Granade 🏳️⚧️replied to Asta [AMP] last edited by
@aud There does in general seem to be a bit of a mismatch between the JavaScript everything-is-a-dict kind of view and the much more strongly typed view that Rust takes.
Shit like C# gets around it by using open-ended polymorphism, but it's surprisingly nontrivial to just write down what the type of a JSON object *is*.
-
Xandra Granade 🏳️⚧️replied to Xandra Granade 🏳️⚧️ last edited by
@aud Bonus points if you can somehow avoid `dyn` in writing that type.