Ian Henry

RSS: https://ianthehenry.com/feed.xml
Ian Henry 的博客,关于编程语言、编译器与函数式编程的技术写作。

键盘乐器创新:Keyboardion 的不对称调音设计

我有另一个 一个乐器的构想,我觉得效果还不错。 它有点像半音阶按钮手风琴 以及一个键盘吉他.或者是数字版查普曼·斯蒂克 …只是它更偏复音,调音也完全不同。 我不知道。我觉得这算是个新现象。 半音阶按钮手风琴可能是最古老且最受欢迎的同构键盘 世界上的乐器,所以它不是那这其实是件新鲜事。但据我所知,键盘是第一个调整调音以适应这种特定形态的乐器。1 我知道的所有数字同构键盘都有更方形的宽高比,2 而且...
评论点赞收藏20 天前

为什么要学 Janet?

Ian Henry 写了一整本免费的 Janet 编程语言电子书,然后还要写这篇文章说服你入坑。这不是枯燥技术文档,而是有温度的个人安利:Janet 核心只有 8 条指令,一个下午就能上手;编译后原生二进制仅 784KB,无需安装运行时就能直接分发;用解析表达式文法(PEG)替代正则表达式,能解析 HTML、JSON、甚至二进制格式;还有优雅的子进程 DSL,可以替代 Bash 完成大量脚本任务。作者逐一拆解了宏系统、编译期到运行时的值传递机制、可变与不可变集合等特色,并坦言「Janet 握在手里手感很好」—— 主观但真诚。有代码示例,有踩坑记录,有和其他语言的对比判断,不是 ChatGPT 拼贴也不是 SEO 搬运。适合对编程语言设计、脚本工具链、Lisp 方言感兴趣的读者,读完很可能会想打开 REPL 试试。
评论点赞收藏75 天前

德劳内三角剖分可视化(2022)

一篇罕见的兼具深度与人味的技术文章。作者用交互式动画一步步拆解德劳内三角剖分——从"最大化最小角"的直观定义,到抛物面映射解释复杂的圆内点测试矩阵行列式,再到增量算法的完整实现与边界情况处理。更难得的是,整篇文章充满了个人经验、踩坑记录和诙谐叙事(作者做这个的动机竟是为了做一个"可以砸碎的订阅按钮")。没有学院派的枯燥,没有营销号的浮夸,只有认真写代码的人才会有的那种"我终于搞懂了,现在手把手告诉你"的真诚。适合任何想真正理解这个算法而非仅停留在概念层面的读者。
评论点赞收藏207 天前

周期空间:用周期函数重做 SDF 域重复

我最喜欢的SDF技术之一,就是“域重复”: 这是一项极佳的派对小技巧,能够让你实时渲染无限多的几何形状,并且还能呈现出柔和的阴影、 环境遮挡,以及SDF所具备的种种精美效果。 当我第一次看到这项技术时,简直觉得像魔法一样——而如今,它依然让我感到神奇——只不过是以一种截然不同的方式。 之所以能做到这一点,关键在于:你并不是在“评估无限多的几何形状”。每当一束光线穿过场景时,它只会一次只评估一个...
评论点赞收藏259 天前

泛化沃利噪声

沃利噪声是一种在计算机图形学中用于程序化纹理的噪声类型。在其最基础的形式下,它看起来是这样的: 虽然效果难看又枯燥,但这种方式却能快速直观地展示出该效果的最终呈现效果。如果我们利用沃利噪声来扭曲一个三维形状,就能得到类似锤纹或坑洞状的纹理: 与许多程序化纹理一样,如果将这一效果重复多次、并采用不同的频率进行渲染,其视觉效果会更加出色: 这些渲染结果中存在一些视觉伪影,因为它们使用的是对沃利噪...
评论点赞收藏263 天前

用Datalog来调酒:一个家庭调酒师的逻辑编程实验

一篇极其罕见的「个人项目 + 技术叙事 + 生活实用」三位一体好文。作者 Ian Henry 在家调酒时遇到真问题:冰箱里一堆零散基酒和利口酒,面对海量调酒配方,该买什么才能用最少花费解锁最多新鸡尾酒?他没有写两行 Python 交差,而是借机学了 Datalog(一种逻辑编程语言),写了一个叫 Mixologician 的小程序。文章最可贵的地方在于:他完整呈现了从「想当然地写规则」到「被 Soufflé 编译器报错、反复试错、最终写出优雅递归关系」的全过程。他坦诚自己花了几个小时才搞定一条规则,把 Lime → Lime Juice → Lime Cordial 这类食材衍生链用 Begets 和 Composite 关系优雅建模。整篇文章语言幽默、有真人对话感(自问自答段落贯穿全文),代码全公开在 GitHub。不是教程,胜似教程;不是故事,却处处是故事。对于对逻辑编程、领域 DSL、工具思维或调酒感兴趣的读者,这篇文章既有启发又有实操价值。
评论点赞收藏317 天前

构建 Bauble:一个用数学函数雕琢3D图形的个人编程项目

一位资深程序员以第一人称讲述从零构建 Bauble——一个基于 SDF(有符号距离函数)的浏览器端 3D 创作工具——的完整故事。核心看点不是工具本身,而是个人项目从"兴奋原型"到"代码崩塌"再到"两年后彻底重写"的真实心路。作者用 Janet 语言嵌入 WebAssembly,设计了一套函数式 DSL 来自动生成 GLSL 着色器,早期靠字符串拼接实现,最终因无法维护而全部推倒重来;两年后用工程化方法构建了 GLSL AST、类型系统、测试套件和完备的交互式文档。全文充满具体的技术踩坑(矩阵列主序、WebGL 跨浏览器差异、Marching Cubes 精度问题)、真实困惑(为什么第一次不写测试)、审美判断(颜色校正、交互体验)和个人表达,是一篇兼具编程硬核深度与人性温度的个人技术叙事,能激发读者讨论欲和动手尝试的冲动。
评论点赞收藏583 天前

Janet 凡人指南(2023)

一位独立开发者用 20 周业余时间写了本免费的编程书《Janet for Mortals》,并坦诚这篇博文就是借机推广的"垫场文"。但他详细记录了写书之外的大量周边工程:为书籍网站内置交互式 REPL(支持按 Escape 调出、自动补全、一键运行),给 Janet 语言写命令行参数解析库 cmd(受 OCaml Core.Command 启发),重写快照测试框架 Judge,构建交互式海龟画图 playground ——这些 side project 占去了写书一半的时间。文章不回避真实数据:HN 首页一日带来 3 万访客,真正读完 5 个章节以上的仅 387 人;内置 REPL 的 report 功能收到近 500 条反馈。全文坦诚自嘲,充满一手工程判断和取舍思考——比如为什么不用 Janet 写后端(安全性不足)、为什么为 logo 花一天建模乌龟(伴侣说没有乌龟的海龟画图是"辜负")。适合对技术写作、独立开发、编程语言生态感兴趣的读者。
评论点赞收藏627 天前

如何学习 Nix

一篇带有强烈个人风格的 Nix 学习指南索引页——作者 Ian Henry 以自己的真实学习历程为主线,从零开始构建了一份涵盖 Nix 包管理、表达式语言、derivation、交叉编译、flakes 等主题的系列教程。章节标题充满自嘲和幽默("好吧,这才是我的第一个 derivation"、"更多的 flakes,不幸的是"、"我读了手册,嗯"),记录了大量一手踩坑经验:从 Homebrew 迁移到 Nix、第一次写 bug、第一次升级包、配置声明式用户环境等。这不是官方文档的复述,而是一个有真实困惑、有失败经历、有动手过程的学习者笔记。虽然页面本身是索引而非正文,但整体结构完整、覆盖面广,且持续维护到 2024 年,对想认真学 Nix 的开发者而言是一个信息密度高、有温度的入口。
评论点赞收藏688 天前

一种与众不同的键盘:Peggi琶音键盘制作手记

一位独立开发者用Faunchpad自制的八键琶音键盘Peggi——贴在手机背面,通过手指顺序滚动按键输入文字,而非同时按压和弦。作者详细分享了设计理念、键位手工布局(把最常用字母放在最顺手的滚动方向上)、与和弦键盘的优劣对比(和弦只需同时按,琶音需顺序按但容错性更好),以及人体工学上的真实翻车(竖屏根本无法使用,横屏拇指操作也很别扭)。最精彩的是前面大谈理论预期可达50wpm,最后实测坦诚"能到10wpm就谢天谢地了"。文风幽默自嘲,信息密度高,有完整踩坑记录和开源固件链接,对替代输入设备或键盘DIY感兴趣的读者非常有启发。
评论点赞收藏731 天前

深入理解宏中的 quote-unquote:编译时值传递与运行时引用

作者以个人学习历程中的"顿悟"为线索,揭示了 Lisp(Janet)中 quote 的真实语义——它并不是"返回参数的抽象语法树",而是"直接透传解析器生成的值"。这意味着你可以在宏展开时分配可变对象(如哈希表),并通过 quote-unquote 模式将同一对象的引用嵌入运行时代码的每一处调用点,实现普通函数做不到的效果:每个宏调用点拥有独占的缓存状态。文章从 Python 装饰器/JavaScript 高阶函数讲起,对比纯语法变换宏的局限,逐步深入 Janet 的具体实现,并展示了这一技巧在 Bauble 编译器重构和 Judge 内联快照测试框架中的实际应用。适合对元编程、Lisp 系语言或编译器实现感兴趣的读者,有清晰代码示例和扎实的底层理解。
评论点赞收藏734 天前

制作并定制一把Kyria无线人体工学键盘

一位从未焊过电路板的开发者,亲手打造了一把完全无线、且能用相机三脚架配件自由调节角度和倾斜度的人体工学键盘。文章详细记录了Kyria套件的组装全过程,包括蓝牙左右分体方案、底壳1/4-20螺纹孔配合云台实现任意"帐篷角"、强磁吸附金属桌面等巧妙设计。作者坦诚分享了初次焊接的踩坑经验与省力技巧,并强调"通孔焊接其实很简单"来打消新手顾虑。这不是一篇泛泛的DIY教程,而是一份充满实物照片和真实手感反馈的建造日记,对想入门客制化键盘或寻找办公舒适方案的人有直接参考价值。
评论点赞收藏747 天前

函数命名空间与 Lisp 宏的问题

一位自称非 Lisp 专家的程序员,在写游戏时被迫写测试框架、从而被迫深入理解宏,结果意外颠覆了对 Lisp 宏的全部认知。他原以为宏只是"把代码转换成代码"的语法变换,但在 Janet 语言中写 do-texture 宏时发现,宏展开时函数名是在调用处而非定义处查找,导致命名空间污染——而解决方案竟然简单到直接在宏里 unquote 函数对象本身。这让他意识到宏不止是语法转换,还涉及编译时值捕获这一至今未被主流教科书充分讨论的机制。他翻出《On Lisp》和《Let Over Lambda》,发现 Paul Graham 对函数捕获的建议只是"放个独立包名",Doug Hoyte 则把 Lisp-2 的独立函数命名空间当成宏构造的护身符。作者质疑:Lisp-2 从来不是解决宏作用域问题的设计,它只是早期硬件的性能 hack,让社区长期回避了真正的问题。文章充满个人探索的鲜活感——不装懂、不背书,边写代码边推翻自己的偏见,是那种能让人读完就想打开 REPL 试一试的技术写作。
评论点赞收藏782 天前

从零开始配置 tmux

从清空所有默认按键绑定开始教你配置 tmux——作者 Ian Henry 分享了一套"从零开始"的 tmux 配置哲学:先 unbind-key -a 解除所有默认绑定,再按需添加自己真正需要的功能。文章覆盖了自定义 prefix 键、配置复制模式(含 vi 风格操作、系统剪贴板集成)、鼠标支持等完整流程,并解释了每个设置背后的真实原因和踩坑经验,比如 escape-time 设为 1 而不是 0 的来由、set-clipboard 的终端兼容性问题、copy-pipe 跨 macOS/Linux 的差异处理等。这不是文档搬运,而是一位长期用户经过思考后的配置实践,充满个人观点("C-b 是键盘上最难按到的键之一")和实用细节。适合想真正理解 tmux 配置原理而非照抄他人配置的读者。
评论点赞收藏812 天前

学习 Nix 第 49 篇:nix-direnv 大幅提升开发体验

nix-direnv 是 Nix 生态中被低估的工具。作者两年实战总结:nix-shell 两大痛点——每次 GC 要重下依赖、强制 bash 交互 shell。自己写 wrapper 解决前者费尽周折,后者一直没搞好。nix-direnv 同时解决:不启动新 shell,在当前 shell 注入环境变量;自动注册 GC root;仅 shell.nix 变化时重评估,典型场景零启动延迟(原生 nix-shell 400ms,作者包装要 750ms)。shell.nix 改动后环境自动更新,无需反复开关 shell。附完整配置步骤和 zsh 隐藏冗余输出的 hack。有真实踩坑、有具体数据、有可用方案,适合所有受 nix-shell 折磨的 Nix 用户。
评论点赞收藏931 天前

学习 Nix 第 48 篇:在 macOS 上安装(单用户模式)Nix

一篇极具个人风格的真实技术踩坑记录。作者以"斯德哥尔摩综合征"自嘲与 Nix 的 18 个月纠缠:觉得它毛病一堆但比 Homebrew 强,咬牙坚持。核心问题:macOS 上 Nix 官方已移除单用户安装选项,强制多用户模式(需跑 root 守护进程、建一堆构建用户),且每次 macOS 升级都会崩。作者受不了多用户安装,自己黑了一套非官方单用户方案,跑了一年半毫无问题。文章详细解释了两者区别、多用户安装的弊端(升级必崩、改系统配置)、以及如何绕过限制完成单用户安装。文末反思多用户也有沙箱优势,但认为不值得增加复杂度。强烈的个人立场、真实困惑和动手记录,不是通稿也不是教程复读机。
评论点赞收藏933 天前

斐波那契矩阵

一篇以强烈个人风格重新审视斐波那契数列的深度博客。作者从"矩阵即状态机"的视角切入,用线性代数的特征分解(eigendecomposition)工具,展示如何用矩阵乘法和特征向量在 log(n) 甚至"常数时间"内计算斐波那契数——然后诚实指出浮点误差使这一方法在实践中不可行。全文贯穿个人观察(为何讨厌用递归教编程)、互动可视化、对黄金比例的直觉解释,以及脚注里的冷知识(如斐波那契数可用于英里/公里换算)。不是教科书翻版,而是一个人带着好奇和幽默分享他真正觉得酷的东西。
评论点赞收藏1113 天前

我心目中的 REPL

一位程序员分享他过去六年几乎唯一的测试方法——让源文件变成持久化 REPL:你在编辑器里写表达式,按快捷键,运行结果直接回写到文件里,这些记录下来的会话自动成为活着的测试用例。这种"读取-求值-修补"循环(read-eval-patch loop)彻底改变了他的编程工作流。核心洞见:当写测试的摩擦足够低时,你自然会写得更多;当测试立刻就有用(而不仅是留给未来的自己),你自然会写出更好的代码。作者在 Janet、OCaml、Rust 中实际使用,JavaScript 的 Jest 也支持类似的内联快照测试。这不是哲学说教,而是一种可复用的机械式工作流改进。
评论点赞收藏1138 天前

广义宏:一种可以重写程序任意形式的宏系统

一位独立程序员在Janet语言中实验了一种全新宏系统构想:让宏不仅能改写自身,还能改写整个程序中的任意语法形式。这种"广义宏"可以出现在表达式任何位置、能感知左右两侧代码、并能返回匿名一级宏实现递归展开。从更简洁的defer/def语法到中缀运算符、泛型函数应用到if/else改写,文章展示了多个有实用潜力的用例,同时坦率讨论了REPL兼容性问题、宏组合失效和可读性灾难三大现实缺陷。附有可运行的原型实现代码。文笔幽默,有鲜明个人立场和一手实践经验,是真正的设计探索与思想实验,而非泛泛的趋势介绍。
评论点赞收藏1216 天前

登录芦苇

登录后关注作者、收藏内容和参与讨论。