frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

Show HN: Refine – A Local Alternative to Grammarly

https://refine.sh
42•runjuu•2h ago•10 comments

Let's Learn x86-64 Assembly (2020)

https://gpfault.net/posts/asm-tut-0.txt.html
231•90s_dev•9h ago•48 comments

Show HN: Ten years of running every day, visualized

https://nodaysoff.run
374•friggeri•3d ago•153 comments

Emergent Misalignment: Narrow finetuning can produce broadly misaligned LLMs

https://arxiv.org/abs/2502.17424
94•martythemaniak•7h ago•26 comments

OpenCut: The open-source CapCut alternative

https://github.com/OpenCut-app/OpenCut
309•nateb2022•10h ago•92 comments

A Century of Quantum Mechanics

https://home.cern/news/news/physics/century-quantum-mechanics
23•bookofjoe•3d ago•7 comments

The underground cathedral protecting Tokyo from floods (2018)

https://www.bbc.com/future/article/20181129-the-underground-cathedral-protecting-tokyo-from-floods
102•barry-cotter•3d ago•30 comments

APKLab: Android Reverse-Engineering Workbench for VS Code

https://github.com/APKLab/APKLab
96•nateb2022•10h ago•5 comments

How does a screen work?

https://www.makingsoftware.com/chapters/how-a-screen-works
403•chkhd•17h ago•81 comments

Black hole merger challenges our understanding of black hole formation

https://gizmodo.com/astronomers-detect-a-black-hole-merger-thats-so-massive-it-shouldnt-exist-2000628197
43•Bluestein•6h ago•38 comments

A technical look at Iran's internet shutdowns

https://zola.ink/blog/posts/a-technical-look-at-irans-internet-shutdown
161•znano•14h ago•65 comments

Myanmar’s proliferating scam centers

https://asia.nikkei.com/static/vdata/infographics/myanmar-scam-centers/
60•WaitWaitWha•3h ago•9 comments

The North Korean fake IT worker problem is ubiquitous

https://www.theregister.com/2025/07/13/fake_it_worker_problem/
265•rntn•19h ago•278 comments

Hypercapitalism and the AI talent wars

https://blog.johnluttig.com/p/hypercapitalism-and-the-ai-talent
79•walterbell•11h ago•25 comments

Show HN: FFmpeg in plain English – LLM-assisted FFmpeg in the browser

https://vidmix.app/ffmpeg-in-plain-english/
82•bjano•3d ago•17 comments

The Scourge of Arial (2001)

https://www.marksimonson.com/notebook/view/the-scourge-of-arial/
28•andsoitis•6h ago•15 comments

Binding Application in Idris

https://andrevidela.com/blog/2025/binding-application/
3•matt_d•3d ago•0 comments

Burning a Magnesium NeXT Cube (1993)

https://simson.net/ref/1993/cubefire.html
28•leoapagano•3d ago•4 comments

James Webb, Hubble space telescopes face reduction in operations

https://www.astronomy.com/science/james-webb-hubble-space-telescopes-face-reduction-in-operations-over-funding-shortfalls/
73•geox•5h ago•43 comments

GLP-1s Are Breaking Life Insurance

https://www.glp1digest.com/p/how-glp-1s-are-breaking-life-insurance
303•alexslobodnik•12h ago•347 comments

Show HN: A Raycast-compatible launcher for Linux

https://github.com/ByteAtATime/raycast-linux
161•ByteAtATime•14h ago•43 comments

The upcoming GPT-3 moment for RL

https://www.mechanize.work/blog/the-upcoming-gpt-3-moment-for-rl/
195•jxmorris12•4d ago•80 comments

Five companies now control over 90% of the restaurant food delivery market

https://marketsaintefficient.substack.com/p/five-companies-now-control-over-90
211•goinggetthem•11h ago•209 comments

C3 solved memory lifetimes with scopes

https://c3-lang.org/blog/forget-borrow-checkers-c3-solved-memory-lifetimes-with-scopes/
107•lerno•2d ago•77 comments

Show HN: Learn LLMs LeetCode Style

https://github.com/Exorust/TorchLeet
147•Exorust•18h ago•18 comments

How to scale RL to 10^26 FLOPs

https://blog.jxmo.io/p/how-to-scale-rl-to-1026-flops
69•jxmorris12•3d ago•4 comments

Fine dining restaurants researching guests to make their dinner unforgettable

https://www.sfgate.com/food/article/data-deep-dives-bay-area-fine-dining-restaurants-20404434.php
82•borski•16h ago•157 comments

Show HN: ArchGW – An intelligent edge and service proxy for agents

https://github.com/katanemo/archgw/
38•honorable_coder•1d ago•7 comments

Infisical (YC W23) Is Hiring DevRel Engineers

https://www.ycombinator.com/companies/infisical/jobs/qCrLiJb-developer-relations
1•vmatsiiako•14h ago

Monitoring My Homelab, Simply

https://b.tuxes.uk/simple-homelab-monitoring.html
133•Bogdanp•3d ago•47 comments
Open in hackernews

Zig's new I/O: function coloring is inevitable?

https://blog.ivnj.org/post/function-coloring-is-inevitable
54•ivanjermakov•15h ago

Comments

audunw•14h ago
I really don’t agree with the idea that this is functional colouring. Then we have to start talking about function colouring in a whole bunch of new contexts like with Zigs explicit passing of allocator. Or any other parameter that needs to be explicitly passed to use some kind of interface.

I think we should stick to talking about colouring when there is special calling conventions or syntax, which has the consequence of having to write separate libraries/modules for async code and non-async code.

That is the significant problem we have been seeing with many async implementation, and the one which Zig apparently fully solves.

dwattttt•4h ago
> Then we have to start talking about function colouring in a whole bunch of new contexts like with Zigs explicit passing of allocator.

That's pretty much where we are though. If you have a function that isn't passed an allocator, and now it needs to call a function that does take an allocator, we're in the same place.

Rust's 'async' keyword changes the type of the return value, but you can just write the different return value yourself; it's 'coloured' purely by what it means to be returning a 'Future'.

koolala•4h ago
So its impossible to get an allocator through a different means from inside a function? It must be passed in?
dwattttt•4h ago
No, it's entirely possible. And that's why we don't think about "has an allocator" as a colouring problem.

Likewise if JavaScript had an easy way to get a handle to its Runtime, and a function "block on promise" in its early days, we'd have never had all these "colouring" arguments.

woodruffw•4h ago
This is effectively a special calling convention: Zig expects you to pass in a "token" object that communicates a kind of effect (I/O in this case). No token, no effect (modulo a soundness hole).

This is not a new pattern, and I think it's a pretty good one (and is arguably more ergonomic and general than syntax-level effects). But it's quintessential function coloring.

throwawaymaths•3h ago
> Zig expects you to pass

It does no such thing. you could pass a function a vtable and the vtable could have one implementation that calls an io stashed in the parent of the vtable, and a different vtable that doesnt and the function calling the vtable would be none the wiser. what is the color of the function that took the vtable?

this is not just academic; it would be for example the basis for mocked integration tests on a database or over the net api call.

woodruffw•3h ago
That's a calling convention, with indirection. You need some kind of capability token for this kind of asynchronicity scheme; it doesn't matter how you get it, but it needs to be there.

To be clear, there's nothing wrong with this; it's just another way to encode capabilities/effects.

> what is the color of the function that took the vtable?

It has the I/O effect.

hamandcheese•3h ago
> which has the consequence of having to write separate libraries/modules for async code and non-async code.

That is not a consequence of function coloring or syntax, it is a consequence of having multiple ways of performing IO.

camgunz•9h ago
Look, either you move the program counter to a different place in memory (function call) or you push a task into an event loop. Even if you somehow elide all these differences, they're so different under the hood you'll always have to know in some circumstances. It's honestly wild we conflate them at all.
kristoff_it•9h ago
If you want to go down that route, any function that has, or doesn't have, any given resource is colored then.

   fn foo(db: *Db) !void { ... }
   fn bar() !void { ... }
Would you consider `foo` a blue function and `bar` a red function? That doesn't seem particularly helpful to me.

The virality of async await is that once you mark a function async, then you can only call it from another async function, which forces you to mark more functions async, which in turn means that if you want to use blocking I/O APIs then you just can't because it's incompatible with your execution model because by daring to express asynchronicity of operations, you were forcefully opted into stackless coroutines.

That's what Zig solves, and that's what is real function coloring. People have written reimplementations of the same libraries multiple times because of it.

https://github.com/redis/redis-py https://github.com/jonathanslenders/asyncio-redis

Just as an example. Note also how, coincidentally, this duplication of effort resulted in asyncio-redis being semi-abandoned and looking for maintainers. And you have to have both libraries because the asyncio one can't do blocking, and vice versa the other one can't do async.

Would you write two instances of essentially the same library just because one is missing an argument that gives it access to an `Io` interface? No, because you would just pass that extra argument around and nothing else would have to change.

n42•8h ago
I've been trying to beat this point in and failing. If a parameter type creates "colors", you can extrapolate that to an infinite set of colors in every single language and every single standard library, and the discussion on colors becomes meaningless.

Some people are so focused on categorical thinking that they are missing the forest for the trees.

The colors are a means of describing an observed outcome -- in Node's case, callback hell, in Rust's, 4 different standard libraries. Whatever it may be, the point is not that there are colors, it's the impact on there being colors.

> But there is a catch: with this new I/O approach it is impossible to write to a file without std.Io!

This sentence just makes me laugh, like it's some kind of "gotcha". It is the ENTIRE BASIS of the design!

dwattttt•5h ago
> you can extrapolate that to an infinite set of colors in every single language and every single standard library, and the discussion on colors becomes meaningless.

It's more that discussion about most of them becomes meaningless, because they're trivial. We only care when it's hard to swap between "colours", so e.g. making it easy to call an Io function from a non-Io function "removes" the colouring problem.

hamandcheese•3h ago
> so e.g. making it easy to call an Io function from a non-Io function "removes" the colouring problem.

Exactly. In golang (which is also a cooperatively multithreaded runtime if I understand correctly), calling a function that needs IO does not infect the callers type signature.

In async rust, and in "async param" zig, it does.

naasking•3h ago
Another poster up thread identified the exact problem: async/await contexts are not first-class values, they are second class citizens. If they were values then you could just stick the context in a struct/class and pass that around instead, and avoid having to refactor call chains every time something changes. It's their second class status that forces the "colouring" into the function signature itself at each point. This is also why ordinary first class values do not introduce colours, ie. you can hide new values/parameters inside other types that are already part of the function signature, thus halting the propagation/vitality of the change.

Of course, if these async contexts were first class citizens then you've basically just reinvented delimited continuations, and that introduces complications that compiler writers want to avoid, which is why async/await are second citizens.

vips7L•2h ago
Go is preemptive. Async/await is cooperative because you’re explicitly cooperating and yield.
woodruffw•6h ago
> Would you consider `foo` a blue function and `bar` a red function? That doesn't seem particularly helpful to me.

In the sense of effect/capability typing, I think the answer is yes.

"Coloring" isn't magical, it's just a way to describe effects. Those effect can be described by keywords (`async` in JS, `throws` in Java, etc.) or special token parameters/types (what Zig does), but the consequences are the same: the effect propagates to the caller, and the caller becomes responsible for dealing with it.

nextaccountic•4h ago
Yeah, parameter passing can be seen as some kind of effect (like the Reader monad in Haskell). Passing parameters down the call stack is viral just like function coloring (if you need to do i/o and thus need to receive an io parameter, then your caller must receive an io parameter too, recursively; this is analogous to adding a keyword async in front of your function, and to its callers recursively). The solution is probably some sort of implicit parameter, again, like the Reader monad.

Note: async fn in Rust is also just a fn (in Rust's case, a fn that returns a future). It turns out that returning a future, or receiving as parameter a reference to the runtime, are equivalent in some sense

koiueo•3h ago
> Passing parameters down the call stack is viral

It's in a different league comparing to async-await abomination. For one, you can store parameter on a struct thus working around the "virality" on a call site.

0x457•3h ago
Huh?

You have the following call stack (top to bottom): a -> b -> c -> d

Function "d" does IO, so a, b and c need to pass that IO down. It's the same as with async in terms of virality.

If I understood correctly, the main benefit here is that you don't have to dance around "can I call this function or is it going to block async runtime reactor?"

I would pick async/await style over this because (I think) extra function argument is higher visual load than "async fn".

koiueo•2h ago

  const Greeter = struct {
      io: std.Io,

      pub fn greet(self: Greeter, msg: []const u8) !void {
          var stdout_writer = self.io.stdout.writer();
          try stdout_writer.writeAll(msg);
      }
  }

  Greeter.greet("Look ma, no coloring")
woodruffw•1h ago
`greet` has Io within its closure, so I’m pretty sure this is consistent with the GP’s point.
tcfhgj•6h ago
> The virality of async await is that once you mark a function async, then you can only call it from another async function

Rust calling async function in non-async function:

    ...
    // Create the runtime
    let rt  = Runtime::new().unwrap();
    
    // Get a handle from this runtime
    let handle = rt.handle();

    // Execute the future, blocking the current thread until completion
    handle.block_on(async {
        println!("hello");
    });
https://docs.rs/tokio/latest/tokio/runtime/struct.Handle.htm...
vlovich123•6h ago
Of course, spinning up a new runtime within the context of a boundary like that is probably wasteful (lots of new threads created if you’re not careful). But you could stash that runtime behind a OnceLock (you’d need to block_on the Handle I imagine rather than the Runtime directly, but doable).

And calling blocking from non-blocking:

    let result = tokio::task::spawn_blocking(|| {
       5
    }).await;
This of course is basically essentially what Zig is doing, except instead of hidden global state it’s parameter passed. This is one area Zig does do better in - I wish Rust would default more to instance state instead of implicit global state.
rk06•3h ago
Well said. Honestly I don't understand this "function coloring argument" at all in zig's context.

Function is the smallest unit of logic. And function parameter is the fundamental way to control it.so, in theory, __A function parameter is the smallest possible design choice you have to control async vs sync__

There is no way to reduce it further. As you need to encode this somehow, otherwise it will be implicit and very hard to debug.

functions can compose. Function parameters can be composed. Making this a solid design choice.

Zig has somehow achieved this feat of decomposing async/sync to a single parameter. This deserves an ovation Other langs should take note.

metaltyphoon•49m ago
> in theory, __A function parameter is the smallest possible design choice you have to control async vs sync__

So we are just going to forget Go exists?

alex_hirner•3h ago
> The virality of async await is that once you mark a function async, then you can only call it from another async function

That's not exactly true. Many languages return a curried version of it, which can be executed once you have a runtime.

orphea•9h ago
Related discussion (Zig's New Async I/O): https://news.ycombinator.com/item?id=44545949
AYBABTME•7h ago
One way or another, I like how this is implemented. Explicitely passing dependencies like this, with a tight syntax, makes things easy to understand and write.

I haven't written any Zig but these demonstrations give me strong vibes of how I felt when I picked up Go more than 10y ago.

ezst•1h ago
I mean, isn't it how it's always been, up until JS/python "single threaded" runtimes became what most people had ever encountered?
dwattttt•6h ago
Function colouring created a lot of angst when it first came about, particularly because of the difficulties of calling a function of one colour from another. Whether that was possible, what it actually meant, wasn't really well defined.

As other comments have said, there's nothing special about "colouring"; sync/async functions are a case where those above problems are tough, but simpler versions of the problem are everywhere and we don't freak out about them e.g. call a fallible function from an infallible function.

It really all turns on how easy it is to ultimately make the call to the other "function" colour. In Zig's case, if its easy to get an Io in a function that didn't take an Io, it's a non-issue. Likewise for the "fallible function call from infallible function": if it fails, do something that doesn't result in the infallible function failing (do something else? Terminate? Anything will do).

andyferris•6h ago
I am actually really excited about this.

The issues I've had with function colouring had to do with trying to compose code using (or expecting) blocking effects with those using async effects in NodeJS - if one library has a higher-order function that expects a non-async function and you have functionality which is provided to you as async, it can be very difficult to plumb them together! And if it's the other way around, it can be quite the performance killer (think how much faster better-sqlite3 is than alternatives). Zig's approach eliminates this problem, AFAICT.

If I had to choose between having to pass through an effect handler like `io` or write `async` everywere, the former seems like a better use of my time. It's explicit, but that can be good.

It also fits Zig well with the allocator. Code can expect an allocator or perhaps an allocator and `io`, or perhaps neither. It's analogous to Rust code that is core vs alloc/nostd vs std.

I am slightly amused that a "C-but-better" language is going to have an `io` passed through non-pure functions much like Haskell. It's that idea combined with Rust's pluggable async runtimes (and stackless concurrency) combined with Roc's "platforms" - but for systems programmers. Quite amazing.

et1337•6h ago
I think this is a good kind of function coloring. It would avoid some scars I have from:

- seemingly harmless functions that unexpectedly end up writing four different files to disk.

- Packages that do I/O or start threads when you simply import them.

hiccuphippo•5h ago
I don't care about the color of the function. What matters is if you'll have to write two versions of the function, and this seems to solve that.
koiueo•3h ago
If we apply your logic, then every mainstream language has the coloring problem with not just two, but a multitude of colors.

  // OMG we can't call this without passing the service
  // This function is people-colored
  public Person findPersonByName(PeopleService service, String name) {
    // OMG we can't find without the service
    service.find(name)
  }


EDIT: formatting
vips7L•2h ago
This is off topic. But I really hate “services”. They always are just some random collection of functions and aren’t a real object at all.
koiueo•2h ago
I think I know what you are talking about. In a typical three-tier enterprise application there's no clear separation of concerns between "services" and DAO/Repo... And this is due to how most persistence libraries are designed: they eagerly execute side-effects, this breaks composability due to poor transaction control, so you end up leaking a lot of your business logic into your supposedly persistence layer.

Take a look at Scala's doobie[1]. Any doobie operation returns a `ConnectionIO`, which is only a description of an operation (free monad). With a proper doobie usage the DAO layer is an algebra of possible persistence-related operations, and the service layer implements business logic by combining primitive ConnectionIOs and interpreting them with full control of transaction boundaries.

[1] https://typelevel.org/doobie/index.html

vips7L•1h ago
I’m sorry but I just don’t enjoy functional Scala.
koiueo•1h ago
Paraphrasing someone else: then keep enjoying the disfunctional one :-P
vips7L•1h ago
Haha you got a good chuckle out of me on that one.
jmull•3h ago
With Zig I/O you can call i/o functions from non-i/o functions and non-i/o functions from i/o functions.

In the analogy of “What color is your function”, you can call blue functions from red functions and red functions from blue functions.

The pernicious viral nature of function coloring doesn’t apply.

Surac•52m ago
i never got warm with this async/await style of calling things. i much more prefer using threads/fibers/protothreads instead. Sure you have to be more expicit on creating and controlling these and also passing around data may get more complex, but at least they do not gloss over the underlying problems async and await tries to cover up
SkiFire13•49m ago
I believe Zig's new I/O is neither colored nor not colored, instead the design is orthogonal to that. You won't be able to make code magically async by just swapping the implementation of Io, instead you'll need some kind of runtime that allows functions to wait without blocking OS threads. Depending on how this is implemented (if it's possible at all) you'll have colored functions or not.