[HN Gopher] Nibbles of Rust - Restructuring Patterns
___________________________________________________________________
Nibbles of Rust - Restructuring Patterns
Author : g0xA52A2A
Score : 111 points
Date : 2023-04-16 08:21 UTC (14 hours ago)
(HTM) web link (www.catmonad.xyz)
(TXT) w3m dump (www.catmonad.xyz)
| pflanze wrote:
| The author talks about adding structure, and I've been puzzled
| about what they are talking about until realizing that they
| apparently mean that a reference to something is "more" than the
| something hence it "adds structure". That doesn't make sense to
| me. More structure is if there are more elements in the data
| (more fields in a struct, or more alternatives in an enum),
| whereas a reference is just an indirection of access.
|
| Or am I missing something?
| clord wrote:
| &T, &mut T, and T are all different types in a sense. Hence ref
| is transmuting types during restructuring.
|
| Really, they are adding a new view, so perhaps this is like
| Haskell lenses, where you can make views with a different type
| that acts on underlying data
| fkcgnad wrote:
| [dead]
| bobbylarrybobby wrote:
| I think it's "more" in the same sense that Some(x) is more than
| x. You can destructure &x in exactly the same way.
| cstrahan wrote:
| The set of all &T is larger than the set of T.
|
| Let's consider the case where T is u8. There are 256
| inhabitants of the u8 type (0u8-255u8).
|
| Now consider &u8. Each u8 referent is still some value between
| 0 and 255, but the number of references you could have is
| dependent on the pointer width of your target system -- let's
| say 64 bits. So that's 2^8 possible u8 values times 2^64
| possible references, or 2^72 inhabitants. Well, minus one to
| account for null, and I'm probably missing other details, but
| you get the idea.
|
| So going from T to &T introduces structure in the same sense
| that going from T to (T, U) does; and going from &T to T
| destructures in the same sense that going from (T, U) to T
| does. That structure may not be directly observable (as in the
| case of a reference: you'd have to go out of your way to
| observe the underlying address), but conceptually the structure
| is there nonetheless.
|
| Edit:
|
| Another way to look at it is this:
|
| Consider a Rust "newtype", like struct Days(u8).
|
| If you pattern match on that to obtain the inner u8, we call
| that destructuring. Destructuring is to reduce or break down
| the structure of a thing, so the opposite must be building up
| structure, or "restructuring". Therefore going in the opposite
| direction -- stuffing a u8 value in a Days - must be
| restructuring. In this case both types have the same number of
| inhabitants (256); regardless, one direction is destructuring
| and the other direction is restructuring.
| juancampa wrote:
| I don't understand why go through the complication of giving this
| a new name (i.e. "Restructuring Pattern") where the second
| explanation seems more intuitive and correct.
|
| "Restructuring Pattern" sounds like you can put back together a
| struct from its constituents, but that's done by normal struct
| instantiation.
| fkcgnad wrote:
| The author is talking about restructuring syntax in the
| destructing match.
|
| Rust Has this with "match" but only via a single ref.
|
| You would have to make alternative restructuring syntax to go
| into the match expression if you want it to work.
|
| Hypothetically: fn g(v: Option<i32>) ->
| Option<Option<i32>> { match v {
| Some(_Some(_Some(x))), None(_None)
| } }
|
| Any character with an underscore is a "restructuring" syntax
| here. Rust only does restructuring with references via the ref
| keyword and it only does it once per var per expression. The
| syntax I presented here is hypothetical of course.
|
| I would say it's more syntactic sugar as you can do the
| restructuring on the right side of the match expression. You
| can make up an entire functional language using this technique
| and eliminate the => and everything after it.
|
| I largely agree with you that it's not exactly necessary to do
| this. Arguably it makes things harder to read.
| fmiras wrote:
| nice reading!
| rtpg wrote:
| Nice tip.
|
| I honestly am a bit frustrated with Rusts pattern matching
| ergonomics, cuz it ends up requiring me to introduce indentation
| in places where I don't want it, mainly to futz around with
| unwrapping structures or the like.
|
| Lots of helper methods exist on standard library enumerations but
| I really want there to be some nice built in macros to just give
| me the innards when I need it, and have a control flow block for
| when I _cant_ pattern match (and thus want to do an early return
| or blow up). Maybe this already exists!
|
| Too much indentation makes languages unfun (see every lisp
| struggle with this with name binding)
| spease wrote:
| You mean like 'matches!'?
|
| https://doc.rust-lang.org/std/macro.matches.html
| rtpg wrote:
| What I want is..
|
| let MyEnum(foo, bar, baz) = input but otherwise { do some
| stuff return some value }
|
| Point being I don't have to check for MyEnum-ness twice (like
| with matches! + if let) and the indented code is for the
| exception (no match) not the norm.
|
| Tho I ... guess !matches(MyEnum{ .. }) is not the worst...
| but it's annoying to have this pattern all over my code
| instead of as some encoded concept we all use
| ljsb wrote:
| You were pretty close with your hypothetical syntax! You
| can write: let Some(y) = x else {
| do_stuff(); return };
|
| I think it was a fairly recent addition to Rust.
| metadat wrote:
| What determines whether `let Some(y) = x` evaluates to
| boolean true?
| asherah wrote:
| if x is `Some`, then `y` is set to the inner value and
| the following block occurs. you can also use this with
| other enums - i don't remember off the top of my head if
| it works for all enums, but you can at least also use it
| with `Result`
| jeffdn wrote:
| It absolutely works for all patterns!
| bombela wrote:
| The fact that the pattern matches.
|
| Here the type being matched is: enum
| Option<T> { None, Some(T)
| } let x = Some(42); let Some(y) = x
| else { panic!("None") };
| rtpg wrote:
| Thank dog for that. I feel like I even read the release
| notes for that but it was while I hadn't been touching a
| specific codebase with loads of early returns. Thanks for
| pointing this out!
| chrismorgan wrote:
| let-else was stabilised in 1.65.0, released 2022-11-03.
| e-dant wrote:
| Use combinators!
| lloydatkinson wrote:
| I think there needs to be a "center the page" browser extension
| because this is just absurd: https://imgur.com/a/HZqaA4V
| muattiyah wrote:
| I always thought it was weird when people have websites like
| this, anyways, for those phased away and want to read this
| article while centered, execute in the console:
| document.getElementsByTagName('body')[0].children[0].style.marg
| in = '0 auto';
| lloydatkinson wrote:
| That's a good tip! I also think its just as weird when sites
| have zero links to their home page. On what planet is "go to
| the address bar and delete the last part of the url and hit
| enter to go to the index" good user experience?
| Monadic-Cat wrote:
| Agreed. It was a good tip.
|
| My goal in leaving out the link to my home page was to make
| the Writing Gaggle home page more prominent than my
| personal blog. (I manage hosting both, see.) I only added
| my blog index page as an afterthought when I saw a ton of
| 404 errors on my server a few months ago because people
| were manually navigating to it.
|
| I'll consider adding actual navigation to my page template
| though, so maybe you'll be less annoyed ;)
| Monadic-Cat wrote:
| I'll go ahead and promise to leave the '#wrapper' id on that
| element in my blog template, so this can be shortened to:
| document.getElementById('wrapper').style.margin = '0 auto';
|
| Though if you're in the habit of customizing sites you read,
| I'd personally recommend using a browser extension like
| Stylus (https://add0n.com/stylus.html) to do CSS, so you
| could write it like this: #wrapper {
| margin: 0 auto; }
| kibwen wrote:
| Ctrl+Shift+K for the web console, then
| `document.body.style.display = "flex";
| document.body.style.justifyContent = "center";`.
| kps wrote:
| Text becomes hard to read when lines are much over 70
| characters. I don't know that there's a universally preferred
| solution. Personally, I only use movie-shaped windows for
| movies, and page-shaped windows for everything else.
| avtar wrote:
| Firefox has built-in reader view, and whatever the Chrome
| equivalent is.
| ebresafegaga wrote:
| This sounds like view patterns in Haskell / active patterns in F#
| cinericius wrote:
| Since the author mentions at the end that they were motivated to
| write and publish this as a part of a writing group, I'd like to
| say that this was a very pleasant read. Tightly-scoped but
| insightful and informative!
| Monadic-Cat wrote:
| Thanks! (Post author. I made an HN account to reply here,
| haha.)
___________________________________________________________________
(page generated 2023-04-16 23:02 UTC)