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

推荐订阅源

Cyberwarzone
Cyberwarzone
Google DeepMind News
Google DeepMind News
宝玉的分享
宝玉的分享
博客园_首页
量子位
博客园 - 司徒正美
罗磊的独立博客
腾讯CDC
IT之家
IT之家
S
Schneier on Security
Hugging Face - Blog
Hugging Face - Blog
L
Lohrmann on Cybersecurity
H
Hacker News: Front Page
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
Know Your Adversary
Know Your Adversary
人人都是产品经理
人人都是产品经理
有赞技术团队
有赞技术团队
大猫的无限游戏
大猫的无限游戏
D
Darknet – Hacking Tools, Hacker News & Cyber Security
AWS News Blog
AWS News Blog
Spread Privacy
Spread Privacy
I
InfoQ
T
Threatpost
Simon Willison's Weblog
Simon Willison's Weblog
云风的 BLOG
云风的 BLOG
L
LINUX DO - 热门话题
A
About on SuperTechFans
Blog — PlanetScale
Blog — PlanetScale
Latest news
Latest news
Forbes - Security
Forbes - Security
Security Latest
Security Latest
NISL@THU
NISL@THU
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
The Hacker News
The Hacker News
M
MIT News - Artificial intelligence
S
SegmentFault 最新的问题
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
B
Blog
A
Arctic Wolf
C
Check Point Blog
G
Google Developers Blog
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
The Cloudflare Blog
L
LINUX DO - 最新话题
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Privacy International News Feed
小众软件
小众软件

Hacker News

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 Bonsai 1-bit WebGPU - a Hugging Face Space by webml-community 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. 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] Retrofitting JIT Compilers into C Interpreters IPv6 – Google The Accursèd Alphabetical Clock Cybersecurity Looks Like Proof of Work Now 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 When moving fast, talking is the first thing to break Too much Discussion of the XOR swap trick – Heather Cafe Introduction to Spherical Harmonics for Graphics Programmers The Grand Line Building a Z-Machine in the worst possible language High-Level Rust: Getting 80% of the Benefits with 20% of the Pain GitHub - duguyue100/midnight-captain: Inspired by Midnight Commander, tailored to my taste. How to build a `git diff` driver · Jamie Tanna | Software Engineer Center for Responsible, Decentralized Intelligence at Berkeley The Local Universe’s Expansion Rate Is Clearer Than Ever, but Still Doesn’t Add Up - A new synthesis of astronomical measurements confirms a persistent mismatch that could point to physics beyond current models The air throughout our homes is infused with microplastics. But there are things you can do to breathe less of them The disturbing white paper Red Hat is trying to erase from the internet – OSnews The Future of Everything is Lies, I Guess: Annoyances ‘Abhorrent’: the inside story of the Polymarket gamblers betting millions on war Productive procrastination — Max van IJsselmuiden maps, territory and LMs 447 Terabytes per Square Centimetre at Zero Retention Energy: Non-Volatile Memory at the Atomic Scale on Fluorographane Show HN: Pardonned.com – A searchable database of US Pardons 20 Years on AWS and Never Not My Job The Seasons are Wrong Artemis II crew splashes down near San Diego after historic moon mission We gave an AI a 3 year retail lease in SF and asked it to make a profit | Andon Labs How a dancer with ALS used brainwaves to perform live On filing the corners off my MacBooks Installing every* Firefox extension OpenClaw’s memory is unreliable, and you don’t know when it will break Steve Blank Nowhere Is Safe Chimpanzees in Uganda locked in vicious 'civil war', say researchers watgo - a WebAssembly Toolkit for Go linux/Documentation/process/coding-assistants.rst at master · torvalds/linux GitHub - callumlocke/json-formatter: Makes JSON easy to read. Founding Product Engineer at Bild AI | Y Combinator A compelling title that is cryptic enough to get you to take action on it GitHub - Keychron/Keychron-Keyboards-Hardware-Design: Industrial design files for Keychron keyboards and mice. 100+ models with CAD assets in STEP, DXF, DWG, and PDF. Source-available, with commercial use allowed for original compatible accessories within the license terms. [ANNOUNCE] WireGuardNT v0.11 and WireGuard for Windows v0.6 Released 1D-Chess Helium Is Hard to Replace Cooperative Vectors Introduction | Evolve Keeping a Postgres queue healthy — PlanetScale Our response to the Axios developer tool compromise Do Americans read print books, e-books or audiobooks more? The Zettelkasten Method in Obsidian: A Practical Setup Guide Artemis II Is Competency Porn and We Are Starving For It WeakC4 Flight Viz — Cockpit View A Mexican surveillance giant you’ve never heard of is now watching the U.S. border Surelock: Deadlock-Free Mutexes for Rust RISC-V 101 – what is it and what does it mean for Canonical? | Ubuntu The Problem That Built an Industry How Much Linear Memory Access Is Enough? | Solidean Investigating Split Locks on x86-64 Simplest hash functions Sybilproof reputation mechanisms (2005) [pdf] What is a property? How Complex is my Code? Static code analysis in Kotlin — tools overview Toffoli gates are all you need PGLite evangelism dcmake: a new CMake debugger UI Clojure on Fennel part one: Persistent Data Structures Fragments: April 2 Python Release Python install manager 26.1 The Life and Death of the Book Review - Liberties Introducing Database Traffic Control — PlanetScale Bitcoin miners are losing $19,000 on every BTC produced as difficulty drops 7.8% God sleeps in the minerals Building slogbox Apple Silicon and Virtual Machines: Beating the 2 VM Limit Who was “Not Even Wrong” first? Pokemon Evolution Vs Darwinian Evolution The APL Programming Language Source Code
Why Janet?
ianthehenry. · 2023-04-12 · via Hacker News

I never thought it could happen to me. I mean, parentheses? In this day and age? But for the past couple years, my go-to programming language for fun side projects has been a little Lisp dialect called Janet.

(print "hey janet")

I like Janet so much that I wrote an entire book about it, and put it on The Internet for free, in the hopes of attracting more Janetors to the language.

I think you should read it, but I know that you don’t believe me, so I’m going to try to convince you. Here’s my attempt at a sales pitch: here is why you – you of all people – should give Janet a chance.

Janet is simple

Janet is an imperative language with first-class functions, a single namespace for identifiers, and lexical block scoping. The core of the language is very small, consisting of only eight instructions: do, def, var, set, if, while, break, fn. But thanks to macros, there are lots of high-level wrappers that give you more powerful or convenient control flow.

You can “learn” Janet in an afternoon, because the runtime semantics are extremely familiar: think JavaScript, plus value types, minus all the wats. And the rest of the language is small: the entire standard library fits on one page. It was this ease of getting started that got me hooked in the first place.

Janet is distributable

It’s easy to compile Janet programs into native executables that statically link the Janet runtime. And you can share those programs with other people, without asking them to install Janet first – or your project’s dependencies, or anything else for that matter. You don’t even have to tell them it’s written in Janet!

The way that Janet pulls this off is very elegant: Janet compiles itself to bytecode, and then writes that bytecode into a .c file that also starts up the Janet runtime. Then it compiles that C file with your system’s C compiler. Since Janet is designed to be easy to embed, this makes perfect sense: it is, essentially, embedding itself into a trivial C executable.

A simple Janet “hello world” compiled to a native binary weighs under a megabyte (784K for Janet 1.27.0 on aarch64 macOS, but your mileage may vary). This includes the full Janet runtime, garbage collector, and even the bytecode compiler – so you can write programs that evaluate Janet code at runtime, if you want to.

This makes Janet an excellent choice for writing little command-line apps. Which is especially true when you consider that…

Janet is unrealistically good at parsing text

Instead of regular expressions, Janet’s text wrangling is based around parsing expression grammars. Parsing expression grammars are simpler, more powerful, and more predictable than regular expressions. They aren’t line-oriented, so they can parse multi-line text without a problem. They can also parse HTML, or JSON, or any other non-regular language. They can also parse binary file formats – they have no problems with arbitrary null bytes.

They really are parsers: structured, composable, first-class parsers. And they’re pretty easy to learn!

Janet has the best subprocess DSL of any high-level language

There is a third-party library called sh that provides a shell scripting DSL that allows you to express pipes and redirects directly in Janet. Like this:

($ find . -name *.janet | say)

It’s pretty incredible. It’s such a nice DSL that I dedicated a whole chapter of Janet for Mortals to it – and the things that you can do with it. It elevates Janet from a reasonable alternative to Perl to a reasonable alternative to Bash for a surprisingly large range of programs.

Janet is embeddable

Lua has become the de facto “embedded language,” which is a shame, because… well, this isn’t a post about Lua. You might not care about this very much, but there’s a chance that it’s just because you haven’t tried it yet: being able to write progams that expose scripting interfaces is a pretty fun superpower.

Embedding Janet is very easy: the Janet runtime is a small C library, and all you have to do is link it in and then call regular C functions to manipulate Janet values. You can even embed it into websites, and write static sites with custom programmable DSLs!

Janet has mutable and immutable collections

Janet’s collection types come in mutable and immutable flavors. Immutable collections have value semantics: the immutable vector [1 2] is indistinguishable from (take 2 [1 2 3]), despite the fact that they have different memory addresses. Mutable collections, on the other hand, have reference semantics: the hash table @{:x 1 :y 2} is only equal to itself. Another hash table with the same keys and values is a distinct object.

Not every language has immutable composite values built right into the standard library!

Macros, macros, macros

I think this is the real reason you should learn Janet, but I didn’t want to lead with it because I didn’t want to scare you off.

You can write Janet just fine without ever learning how to write macros. But you should learn how, because writing macros is fun. It feels different than any sort of programming that I’ve done before.

Writing macros requires thinking twice at once: you’re writing code to write code, so you have to keep two threads of execution straight in your mind: the code that is running now, at compile time, manipulating values and abstract syntax trees, and the code that you are manipulating, the application code that you produce, the code that will run in the future.

Janet’s macros are not hygienic, and Janet does not have a separate namespace for functions. But by allowing you to unquote literal functions, Janet makes it possible to write macros that are completely referentially transparent. It’s an incredibly simple and elegant solution to an otherwise very delicate problem. And the fact that it is possible to do this in Janet highlights my next favorite feature…

Janet lets you pass values from compile-time to run-time

This is the most interesting thing about Janet, in my opinion. But it might not sound very interesting at first – really all it means is that any Janet value can be serialized to disk and read back in later.

But this serialization is implicit: when you compile a Janet program, it runs all of the top-level instructions – regular statements, function declarations, whatever – and then, once it’s executed all of the top-level values, Janet writes down a snapshot of your program’s state to disk.

And it’s a full snapshot of your program’s state: shared references are preserved, so mutable values can still be mutated after you “resume” the snapshot. Generators remember exactly what instruction they need to run the next time you resume them. Closures gonna close.

Macros are a special-case of compile-time code execution – manipulating abstract syntax trees to create new functions – but this is a superpower that you can enjoy without any macros at all. Making a game? Reticulate your splines ahead of time! Or embed assets in your final binary by reading files at compile time – you can perform arbitrary side effects!

Janet for Mortals has an example of using this to autogenerate database bindings based on a SQL schema file – a bit of a silly example, but something that would be quite difficult to do in most languages.

Janet feels good in the hand

This is completely subjective, but I love Janet’s syntax. It strikes a perfect balance of simplicity, uniformity, and variety.

It uses pervasive parentheses, but breaks them up with [] for lists and {} for tables.

Mutable literals are always prefixed with @: @"mutable string", {:immutable hash-table}, etc.

Anonymous functions are written (fn [x] (+ 1 x)), but there’s a shorthand notation for lifting any expression into a function with |: |(+ 1 $).

Janet supports “splats” or “spreads” with ;: (+ ;args).

String literals can be written with any number of backticks, and closed with the same number of backticks. Escape sequences like \n don’t apply in backtick-quoted strings, so you can create strings with any contents without ever thinking about how to escape them – all you have to do is wrap them in a sufficient number of backticks.

Rest parameters use & instead of .: (defn foo [first & rest] ...).

Janet doesn’t support reader macros, so the syntax itself is fixed. If you know how to read Janet, you can read all Janet programs. Which is not to say you can make sense of them…

Janet prefers comfort to tradition

Janet does not adhere to the ancient customs. CAR is called first. PROGN is called do. LAMBDA is fn, and SETQ is def. nil is not the empty list; it is its own type, and there are first-class Booleans in the language. It eschews EQ, EQL, EQUAL, and EQUALP. There is nary a linked list in sight.

This isn’t really good or bad, but I thought it was worth calling out: if you saw the parentheses and assumed FORMAT was not far behind, maybe give Janet a second look.