Live data from Hacker News

Rust's Block Pattern

notgull.net

41–50 of 121 posts

Re: Rust's Block Pattern

#41
I think the technique is important to have in your vocabulary, but I think the examples given are a weak sell.

In the example given, I would have preferred to extract to a method—-what if I want to load the config from somewhere else? And perhaps the specific of strip comments itself could have been extracted to a more-semantically-aptly named post-processing method.

I see the argument that when extracted to a function, that you don’t need to go hunting for it. But if we look at the example with the block, I still see a bunch of detail about how to load the config, and then several lines using it. What’s more important in that context—-the specifics of the loading of config, or the specifics of how requests are formed using the loaded config?

The fact that you need to explain what’s happening with comments is a smell. Properly named variables and methods would obviate the need for the comments and would introduce semantic meaning thru names.

I think blocks are useful when you are referencing a lot of local variables and also have fairly localized meaning within the method. For example, you can write a block to capture a bunch of values for logging context—-then you can call that block in every log line to get a logging context based on current method state. It totally beats extracting a logging context method that consumes many variables and is unlikely to be reused outside of the calling method, and yet you get delayed evaluation and single point of definition for it.

So yes to the pattern, but needs a better example.

Re: Rust's Block Pattern

#43

I love that this is part of the syntax. I typically use closures to do this in other languages, but the syntax is always so cumbersome. You get the "dog balls" that Douglas Crockford always called them: ``` const config = (() => { const raw_data = ... ... return compiled; })()' const result = config.whatever; // carry on return result; ``` Really wish block were expressions in more languages.

By the by, code blocks on here are denoted by two leading spaces on each line

  like
  this

Re: Rust's Block Pattern

#44
post #28

I have one better: the try block pattern. https://doc.rust-lang.org/beta/unstable-book/language-featur...

Why does this need special syntax? Couldn't blocks do this if the expression returns a result in the end?

Not without being able to use the ? operator.

The closest thing I can think of that will let you return a result from within a separate scope using a set of foo()? calls would be a lambda function that's called immediately, but that has its own problems when it comes to moving and it probably doesn't compile to very fast code either. Something like https://play.rust-lang.org/?version=stable&mode=debug&editio...

Re: Rust's Block Pattern

#45
post #24

I have one better: the try block pattern. https://doc.rust-lang.org/beta/unstable-book/language-featur...

I want that stabilized so bad but it's not been really moving forward.

There's some active work recently on fixing blocking issues, e.g.:

https://github.com/rust-lang/rust/pull/148725

https://github.com/rust-lang/rust/pull/149489

Re: Rust's Block Pattern

#46

It's idiomatic in Kotlin as well! https://kotlinlang.org/docs/scope-functions.html

So many options why oh why. let run with also apply

Each does different things, and Rust also has plenty of them. and_then(), or(), or_else(), then(), the list goes on. Kotlin just implements them more widely.

Actually, Kotlin's with() and apply() are more powerful than what Rust can provide. Then again, Rust isn't designed with OO in mind, so you probably shouldn't use those patterns in Rust anyway.

Re: Rust's Block Pattern

#48
post #23

Not mentioned in the article but kinda neat: you can label such a block and break out of it, too! The break takes an argument that becomes the value of the block that is broken out of.

I just learned this one, and am gradually starting to use it! It applies for loops too. I saw it in ChatGPT code, and had to stop and look it up. Rust is a big language, for worse and for better.

I wouldn't call Rust "a big language" because of labeled break. This is a pretty standard language feature, you can do the same in C (and therefore C++), Go, Javascript, Java, C#...

Re: Rust's Block Pattern

#49
Blocks being expressions is one of the features of the Rust language I really love (and yes I know it's not something Rust invented, but it's still not in many other popular languages).

That last example is probably my biggest use of it because I hate having variables being unnecessarily mutable.

Re: Rust's Block Pattern

#50
post #32

This is also somewhat common in c++ with immediate-invoked lambdas

The same pattern can also be useful in Rust for early returning Result errors (you cannot `let x = foo()?` inside of a normal block like that).

    let config: Result = {
        Ok(
            "1234".parse::().map_err(|_| -1)?
        )
    };
would fail to compile, or worse: would return out of the entire method if surrounding method would have return type Result. On the other hand,

    let config: Result = (||{
        Ok(
            "1234".parse::().map_err(|_| -1)?
        )
    })();
runs just fine.

Hopefully try blocks will allow using ? inside of expression blocks in the future, though.

Post reply on HN