惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
aimingoo的专栏
aimingoo的专栏
F
Fortinet All Blogs
Blog — PlanetScale
Blog — PlanetScale
GbyAI
GbyAI
MongoDB | Blog
MongoDB | Blog
月光博客
月光博客
The Cloudflare Blog
量子位
T
Tailwind CSS Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
MyScale Blog
MyScale Blog
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
G
Google Developers Blog
D
DataBreaches.Net
V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
U
Unit 42
博客园 - 聂微东
有赞技术团队
有赞技术团队
A
About on SuperTechFans

Hacker News: Front Page

SPICE simulation → oscilloscope → verification with Claude Code — Lucas Gerads Introducing Claude Opus 4.7 Qwen Studio The Future of Everything is Lies, I Guess: Where Do We Go From Here? GitHub - SeanFDZ/macmind: Single-layer transformer in HyperTalk for the classic Macintosh Show HN: Agent-cache – Multi-tier LLM/tool/session caching for Valkey and Redis Ancient DNA reveals pervasive directional selection across West Eurasia [pdf] AI cybersecurity is not proof of work Moving a large-scale metrics pipeline from StatsD to OpenTelemetry / Prometheus GitHub - Nightmare-Eclipse/RedSun: The Red Sun vulnerability repository GitHub - SethPyle376/hiraeth: Local AWS emulator focused on fast integration testing, with SQS support, SQLite-backed state, and a debug-friendly web UI. A Better Ludum Dare; Or, How to Ruin a Legacy GitHub - macOS26/Agent: Any AI, replaces Claude Code, Cursor, OpenClaw. Over 18 LLM providers (Claude, OpenAI, Gemini, Ollama, Zai, HF, Qwen) wired into a native Mac app that writes code, builds Xcode projects, bumps versions, manages git, automates Safari, use AppleScript, JS or Accessibility, extend Agent! w/ MCP Servers, run tasks from your iPhone via Messages. YouTube now lets you turn off Shorts I Made a Terminal Pager Burgers | マクドナルド公式 Commands — HackerNews CLI documentation ChatGPT for Excel PiCore - Raspberry Pi Port of Tiny Core Linux Live Nation illegally monopolized ticketing market, jury finds Google Broke Its Promise to Me. Now ICE Has My Data. Founding Engineer at Adaptional | Y Combinator CRISPR takes important step toward silencing Down syndrome’s extra chromosome GitHub - saffron-health/libretto: The AI toolkit for building reliable browser automations US v. Heppner (S.D.N.Y. 2026) no attorney-client privilege for AI chats [pdf] Unexpected €54k billing spike in 13 hours: Firebase browser key without API restrictions used for Gemini requests Fragments: April 14 Cal.com Goes Closed Source: Why AI Security Is Forcing Our Decision | Cal.com - Scheduling Software for Online Bookings Laravel raised money and now injects ads directly into your agent Codex Hacked a Samsung TV
Functional Programmers need to take a look at Zig.
2026-04-30 · via Hacker News: Front Page

I’ve been tinkering around with Zig to explore what’s possible with comptime. Whenever I evaluate a new language I use three axes:

  1. How well can I express my ideas in this language. Or in other words, how easy is it for me to express the domain of the program. This is a test on how much noise is applied to the ideas I want to express in the program. Noise is anything that must be written for the program to function that is not relevant to the domain. For example, the canonical example of noise is the need to do manual memory management. We must allocate memory for the program to run, but this is orthogonal to the program’s domain; its an implementation detail.
  2. What facilities does the language provide me to create correct-by-construction systems and how easily can I program the type-system. This is essentially a test on how well I can program the language itself or how well I can create a deep embedding.
  3. What is the mean-time to a surprise. In the study of vacuum systems (think outer space) there is a concept called the mean-free path length or just mean-free path. The mean-free path of a vacuum system is the average distance a particle can travel in the system without experiencing a collision, it is essentially a metric of how good the vacuum is. When I apply this concept to programming languages I think of it as “How much code can I write before my implementation differs from my understanding of the system I am implementing”. This is why I frame this metric as a “surprise”; its “how many lines of code can I write until I experience a surprise”. And a surprise is a delta between what I think I’ve implemented and what I’ve actually implemented.

Enter Zig. I’m interested in Zig for a few reasons. First, I suspect that comptime is a simpler and more flexible system to achieve a lot of the type-system programming I’ve seen in the Haskell-verse and I’ve done enough Haskell (over 10 years) that programming the type system is now a hard requirement for me to take any language seriously.

Second, I am desperately trying to avoid writing a functional systems language. This is probably a blog post in its own right but the programming language industry has not grokked the meaning of monads. Monads are not some kind of obscure math-y thing that only the big brains think are necessary. No, instead monads are a fundamental abstract algebraic description of imperative programming as a computational context. They allow a programming language to not have a built-in notion of time (among other things). So if I want an imperative programming language I can implement MonadCont (the continuation monad), if I want a logic programming language I can implement LogicT (a monad that has non-deterministic semantics and backtracking). Not having a built-in notion of time means that my language is de-facto more expressive, allows users to mold the language to their needs, and improves the optimization ceiling compilers for that language can achieve.

So how does this connect with systems programming? Well, I’ve been radicalized. I’ve learned enough performance-oriented programming to be dissatisfied with the common functional languages (Haskell, OCaml, Common Lisp/Clojure, Scheme) because each of these languages are predicated on the existence of garbage collection and heaps. I think we are at the tail end of a large scale experiment with garbage collection. We can now look back on the last 30 years and conclude that garbage collection does communicate immense value by reducing noise, but the tradeoff is that the one ends up with a forest of pointers into the heap and that will always create a performance ceiling for the program and language implementation.

To exacerbate matters, I think there is a cognitive risk to garbage collection. Garbage collection makes it too easy to not think about or care about the underlying machine and runtime system. This has created a generation of developers who never gained or have lost the knowledge of how programs actually execute on a computational machine. Or to use less flowery language, just look at the era of software that garbage collectors have ushered in. Programs are bloated, slow, and wasteful compared to the literal super-computers that are running them. Surely we can do better.

Furthermore, I think the value proposition of garbage collectors has changed. The first garbage collector was innovated in LISP in 1957, but once they gained prominence in 1995 due to Java they proliferated, and for good reason. However, the machines of 2026 are much different than the machines of 1995 (but our languages aren’t ). Since 1995, compute on a CPU has grown something like 10,000 times faster while memory access timing has lagged. That was not the case in 1995. In 1995 these were roughly comparable. So we are in a situation where we are using languages designed for the machines of yesteryear that do not consider the machines of today. As an industry we (largely) have stopped innovating on new languages.

I once saw a talk by Steven Diehl that asked Where the next Programming Language will come from? that beautifully described the sad state of things. His main point is that the incentives for programming language innovation are at best misaligned and at worst non-existent. He states that we can assume there are three groups of people that are capable of innovation: Academics, Industry, and Hobbyists. But academics have no incentive to do the real-world engineering required to make a viable programming language, and any academics who decide to try are committing career suicide. Industry cannot fund any long-term projects (due to its culture of shareholder-value maximization) and are tied into sticky network effects. Hobbyists (generally) don’t have the time nor the economic means to make something real; which takes decades of full time work to accomplish. And so we are stuck with a local maxima.

Okay now back to Zig. I’m bullish on Zig because Zig (and its BDFL Andrew Kelley) are innovating and have the courage to innovate. Here are some innovations. Zig discourages the forest of pointers approach and encourages better manual memory management through Arenas and Allocators. This means that users have much more control over the memory management of their programs. This is just one reason why stuff written in Zig is so damn fast; Zig programs tend to exploit the machines of today better than the machines of yesteryear. Zig 0.16 just released and reworked the IO system to an interface design, here is the example from the release notes:

const std = @import("std");
const Io = std.Io;

pub fn main(init: std.process.Init) !void {
    const gpa = init.gpa;
    const io = init.io;

    const args = try init.minimal.args.toSlice(init.arena.allocator());

    const host_name: Io.net.HostName = try .init(args[1]);

    var http_client: std.http.Client = .{ .allocator = gpa, .io = io };
    defer http_client.deinit();
...
}

You know what I see when I look at this code? I see http_client as existing in a Reader monad that contains an allocator and an IO interface. This is exactly how the IO monad (and for that matter IO#) works in Haskell. The fact that the Zig people came up with this independantly speaks not just to the universal nature of monads (and the algebraic structures of programming languages) but also tells me that they are absolutely on the right track. Kudos to that team! I even mentioned as much on the orange website which set off a great discussion for those that are interested.

My last example is comptime. Recall that I want to be able to create correct-by-construction programs. This means that I need nominal typing. Well a Haskell-like newtype. In Zig is just a singleton struct:

struct PlayerHealth {
  health: u32
}

Nice! Okay what about a sum type. Easy that’s just a union:

  const std = @import("std");

    fn Maybe(comptime T: type) type {
    return union(enum) {
        value: T,
        nothing,

        const Self = @This();

        pub fn just(the_val: T) Self   { return .{ .value = the_val }; }
        pub fn nothing() Self          { return .nothing; }

                        pub fn map(self: Self, comptime B: type, f: fn (T) B) Maybe(B) {
            return switch (self) {
                .value => |v| .{ .value = f(v) },                 .nothing => .nothing,
            };
        }
    };
}

Very nice! What about typeclasses? Again comptime and structs are the way:

    const std = @import("std");

        fn Eq(comptime T: type) type {
                        if (!@hasDecl(T, "eql"))           @compileError(@typeName(T) ++ " must implement eql(T, T) bool");

      return struct {
          pub fn eql(a: T, b: T) bool { return T.eql(a, b); }
          pub fn neq(a: T, b: T) bool { return !T.eql(a, b); }
      };
    }

        const Point = struct {
      x: i32,
      y: i32,

            pub fn eql(a: Point, b: Point) bool {
          return a.x == b.x and a.y == b.y;
      }
  };

    pub fn main() void {
    const EqPoint = Eq(Point);
    const a = Point{ .x = 1, .y = 2 };
    const b = Point{ .x = 1, .y = 2 };
    const c = Point{ .x = 3, .y = 4 };

    std.debug.print("a == c: {}\n", .{EqPoint.eql(a, c)});      std.debug.print("a == b: {}\n", .{EqPoint.eql(a, b)});  }

You’ll notice that this is a but clunky; we have to instantiate a Eq(Point) and then call EqPoint.eql. EqPoint is essentially the typeclass dictionary that Haskell creates behind the scenes, and so in Zig we have to manually pass that dictionary around. The good part is that this comports with Zig’s “no spooky action at a distance” philosophy, typeclass dictionary passing is spooky-action at a distance. But we can make this more ergonomic by just deriving Eq on our Point type:

const std = @import("std");

fn EqClass(comptime T: type) type {
    if (!@hasDecl(T, "eqlImpl"))         @compileError(@typeName(T) ++ " must implement eqlImpl(T, T) bool");

    return struct {
                pub fn eql(a: T, b: T) bool { return T.eqlImpl(a, b); }
        pub fn neq(a: T, b: T) bool { return !T.eqlImpl(a, b); }
    };
}

const Point = struct {
    x: i32,
    y: i32,

        pub fn eqlImpl(a: Point, b: Point) bool {
        return a.x == b.x and a.y == b.y;
    }

        pub const Eq = EqClass(@This());
};

pub fn main() void {
    const a = Point{ .x = 1, .y = 2 };
    const b = Point{ .x = 1, .y = 2 };
    const c = Point{ .x = 3, .y = 4 };

    std.debug.print("a == c: {}\n", .{Point.Eq.eql(a, c)});      std.debug.print("a == b: {}\n", .{Point.Eq.eql(a, b)});      std.debug.print("a != c: {}\n", .{Point.Eq.neq(a, c)});  }

Not bad. Its less ergonomic than Haskell for sure but I think that’s a good thing. In fact, I look at this, squint really hard and see something like an ML module system hiding behind the scenes. I could go on. In fact, in Zig you can use structs to create closures, to curry, and therefore write higher-ordered functions all without a garbage collector (if that interests you check out the standard libraries sort function). But I’ll save that for another post.

Needless to say I’m bullish on Zig. I think Zig is doing so much right. Zig has what I need and want to express my domain and ideas succinctly (this was 1. in my original criteria). Zig’s comptime has very good support for programming the type system and creating correct-by-construction programs. I still have to experiment more with it, but I think it is atleast in the ball park of Haskell and easier to program at that (this was 2.). Finally, Zig’s “no spooky action at a distance” means I have not once been surprised about the semantics in my experimentation. I’m sure there will be edge cases but I can confidentally say that Zig has a greater mean free path length than languages that its often positioned against: Rust, C++ (for sure). I love Haskell and its been my go to language for the last 10-13 years but god damn I see a lot of Zig in my future.