Hacker Newsnew | past | comments | ask | show | jobs | submit | conaclos's commentslogin

I recently started working with Rust async. The main issue I am currently facing is code duplication: I have to duplicate every function that I want to support both asynchronous and blocking APIs. This could be great to have a `maybe-async`. I took a look at the available crates to work around this (maybe-async, bisync), but they all have issues or hard limitations.

There is work happening on keyword generics[0], which would let a function be generic over keywords like `async` and `const`.

For now the best option to write code that wants to live in both worlds is sans-io. Thomas Eizinger at Fireguard has written a good article about this[1] pattern. Not only does it nicely solve the sync/async issue, but it also makes testing easier and opens the door to techniques like DST[2]

I have my own writing on the topic[3], which highlights that the problem is wider than just async vs sync due to different executors.

0: https://github.com/rust-lang/effects-initiative

1: https://www.firezone.dev/blog/sans-io

2: https://notes.eatonphil.com/2024-08-20-deterministic-simulat...

3: https://hugotunius.se/2024/03/08/on-async-rust.html


Keyword generics are probably not happening because it's kinda a hack.

Algebraic effects are the way forward, but that's a long way off.


Yes I hope in the future we can get to what OCaml 5 has with their algebraic effects system, and hopefully fix any flaws we see in there, so that async will just be syntactic sugar over the underlying effects system.

Considering the latest commits and issues in effects-initiative are about 2 years old, the keyword generics initiative seems effectively dead.

Rust uses Zulip for lang-related discussions. The 't-lang/effects' channel is still somewhat active.

I may have missed something, but how does “sans-io” deal with CPU heavy code? For example, if there’s some heavy decoding/encoding required on the data? Does the event loop only drive the network side and the heavy part is done after the loop is finished?

This is a great question and there isn't a definitive answer provided in the sources I linked.

Broadly I think there are three approaches:

1. For frequent and small CPU heavy tasks, just run them on the IO threads. As long as you don't leave too long between `.await` points (~10ms) it seems to work okay.

2. Run your sans-io code on a dedicated CPU thread and do IO from an async runtime. This introduces overhead that needs to be weighed against the amount of CPU work.

3. Have the sans-io code output something like `Output::DoHeavyCompute { .. }` and later feed the result back as `Input::HeavyComputeResult { .. }`, in the middle run the work on a thread pool.


Realised all of these examples are for async, but they apply equally for sync.

You won't get any benefits using async with CPU heavy code. Quite the opposite really.

> For now the best option to write code that wants to live in both worlds is sans-io

Thanks for sharing! Reading the articles, it looks at me, it is a kind of manual reimplementation of the state machine generated by async? This also makes the code harder to reason with. I am unsure if it is worth the complexity.


It'll depend immensely on what you're actually doing, but if it's simple enough you may be able to make a macro that subs out the types & awaits

One of the issue I face is a blocking function that takes a generic constrained by a `trait` and its async version takes a generic constrained by an `async trait`.

In my perspective, an "async" function is already an "maybe-async". The distinction between a a `fn -> void` and `fn -> Future<void>` is that the former executes till its end immediately, whereas the other may only finish at another time. If you want to run an async fn in a blocking manner, you would use a blocking executor.


There is a relevant Wikipedia page about minifloats [0]

> The smallest possible float size that follows all IEEE principles, including normalized numbers, subnormal numbers, signed zero, signed infinity, and multiple NaN values, is a 4-bit float with 1-bit sign, 2-bit exponent, and 1-bit mantissa.

[0] https://en.wikipedia.org/wiki/Minifloat


Have you tried `firefox --no-remote --profile <path>`?

In my case, I am able to launch several Firefox instances with distinct profiles.


Note that `--no-remote` breaks starting new browser windows from outside, which users normally want.

I'm starting to think that setting the `HOME` environment variable is the only way to really make things isolated - this still won't handle `~insertusernamehere` but basically everything else respects it.


--no-remote doesn't do anything anymore. It was removed about a year ago if memory serves.


I do `open -n "/Applications/Firefox.app" --args -p myprofilename` and that does the trick on mac


On windows powershell I do Start-Process "C:\Program Files\Mozilla Firefox\firefox.exe" -ArgumentList "-P default-release" Which is the exact same idea.


How does that integrate with the "Dock" or menu bar at the bottom? (new to Mac)


Yes, I tried that and everything else. Either it refuses to launch with `--new-instance` or (from memory, in the case of your command) subsequent `--new-tab`s may open in the wrong profile. Presumably due to the order in which the original instances were created. The point is that the system turns on these UIDs, which are not paths or even hashes of paths.


I tried Helix two years ago, unfortunately the default keymap was a bit frustrating to me. I don't mind changing my habits, however I had difficulty I made sense of the keymap design.

For example, typing `w` select the word. However, typing `2w` select the second word and not two words. To select two words you have to enter in visual mode (`v2w`). To remove two words you thus need to type `v2wd` or `wdwd`. In Vim you can type `d2w`. I miss this composability. In Kakoune (one of the main inspiration of Helix), you can type `2Wd` (`2wd` has the same behavior as Helix).

I was also hoping that the use of Ctrl/Alt modifiers be completely removed. Why not fully embrace modal editing?


If I remember correctly, TCO is now part of the ECMAScript standard. Safari has implemented it. The issue is that others engines have not because they are concerned about stack unwinding and stacktraces.


UFCS and the implicit `result` variable remember me the Eiffel programming language [0].

[0] https://en.wikipedia.org/wiki/Eiffel_(programming_language)


The following articles may also be of interest to the audience:

- The definitive guide to error handling in Rust [0]

- Error Handling for Large Rust Projects - Best Practice in GreptimeDB [1]

- Designing error types in Rust [2]

- Modular Errors in Rust [3]

[0]: https://www.howtocodeit.com/articles/the-definitive-guide-to... [1]: https://greptime.com/blogs/2024-05-07-error-rust [2]: https://mmapped.blog/posts/12-rust-error-handling [3]: https://sabrinajewson.org/blog/errors


I was quite excited by the description and then I noted that Bolt heavily relies on double floating point numbers. I am quite disappointed because this doesn't allow me to use Bolt in my context: embedded systems where floating point numbers are rarely supported... So I realized that I misinterpreted `embedded`.


Same here! It's very cool but my ideal use case would be on a limited ISA architecture like ESP32.


Bolt doesn’t support ARM or RISC. There’s some comments above re: the confusion with the term “embedded” and “real time”.


I think you might have misread our comments, that is exactly what we are lamenting.


I like the idea of repeating the delimiter on every line. However `//` looks like a comment to me. I could simply choose double quote:

    const still_raw =
        "const raw =
        "    "Roses are red
        "    "  Violets are blue,
        "    "Sugar is sweet
        "    "  And so are you.
        "    "
        ";
        "
    ;
This cannot be confused with a string literal because a string literal cannot contain newline feeds.


What if you have something like

    const raw =
        "He said "Hello"
        "to me
    ;
Wouldn't that be a mess to parse? How would you know that "He said " is not a string literal and that you have to continue parsing it as a multiline string? How would you distinguish an unclosed string literal from a multiline string?


I got a 404. IS the website still online?


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: