Live data from Hacker News

Rust's Block Pattern

notgull.net

11–20 of 121 posts

Re: Rust's Block Pattern

#11
More significantly the new variables x and y in the block are Drop'd at the end of the block rather than at the end of the function. This can be significant if:

- Drop does something, like close a file or release a lock, or

- x and y don't have Send and/or Sync, and you have an await point in the function or are doing multi-threaded stuff

This is why you should almost always use std::sync::Mutex rather than tokio::sync::Mutex. std's Mutex isn't Sync/Send, so the compiler will complain if you hold it across an await. Usually you don't want mutex's held across an await.

Re: Rust's Block Pattern

#12
There are some situations with tricky lifetime issues that are almost impossible to write without this pattern. Trying to break code out into functions would force you to name all the types (not even possible for closures) or use generics (which can lead to difficulties specifying all required trait bounds), and `drop()` on its own is of no use since it doesn't effect the lexical lifetimes.

Re: Rust's Block Pattern

#16
This is one of those natural consequences of "everything is an expression" languages that I really like! I like more explicit syntax like Zig's labelled blocks, but any of these are cool.

Try this out, you can actually (technically) assign a variable to `continue` like:

let x = continue;

Funnily enough, one of the few things that are definitely always a statement are `let` statements! Except, you also have `let` expressions, which are technically different, so I guess that's not really a difference at all.

Re: Rust's Block Pattern

#18
post #5

The first example given is not at all convincing. Its is clear as the sky that loading the config file should be be a separate function of its own. Coupling sending HTTP requests with it makes no sense. The second example "erasure of mutability" makes more sense. But this effectively makes it a Rust-specific pattern.

It's essentially an inline function with only 1 client. Can be a preference for inline readability and automatically enforces there are no other clients of the "function".

Re: Rust's Block Pattern

#19
I often employ this pattern in Ruby using `.tap` or a `begin` block.

It barely adds any functionality but it's useful for readability because of the same reasons in the OP.

It helps because I've been bitten by code that did this:

  setup_a = some_stuff
  setup_b = some_more_stuff
  i_think_this_is_setup = even_more_stuff
  the_thing = run_setup(setup_a, setup_b, i_think_this_is_setup)
That's all fine until later on, probably in some obscure loop, `i_think_this_is_setup` is used without you noticing.

Instead doing something like this tells the reader that it will be used again:

  i_think_this_is_setup = even_more_stuff
  
  the_thing = begin
    setup_a = some_stuff
    setup_b = some_more_stuff
    run_setup(setup_a, setup_b, i_think_this_is_setup)
  end
I now don't mentally have to keep track of what `setup_a` or `setup_b` are anymore and, since the writer made a conscious effort not to put it in the block, you will take an extra look for it in the outer scope.
Post reply on HN