2024-08-03

28 篇热帖

1. "We ran out of columns" (jimmyhmiller.github.io)

文章摘要:"We ran out of columns"

本文作者回顾了其第一份软件工作的经历,描述了一个堪称“最差也是最佳”的遗留代码库,并通过一系列荒诞却真实的例子,揭示了大型遗留系统中数据库、代码和流程的独特生态与内在逻辑。

数据库的“奇观”

  • 列数限制:系统核心的merchants(存储客户信息)表因列数超过SQL Server当时的限制(1024列),不得不创建了拥有500多列的merchants2表来分担数据。
  • ID生成机制:存在一个名为SequenceKey的极简表,仅有一列一行,用于为系统中新建的所有实体生成ID,从而在不同表之间建立了隐式关联。
  • 手动维护的依赖:系统登录依赖一个名为calendar的日历表,此表由手动填充日期;一次日历耗尽导致系统无法登录,后由实习生手动添加了5年数据。
  • 每日重置的数据employees表每天早晨被清空,并从ADP的CSV文件重新导入,此过程会导致系统暂时无法登录,数据后续还需人工同步至总部。

混乱的代码库与工作流

  • 技术栈混杂:主代码库混合使用VB和C#,运行于IIS,依赖Session状态,导致不同访问路径下页面显示内容不同。仓库中还混入了多种带有自定义修改的JavaScript框架。
  • 依赖“硬盘”上的代码:开发者Gilfoyle编写的“船运管理器”应用等代码未提交至版本控制,其个人硬盘以RAID配置长期保留,以应对此类“幽灵应用”的bug报告。
  • 离奇的销售数据修正:销售订单修正的需求从个案演变为常态,最终导致三名实习生全职编写SQL语句进行人工修改,开发应用程序被认为“太困难”。

“美丽混乱”的开发哲学

  • 无规划的演进:代码库缺乏统一设计、API规范或架构审查。开发者无法理清庞大的单体应用,转而在其边缘创建独立、小规模的功能模块,并逐步用新链接替代旧入口,孤立旧代码。
  • 意外获得的解耦:这种看似混乱的方式意外地实现了代码解耦。开发者专注于解决具体问题、最小化影响范围,代码易于替换。例如,开发者Justin通过将商家搜索页的各区块改为独立端点并行加载,将页面加载时间从分钟级降至秒级以下。
  • 直接连接与快速反馈:作者怀念当时没有中间需求层、开发者直接与用户对话、快速获得反馈并解决简单问题的开发模式。这种“美妙而可怕”的代码库体验,在其职业生涯中再未重现。
2. I Made an Extended Version of Vimtutor – Introducing Vimtutor Sequel (github.com)

Vimtutor Sequel 摘要

Vimtutor Sequel 是一个针对 Vim 编辑器的扩展教程项目,旨在为用户提供进阶的 Vim 使用指导,以加深对 Vim 的理解。

主要特性

  • 高级命令与技巧:教程内容涵盖更深入的 Vim 命令和使用技巧。
  • 分步教程:提供结构化的、循序渐进的指导。
  • 交互练习:包含可供用户动手操作的练习部分。

安装方法

该项目提供了多种安装方式,其中最简便的是使用 Homebrew

通过 Homebrew 安装(推荐)

  1. 首次安装
    brew install vimtutor-sequel
    
  2. 检查版本与升级
    • 检查当前版本:vimtutor-sequel --version
    • 升级至最新版本:
      brew update
      brew upgrade vimtutor-sequel
      

不通过 Homebrew 运行(适用于 Windows/Linux 或无 Homebrew 环境)

用户可以通过克隆代码仓库手动运行教程:

  1. 克隆仓库:git clone https://github.com/micahkepe/vimtutor-sequel.git
  2. 进入目录并创建教程副本(可选,用于练习)。
  3. 使用指定配置启动 Vim 加载教程:vim -u vimtutor-sequel.vimrc -U NONE vimtutor-sequel.txt

使用与许可

安装后,直接运行 vimtutor-sequel 命令即可启动教程。该项目基于 MIT 许可证 发布,并提供了 CONTRIBUTING.md 文件说明参与贡献的方式。

3. Fiber optic drone control beats any RF jammer (www.forbes.com)

摘要:

俄罗斯一架被俘获的第一人称视角自杀式无人机采用了一种创新的通信方式:完全放弃无线电,转而通过随飞行释放的光纤线缆与操作员通信。这使其能够免疫所有形式的无线电干扰和探测

事件发现: 2024年3月,乌克兰军事博主“Flash”报告并随后拆解了一架异常俄罗斯无人机。其携带的“神秘蛋”装置被证实是一个光纤线轴,连接着商用光学收发器,线缆长度达10,813米。

技术原理与优势:

  • 核心机制: 无人机飞行时自动释放光纤线缆,通过光信号传输视频和指令。
  • 关键优势: 通信信号无法被无线电频谱探测,从而无法被干扰或欺骗。这在电子战激烈的战场上是巨大优势。
  • 代价: 线轴和收发器增加了额外重量(约几磅),导致无人机载弹量减少。

历史背景: 光纤制导并非新技术。

  • 导弹领域: 美军TOW导弹早期使用铜线制导以避免无线电干扰。1980年代的EFOGM项目更进一步,使用光纤传输视频信号。
  • 无人机领域: 21世纪初,美国国防高级研究计划局曾开发光纤制导的“近距离致命侦察”无人机,该项目部分技术最终应用于**“弹簧刀”300**巡飞弹。

技术现状与影响:

  • 技术可行性: 光纤无人机控制技术已存在,但属于小众领域,商业应用有限。
  • 俄罗斯方案特点: 该无人机似乎并非大型军工产品,而可能由小型团队使用商用部件研制,展示了灵活创新。
  • 全球安全影响: 当前西方国家的大多数反无人机系统依赖无线电干扰。光纤控制无人机的出现对现有反制措施构成了新的严峻挑战,因为传统的电子对抗手段对其无效。

后续发展: 乌克兰方面已注意此威胁。乌克兰无人机研发生产团体Dronarnia已公布其自制的光纤控制FPV无人机视频,目前射程为一公里,并计划延长。这表明相关技术正在扩散。

4. The future of kdb+? (www.timestored.com)

kdb+的未来分析:使用场景、替代技术与发展趋势

一、kdb+的典型使用场景

  • 历史市场数据存储与分析:例如银行机构用于分钟级数据查询、时间序列分析。
  • 本地量化分析:流动性分析、损益计算等。
  • 实时流式计算引擎:流式VWAP、交易成本分析等。
  • 分布式计算:投资组合保证金计算、风险分析等跨数据节点的复杂计算。

二、替代技术对比与各场景前景

  1. 历史数据场景

    • 替代技术:ClickHouse、QuestDB、云数据仓库(BigQuery/Redshift)、市场数据即服务。
    • 关键观点:多数用户无需kdb+的极致速度;竞争产品性能已接近;kdb+难以吸引中型企业(因倾向云原生或低成本方案)。
    • 结论:kdb+或能维持现有客户,但增长受限。
  2. 本地量化分析场景

    • 替代技术:Python生态(DuckDB、Polars、PyKX等)。
    • 关键观点:Python已成为该领域主导;免费开源工具(如DuckDB/Polars)更易普及,避免厂商锁定。
    • 结论:免费、易用的Python工具将胜出,kdb+因高成本、学习曲线陡峭而丧失优势。
  3. 实时流式与分布式计算场景

    • 替代技术:Apache Kafka、Flink、RisingWave等。
    • 关键观点:kdb+在流式与历史数据结合上理论优势突出,但实施复杂、易产生混乱;Kafka已占据主流心智。
    • 结论:kdb+难以成为主流选择。

三、核心挑战与总结

  • 开源竞争压力:kdb+的核心创新(列式存储、内存格式、日志结构等)已被开源项目吸收并标准化(如Parquet/Apache Arrow)。
  • 生态劣势:竞争对手已形成广泛生态联盟(如Snowflake、Databricks支持Parquet),用户可灵活切换工具。
  • 技术停滞风险:kdb+虽性能卓越,但15年来创新有限,开源社区迭代更快。

四、对kdb+的发展建议

  1. 推出免费或低价版本,扩大用户基础。
  2. 聚焦核心数据库产品,减少分散性创新(如AI方向)。
  3. 降低学习门槛,简化语法与架构。
  4. 加强社区与市场推广,否则将面临缓慢衰落。

总结:kdb+仍是强大的技术,但面对标准化、开源化和云原生的趋势,若不加快变革,将在多数场景中被替代方案逐步取代。

5. p5.js (p5js.org)

p5.js 是一个友好的编程与艺术创作工具,是一个免费开源的 JavaScript 库,由一个包容且关怀的社区构建。它欢迎艺术家、设计师、初学者、教育者等各类人群参与。文章通过多个实例展示了 p5.js 的广泛影响力,包括韩国50+人群的编程俱乐部、由 Qianqian Ye 引介的超过600名贡献者的社区沙龙,以及在纽约和内罗毕等地举办的工作坊。p5.js 遵循一项重要原则:除非是为了增强可访问性,否则不会添加新功能。文章还提到了2015年和2019年的贡献者大会,并推荐了一个互动视频,其中包含动画、音频、WebGL、可访问性及参与贡献等主题的入门指南。

6. Lisp with GC in 436 Bytes (justine.lol)

SectorLISP:436字节中的垃圾回收LISP

项目概要 SectorLISP是一个极度精简的LISP语言实现,其完整功能(包括垃圾回收)仅占用436字节,可容纳于一个512字节的软盘引导扇区中。这使得LISP超越了FORTH和BASIC,成为世界上最小的编程语言。该实现仅由223行汇编代码构成,功能强大到足以让用户用40行LISP代码编写出一个LISP解释器。它兼容所有自1981年以来、至少拥有64KB内存的PC型号,并能运行LISP 1.5中包含的证明助手。

核心设计与优化 项目的目标是极致追求文件大小,为此不惜牺牲其他一切。这种理念使其更像一个游戏(如《Universal Paperclips》),而非实用工具。通过回溯优化和极度节俭的无偏方法,团队在i8086汇编实现中又削减了约一百字节,为添加一个40字节的垃圾收集器腾出了空间。

内存模型与数据结构 实现的关键在于对NULL的重新定义。内存被分为两个相邻的栈,从NULL地址向两侧增长:

  • 正地址:用于存储符号(称为“原子”)。通过NULL地址处的NUL终止字符串NIL作为基础。
  • 负地址:用于存储Pair<int>元组(称为cons单元),用于将原子链接成列表等数据结构。空列表()存储在负NULL地址,因此与NIL相等。

垃圾回收(ABC收集器) 系统采用了一个仅需40字节汇编的ABC垃圾收集器。其工作原理是:

  1. 在求值前后保存cons栈的位置(称为A和B)。
  2. 通过递归复制求值结果,进一步减少cons栈指针(新位置称为C)。
  3. 将B与C之间的内存复制到A处。 这种方法能快速、零开销、完美地整理堆碎片,并保证数据结构为无环图。

元循环求值器与内置函数 SectorLISP实现了John McCarthy发现的优雅的元循环求值器(即用LISP编写的LISP解释器)。Apply函数通过递归调用Eval来转换列表的第一个元素为lambda。系统内置了QUOTE, COND, ATOM, CAR, CDR, CONS, EQ等核心原语。

性能与扩展

  • 在4.77MHz的IBM PC上运行元循环求值器内的LISP程序约需10毫秒。
  • 通过将正内存重新定义为哈希表,优化了符号驻留(interning)算法的性能。
  • 项目提供了多个分支:标准版(436字节,仅BIOS)、友好版(509字节,提供错误提示和持久绑定定义)、跨平台.com文件(20KB,可在七种操作系统上运行)以及JavaScript模拟器。
  • 代码可通过C/JavaScript/Thompson Shell多语言方式编写,利用Unicode段落分隔符等技巧实现跨语言注释。

应用与示例 文章展示了用SectorLISP实现的多种功能:

  1. 算术:将数字编码为位列表(如NIL为0,T为1),并实现加法等运算,支持任意精度。
  2. 微积分:实现符号微分,能够对表达式进行求导。
  3. 万能性:展示了用六个内置原语定义整个LISP的可能性,以及用LISP实现图灵机等特定领域语言(DSL)的例子。

历史与意义

  • 项目确认了SectorLISP能在原始IBM PC 5150硬件上运行。
  • 它与自然界最小基因组(Leuconostoc Phage L5,631字节)相比也毫不逊色。
  • 作者认为,追求极简软件有助于我们更深入地理解问题本质,并可能为自然工程等领域(如基于LISP的基因编程工具)提供启示。

构建与运行 项目提供了二进制文件、源码和模拟器。用户可通过QEMU或专门的blinkenlights模拟器运行引导扇区镜像,或直接在浏览器中使用JavaScript模拟器。源码以GAS汇编和C/JS多语言文件形式提供。

7. Tauri 2.0 Release Candidate (v2.tauri.app)

Tauri 2.0 Release Candidate 摘要

版本状态与发布计划

  • Tauri 2.0 的首个候选版本(RC)现已发布,标志着该项目在经历了长期的 Alpha 和 Beta 测试阶段后,已达到稳定状态,预期不会再有破坏性变更。
  • 计划于 8 月底发布 2.0 稳定版,RC 阶段将持续约 4 周,主要用于完善文档和修复关键错误。

关于移动端支持

  • 明确指出 Tauri 2.0 并非实现“移动端一等公民”的最终版本,但强调目前已经可以使用 Tauri 开发生产就绪的移动应用(Android 和 iOS)。
  • 移动端仍需改进,未来将在次要版本中致力于提供跨平台的功能对等性和优化移动开发体验。官方插件仓库中已有移动插件,社区和合作伙伴(如 CrabNebula)也贡献了多个插件(如 NFC、生物识别等)。

破坏性变更与迁移

  1. 核心插件权限引用变更
    • 变更内容:所有核心插件(如 window, path)的权限标识符需添加 core: 前缀。例如,"path:default" 变为 "core:path:default"
    • 新增权限集:引入了 core:default 权限集合,可一次性启用所有核心插件的默认权限,简化配置。
    • 迁移方式:推荐使用 tauri migrate 工具自动迁移;手动迁移需更新能力配置文件中的权限标识符。
  2. 开发服务器网络访问优化:现在在开发 Android/iOS 应用时,也可直接连接本地开发服务器,无需将其暴露到公网。
  3. 公开 API 重构
    • 为应对未来变化并减少不必要的破坏性更新,对 Rust API 的公开部分进行了收缩,将内部组件私有化,并对公开结构采用 #[non_exhaustive] 属性或构建器模式。
    • 此变更主要影响将 Tauri 作为库的下游开发者,对普通应用开发者影响有限。

安全审计

  • 由 NLNet 资助,RadicallyOpenSecurity 执行的外部安全审计报告已发布。
  • 所有已发现的安全问题(包括独立发现的 CVE-2024-35222)均已修复并验证,相关修复已包含在 Beta 和 RC 版本中。

社区与贡献

  • 发布稳定版前,重点是收集社区反馈、完善文档并修复问题。
  • 鼓励社区成员通过 GitHub Issues、Discussions 和 Discord 参与贡献,包括问题解答、文档改进、内容翻译等,以帮助项目发展。
8. Techniques used by developers to bypass App Store review (9to5mac.com)
# 开发者绕过 App Store 审核的技术手段

## 事件背景
近期,多款盗版流媒体 iOS 应用成功通过 App Store 审核并上架,例如一款名为“Collect Cards”的应用曾登上部分国家免费下载榜首位。苹果在报道后已将其下架,但类似应用仍不断出现。

## 核心技术手段
开发者主要利用以下两种技术组合绕过审核:

### 1. 地理围栏与位置伪装
- 应用内置地理围栏检测,通过 IP 查询设备位置(国家、区域、城市、经纬度)。
- 首次启动时延迟调用地理位置接口,避免触发自动审核的代码扫描。
- 在苹果审核团队所在地区(如加州圣何塞)运行时,仅显示合规的基础界面;而在“安全”位置才会展示真正的隐藏功能(如盗版流媒体界面)。

### 2. React Native + CodePush 远程更新
- 应用基于 React Native 跨平台框架开发,允许通过 JavaScript 更新内容。
- 结合微软的 CodePush SDK,开发者可在不提交新版本的情况下,通过远程更新注入任意代码。
- 此技术本身合法,但被恶意开发者滥用:先提交无害的基础版本通过审核,再通过 CodePush 远程更新为恶意功能。

## 苹果审核机制的局限性
- **自动化审核主导**:App Store 每周审核超过 10 万应用,但大部分依赖自动化流程,易被地理伪装和分阶段更新欺骗。
- **人工审核覆盖有限**:虽拥有 500 多名人工审核员,但难以全面检测动态更新的行为。
- **历史教训未根治**:早在 2017 年,Uber 就曾使用类似地理围栏技术规避苹果总部审核,但苹果后续未建立有效防范机制。

## 苹果的应对与不足
- 苹果在报道后下架了涉事应用,但未公开具体改进措施。
- 文章建议苹果加强多地区行为检测,并更主动地筛查恶意应用,但目前缺乏实质性进展。

## 总结
开发者通过“地理围栏 + 远程更新”的技术组合,利用审核机制的地理盲区和动态更新漏洞,将恶意功能隐藏至审核阶段之后。此类技术虽本身合法,但滥用行为暴露了 App Store 审核系统在动态检测和跨地区验证方面的不足。
11. About Google Chrome's "This extension may soon no longer be supported" (github.com)

从Google Chrome 127版本开始,浏览器扩展管理页面将显示一条警告信息,提示“此扩展程序可能很快将不再受支持”。这是由于Chrome逐步淘汰Manifest v2,转向支持Manifest v3所导致的。广受欢迎的广告拦截扩展uBlock Origin (uBO) 是一个Manifest v2扩展,因此会收到此警告。

目前没有基于Manifest v3的uBO完整版本。作为替代方案,Chrome会推荐用户安装uBlock Origin Lite (uBOL)。uBOL是uBO的一个精简版,其主要目标是将uBO使用的过滤列表尽力转换为符合Manifest v3规范的方式,并延续了自uBO于2014年首次发布以来对可靠性和效率的专注。

然而,这种在Manifest v3环境下对可靠性和效率的专注,意味着必须牺牲许多功能,其中一部分是Manifest v3框架本身所不允许实现的。更详细的uBOL与uBO的功能对比,可参考其官方FAQ页面。

需要明确的是,Manifest v2的uBO不会被Manifest v3的uBOL自动替换。由于两者差异过大,无法进行静默替换。用户需要根据自己的需求,主动做出选择,决定用哪个扩展来取代uBO。最终,uBOL是否是uBO的可接受替代品,完全取决于用户自身的选择。

关于uBO的未来开发:在Chrome上支持可能受限,但uBO的开发将会继续,因为其他浏览器(例如Firefox)并未弃用Manifest v2。

相关讨论指出,存在一个官方方法可以通过Chrome的“ExtensionManifestV2Availability”策略,将Manifest v2的支持延长至2025年6月。此外,社区中对于Chrome扩展Manifest v3的提案、uBO Lite的讨论以及相关兼容性警告也有诸多探讨。

12. Emotional about X11: I'm creating a pure X11 “emoji keyboard” (github.com)

Xmoji 是一个为 X11 设计的纯表情符号键盘,其主要特点是不依赖任何工具包(toolkit)或输入法(input method),并直接通过 XRender 请求来渲染图形用户界面。它是作者之前使用 Qt 开发的 qXmoji 工具的后续版本,并且在功能上已超越前身。

主要功能

  • 发送表情:左键单击表情会通过伪造的按键事件将其发送到当前拥有键盘焦点的 X11 应用程序。提供设置以自动附加零宽空格(Zero-Width Space)或在零宽连接符(ZWJ)序列前添加另一个 ZWJ,以帮助某些 X 客户端正确显示。
  • 选择表情:中键单击可选择表情,以便通过 X11 的“主要选择”(primary selection)机制进行传输。
  • 界面布局:表情按 Unicode 文件建议的主要分组以标签页形式展示。
  • 肤色变体:具有肤色变体的表情只显示中性版本,右键单击会弹出菜单显示所有可用肤色版本。
  • 搜索与历史:提供搜索标签页和历史标签页,后者会自动保存最近使用的表情。

配置与使用

  • 命令行参数:使用传统的 X11 客户端命令行语法(以单破折号 - 开头)。关键参数包括 -cfg(指定配置文件)、-class(设置窗口类名)、-f(前台运行)、-name(设置实例名)以及 -v/-vv(开启详细/调试输出)。还可以通过 -<name> <value> 覆盖 Xresource 值。
  • X 资源(Xresources)配置:外观和渲染通过 X 资源配置,需使用 xrdb 工具加载到根窗口。主要配置类别包括:
    • 字体:配置正常文本、工具提示和表情符号的字体(使用 fontconfig 搜索模式)。
    • 渲染选项:如使用后备存储(backingStore)、DPI、滚动条尺寸和工具提示延迟等。
    • 颜色:提供大量可配置颜色(前景、背景、边框等),支持多种格式并可按部件范围设置。
  • 运行时配置:配置文件通常位于 $HOME/.config/ 目录下,文件名基于实例名(如 xmoji.cfg)。文件会被自动监控以检测外部更改,存储设置对话框的所有选项以及最近使用的表情历史。
  • 访问设置:通过在表情外的窗口区域右键单击可打开设置对话框。

构建

  • 依赖:构建需要 C 编译器(支持 C11 和 GNU 选项)、GNU make,以及一系列开发库(fontconfig、freetype、harfbuzz、libpng、libxcb 相关库、xkbcommon 等)。
  • 构建选项:通过 make 变量提供多种选项,例如:
    • TRACE:启用 X11 请求跟踪。
    • BUNDLED_FREETYPE/BUNDLED_POSER:是否静态链接捆绑的 freetype 或 poser 库。
    • WITH_NLS:支持本地化翻译。
    • WITH_SVG:支持 SVG 字形(需要 freetype >= 2.12)。
    • WITH_KQUEUE/WITH_INOTIFY:使用系统机制监控配置文件变更。
  • 高级配置:使用名为 zimk 的自定义构建系统,可通过 make help 查看所有可配置变量。打包者应注意设置 PREFIXDESTDIR 等变量。
13. 1991 WWW-NeXT Implementation (github.com)

1991-WWW-NeXT/Implementation/ 是由蒂姆·伯纳斯-李(Tim Berners-Lee)最初为NeXT系统开发的“WorldWideWeb”应用程序的代码镜像。该程序是一个原型超文本浏览器兼编辑器,允许用户直接访问超文本服务器、文件和新闻组。

该镜像托管在GitHub上,旨在方便代码浏览。其 Implementation/Features.html 文件提供了一份历史性的更新日志。为了保持时间线的一致性,镜像者将Git提交的日期回溯至每个文件各自的最后修改日期。

14. Show HN: Hanon Pro – piano technique and exercises for the digital age (furnacecreek.org)

Hanon Pro:数字时代的钢琴技巧与练习应用

Hanon Pro 是一款适用于 iPhone、iPad 和 Mac 的应用,旨在通过现代化的曲目和练习帮助用户提升键盘和钢琴演奏技巧。该应用借鉴了健康与健身应用追踪身体健康的理念,用于追踪钢琴练习过程。其智能引擎能够分析演奏、可视化趋势并记录长期练习习惯。

应用内容目录专为在苹果设备上获得出色体验而设计,支持响应式布局、深色模式、丰富的元数据以及内嵌指法编号等特性。用户可以试听每首乐曲、使用内置节拍器进行练习并调整速度。

当通过蓝牙或 USB 连接 MIDI 键盘或钢琴时,Hanon Pro 的核心功能将被激活。智能引擎可分析演奏的准确性、节奏、力度,并能在演奏时自动翻页。为培养练习习惯,应用提供每日练习提醒通知,并集成游戏中心以通过成就系统激励用户。

主要功能包括:

  • 音乐商店与曲目库:浏览并获取专为互动功能(如自动翻页、计算机辅助评估)设计的乐谱,内容涵盖音阶、练习曲以及常用考级曲目。
  • 浏览与元数据:可按作曲家、调性(如ABRSM、RCM、Trinity考级体系)探索音乐,并查看作品的详细元数据。
  • 图书馆管理:支持搜索、排序和过滤乐谱库,并通过iCloud在多个苹果设备间同步。
  • 练习工具:内置节拍器(可调速)、真实感回放引擎。
  • MIDI连接与评估:支持通过蓝牙或USB-C连接MIDI键盘或钢琴,提供对准确性、节奏、风格等方面的实时反馈。
  • 进度追踪与激励:通过图表可视化长期进度;追踪每日练习时间;集成游戏中心解锁成就。
  • 用户体验优化:自动翻页、每日练习提醒(可自定义时间)、深色模式(降低乐谱亮度)、丰富的自定义设置(如节拍器音量、指法显示、MIDI设置等)。
  • 原生应用:基于SwiftUI、Core Audio、Core MIDI、iCloud、Game Center等技术构建的原生苹果平台应用。

曲目内容:音乐目录包含常用于技巧提升的音阶、和弦、Hanon练习曲、Schmitt练习曲以及巴赫、贝多芬、莫扎特等作曲家的作品。用户可在应用内请求添加新乐谱。

应用定位:区别于从零开始教授钢琴的应用,Hanon Pro面向已掌握基础知识、希望提升技巧并获取反馈和进度追踪的钢琴学习者。其理念类似GarageBand的“Learn to Play”功能,但更专注于钢琴技巧训练。

兼容性:兼容大多数现代数码钢琴和MIDI键盘(推荐Yamaha、Roland、Casio等品牌),支持蓝牙和USB连接。系统要求为iOS 17及以上版本(与iOS 26兼容)。

商业模式:由于为每份乐谱实现互动功能(如自动翻页、响应式布局、计算机辅助评估)需要专门制作,并非仅是PDF转换,为维持持续开发,应用内的乐谱和书籍内容需付费购买。

用户评价:有用户反馈称,使用该应用后形成了每天练习的习惯,其游戏化设计(包含反馈、图表、成就和提醒)能持续激励练习。

15. Common I/O Tasks in Modern Java (dev.java)

现代Java中的常见I/O任务

本文聚焦于应用程序员(尤其在Web应用中)常遇到的I/O任务,并强调了自Java 8以来API的改进。核心观点是,应使用现代的java.nio.file.Files等API,摒弃过时的java.io.Filejava.io.BufferedReader类。

核心API改进

  • 默认编码:自Java 18起,UTF-8成为I/O操作的默认字符编码(JEP 400),消除了在文件操作中显式指定编码的需要,提升了代码可移植性。
  • 主要改进的类java.nio.file.Files(Java 7引入,8/11/12增补方法)和java.io.InputStream(9/11/12增补方法)是处理现代I/O任务的关键。

读取文本文件

  • 读取为字符串:使用Files.readString(path)
  • 读取为行集合:使用Files.readAllLines(path)返回List<String>
  • 流式处理大文件:使用Files.lines(path)返回Stream<String>,应配合try-with-resources语句确保流关闭。这取代了BufferedReader.readLine
  • 自定义分隔:使用java.util.Scanner可按非字母等模式分割输入。
  • 数字解析:注意文本数字的格式可能与区域设置相关,建议使用java.text.NumberFormatInteger.parseInt/Double.parseDouble

写入文本文件

  • 写入字符串:使用Files.writeString(path, string)
  • 写入行集合:使用Files.write(path, lines)
  • 格式化输出:若需printf功能,使用PrintWriter(注意:其printf是区域敏感的)。也可用BufferedWriter配合write方法。
  • 从URL或输入流读取数据后,可使用InputStream.readAllBytes()等方法,无需循环。

从Web读取数据

  • 复杂请求:如需设置头信息,使用HttpClient
  • 简单获取数据:直接使用InputStream.readAllBytes()将数据读入字节数组,或使用InputStream.transferTo(outputStream)
  • 集成库:许多库(如Jackson jr)支持直接从URLPath读取JSON、图像等,比传递InputStream更优,因其能利用URL信息确定数据类型。

Files API 核心操作

该类提供文件/目录的创建、复制、移动、删除等全面操作。

  • 遍历目录
    • Files.list(dir):遍历直接子项(文件、子目录等),返回Stream,需用try-with-resources关闭。
    • Files.walk(dir):递归遍历所有后代目录项。
    • 可用流的filtercollect等方法处理结果。
    • Files.walkFileTree提供更精细的遍历控制(如通知),但通常用更简单的Files.walk即可。
  • 废弃方法File.list()File.listFiles()已过时。

处理ZIP文件

  • 推荐方法:使用Java 8引入的ZIP文件系统。
    • 通过FileSystems.newFileSystem(zipPath)创建,需在try-with-resources中管理以自动更新ZIP文件。
    • 之后可直接使用Files类的所有方法(如Files.listFiles.readStringFiles.delete)操作ZIP内条目,极大简化了操作。
  • 旧的ZipInputStream/ZipOutputStream API较为笨拙。

创建临时文件和目录

  • 使用Files.createTempFile(prefix, suffix)Files.createTempDirectory(prefix)方法。它们会在合适位置(如Linux的/tmp)创建临时资源。

总结

现代Java I/O任务有更优、更简洁的解决方案:

  1. 无需循环即可读写字符串或字节数组。
  2. 充分利用Files类的方法进行文件/目录的创建、复制、移动和删除。
  3. 使用Files.listFiles.walk遍历目录。
  4. 使用ZIP文件系统处理ZIP文件。
  5. 避免使用过时的File类,优先采用java.nio.file包中的现代API。
16. Discovering algorithms by enumerating terms in Haskell (twitter.com)

通过在Haskell中枚举项来发现算法

本文探讨了一种在Haskell中系统性地发现算法的方法,其核心思想是枚举(enumerate) 程序中的“项”(terms)。这里的“项”通常指表达式、函数或类型。该方法利用Haskell强大的类型系统和表达能力,通过系统地生成和探索符合特定类型签名的所有可能项,来自动发现满足需求的函数或算法。

核心思路与技术

  1. 类型驱动开发:从目标函数的类型签名出发,例如 (a -> b -> c) -> [a] -> [b] -> [c]
  2. 枚举项空间:使用程序(或在REPL中手动)生成所有符合该类型签名的、由基本操作(如函数应用、lambda、递归等)组合而成的可能项。
  3. 测试与筛选:对生成的候选项进行测试(例如使用QuickCheck或简单示例),根据其行为(输出结果)筛选出符合预期语义的算法。
  4. 发现新算法:这种方法不仅能找到已知算法的实现,还可能发现全新的、有趣的组合或实现方式,因为枚举过程不受先验知识的限制。

关键技术要素

  • 惰性求值:Haskell的惰性求值使得枚举无限列表的项成为可能,只在需要时计算。
  • 高阶函数:大量使用 mapfilterfoldr(.)(函数组合)等高阶函数来构造和组合项。
  • 类型类:利用类型类(如 Eq, Ord, Show)来约束项的行为,使生成的项更可用。
  • 递归:递归是构造项空间的重要部分,能够生成处理列表等递归数据结构的函数。

应用与意义

这种方法特别适用于:

  • 教育:帮助学生理解高阶函数和类型如何组合成复杂行为。
  • 快速原型设计:在需求不明确时,通过枚举探索可能的实现空间。
  • 算法发现:在特定问题域中,系统性地寻找未知的解决方案。

本质上,这是将算法设计过程的一部分自动化,通过搜索由类型约束的程序空间来辅助人类程序员。它体现了Haskell类型系统作为设计工具而不仅仅是约束工具的价值。

17. Go Donut: Convert Live Streaming to WebRTC (github.com)

Go Donut:将直播流转换为 WebRTC

Go Donut 是一个零配置的 SRT (MPEG-TS) 和 RTMP 到 WebRTC 的桥接工具,基于 Pion 构建。

核心功能与目的

该工具的主要目的是将 SRT 或 RTMP 协议的实时直播流,转换为 WebRTC 协议,从而实现在现代浏览器中直接观看直播。

工作原理

工作流程分为三个主要阶段:

  1. 连接建立

    • 用户在浏览器界面输入协议、主机、端口等流媒体信息并点击连接。
    • 浏览器创建 WebRTC Offer 并发送给 Donut 服务器。
    • 服务器回复 WebRTC Answer,完成浏览器与服务器之间的 WebRTC 连接建立。
  2. 流媒体处理与传输

    • 获取媒体:Donut 服务器从指定的 SRT 或 RTMP 源拉取媒体流。
    • 解码转码:使用内置的 ffmpeglibav 库对媒体流进行解复用和转码。
    • 发送:将处理后的媒体流通过已建立的 WebRTC 连接发送至用户的浏览器。
    • 渲染:浏览器接收并解码媒体帧,渲染音视频供用户观看。
  3. 异步流传输:上述的媒体拉取、处理和发送过程在连接建立后异步进行。

部署与运行

快速启动

  1. 环境要求:必须安装 ffmpeg 5.x.x,并正确配置 CGO 库路径。
    export CGO_LDFLAGS="-L/opt/homebrew/Cellar/ffmpeg@5/5.1.4_6/lib/"
    export CGO_CFLAGS="-I/opt/homebrew/Cellar/ffmpeg@5/5.1.4_6/include/"
    export PKG_CONFIG_PATH="/opt/homebrew/Cellar/ffmpeg@5/5.1.4_6/lib/pkgconfig"
    
  2. 安装与运行
    go install github.com/flavioribeiro/donut@latest
    donut
    

使用 Docker Compose

提供 docker-compose 配置,可模拟 SRT 直播传输并轻松运行 Donut。

使用界面

启动后,访问 http://localhost:8080/demo 可打开 Web 用户界面。在该界面中填写直播流的相关信息,点击“Connect”即可连接并观看。

故障排除

如遇问题,可查阅项目提供的 FAQ 文档。

18. Towards userspaceification of POSIX – part I: signal handling and IO (www.redox-os.org)

向用户空间化POSIX迈进(一):信号处理与IO

概述

Redox操作系统获得NGI Zero资助,致力于将POSIX信号处理与进程管理尽可能移至用户空间实现。项目旨在优化内核IPC机制,并重构信号处理架构,以提升系统性能和可扩展性。

改进的用户空间方案协议与无状态IO

Redox内核的传统Packet结构最多支持3个参数,导致技术债务积累(如实现pread需额外样板代码)。新方案采用类似io_uring的提交/完成队列(SQE/CQE),将参数数量扩展至6个,并支持操作码依赖的参数配置。

性能提升

  • 引入SYS_PREAD2/SYS_PWRITE2系统调用,支持偏移量和每调用标志
  • RedoxFS文件复制性能提升63%:277 MiB文件读取吞吐量从170 MiB/s增至277 MiB/s
  • 简化方案实现逻辑(如read_at/write_at替代seek+read组合)

待改进项

  • 旧格式方案需迁移至新协议
  • 事件(Event)结构需类似优化
  • SQE/事件访问应改为环形缓冲区机制

信号处理的用户空间化

问题背景

  • 传统内核信号实现功能有限(缺乏sigprocmasksigaltstack等支持)
  • 微内核架构需最小化内核,将更多POSIX逻辑置于用户空间
  • 当前架构需在用户/内核空间频繁切换信号掩码,导致性能开销

解决方案

通过共享内存原子操作实现信号处理:

  • 在线程控制块(TCB)中存储两个AtomicU64位集(标准信号与实时信号)
  • 低32位为挂起位,高32位为允许集(信号掩码的逻辑非)
  • 使sigprocmask实现无等待操作(通过fetch_add

未来计划

  • 实现进程级信号定向(需内核区分进程/线程)
  • 完善siginfo_t和实时信号队列API
  • 构建用户空间进程管理器,将权限表示为文件描述符(能力)
  • 为全面沙盒化奠定基础

结论

项目进展符合预期,预计夏季末基本完成信号POSIX支持。后续将重点推进进程管理器实现,并可能引入内核性能优化。

22. Primitive Recursive Functions for a Working Programmer (matklad.github.io)

这篇文章主要探讨了“图灵完备性”在实际编程讨论中的常见误解,并通过介绍原始递归函数这一理论工具来澄清相关概念。核心观点是:在实践中,讨论“非图灵完备”时,人们往往想表达的是一系列实用属性(如确定性、终止性、安全性等),而这些属性与真正的图灵完备性定义并无直接关联。

文章的关键理论结论是:如果一个图灵机程序的运行时间被某个原始递归函数所限制(例如,运行时间小于 2^2^N),那么这个算法就可以用原始递归函数本身来实现。这意味着,对于绝大多数实际问题,我们并不需要图灵机完整的(可能不终止的)计算能力,一个保证终止的原始递归函数系统就足够了。

作者通过对比三种计算模型来阐述这一点:

  1. 有限状态机:功能较弱,只能识别正则语言,始终终止但表达能力有限。
  2. 图灵机:计算能力强大,图灵完备,但可能进入无限循环,且其行为在一般意义上是不可判定的(如停机问题)。
  3. 原始递归函数:通过基础函数(零、后继)和受限的构造规则(组合、循环)定义,保证所有函数都终止。它虽然不具备图灵完备性,但可以表达极其快速增长的函数(如 2^2^N),并且能够模拟任何运行时间有原始递归函数上界的图灵机。

文章进一步构建了原始递归函数无法计算的函数(例如阿克曼函数的一个变种 a(n) = A(n,n)),以证明其计算能力确实严格弱于图灵机。这揭示了“非终止性”与“超指数增长终止性”在理论上是不同的,但在实践中,前者等同于后者。

最后,文章回归实践,指出在设计配置语言时,追求“非图灵完备”通常是希望获得以下实际属性,而非仅限于终止性:

  • 确定性:相同输入永远产生相同输出,避免如内存地址等随机性。
  • 良定义性:行为由规范严格定义,保证跨实现的一致性。
  • 纯性:无外部副作用(如IO),结果不依赖执行环境。
  • 安全性/沙盒性:防止恶意代码执行危险操作。
  • 可控的执行时间:通过保证线性复杂度或计量执行(如步数限制)来防御拒绝服务攻击。
  • 简单性:鼓励用户编写简单易懂的程序逻辑。

总结而言,作者认为“图灵完备”是一个精确的数学概念,不应泛化。在实践中,我们真正需要的是上述一系列更强的实用属性。限制语言为“非图灵完备”本身并不能保证这些属性,反而可能是一种用不精确术语来指代复杂需求的做法。

24. To preserve their work journalists take archiving into their own hands (www.niemanlab.org)

这篇文章探讨了当新闻网站关闭或改版时,其内容容易丢失的问题,以及记者们为保存自己的工作成果而采取的个人努力。主要观点如下:

问题现状:近期多个新闻网站(如MTV News、Deadspin、The Awl)内容消失,研究显示仅少数新闻机构能完整保存其内容。网站所有者往往不优先考虑内容保存,导致不仅是读者,记者也面临作品丢失的风险,影响其职业生涯和作品集的建立。

AI带来的复杂性:网站内容可能被用于训练AI模型(如ChatGPT),但如果原始网站下线,未来可能无法追溯信息的原始来源,这对新闻记录的真实性构成挑战。

记者们的个人策略

  1. 主动存档:记者Alex Azzi在任职期间提前将约30篇报道存入Wayback Machine,并为其他作者的报道保存为Word文档。她在求职时,甚至会考虑询问新雇主是否有存档计划。
  2. 技术性保存:广播记者Andrea Gutierrez使用AirTable详细记录作品日期、节目信息,并保存音频文件的本地副本,因为她发现链接经常失效,且某些平台上的内容难以下载。
  3. 利用技术工具:记者Matthew Gault在其所在的Vice面临关闭时,其软件工程师妻子Karen Gault定制了网络爬虫脚本,批量抓取并保存了超过60位作者的全部作品为可读PDF。他们随后协助其他同事保存了作品。

专家建议与挑战

  • NYU的研究馆员Talya Cooper指出,良好的数字保存成本高昂,而廉价方法则依赖大量人力。新闻机构有时会依赖不稳定的内容管理系统作为“存档”。
  • 她建议,如果新闻机构关闭,应尝试联系专业存档组织(如Archive Team、国会图书馆)或学术存档服务(如CLOCKSS、Portico)来接管和长期维护档案,理想情况是传输后端数据而非仅抓取前端页面。
  • 《纽约时报》档案部的Ryan Murphy指出,即使是大型机构,在技术迭代过程中(如从CD-ROM到服务器)也可能因管理疏忽而丢失近代的数字文件。

核心结论:新闻内容作为证据和历史记录,其保存责任链条不清。记者们已认识到必须依靠自己采取创新且往往费时费力的方法来保存作品,这凸显了业界在数字资产长期保存机制上的普遍缺失。

25. ArchiveTeam Warrior (warrior.archiveteam.org)

ArchiveTeam Warrior 是一款虚拟归档工具,用户可通过在个人电脑上运行它来参与 ArchiveTeam 的网站存档工作。它会自动下载指定网站并将内容上传至归档库,整个过程简单易行。

该工具以虚拟机形式运行,因此不会对用户计算机本身造成风险,仅占用部分网络带宽和磁盘空间。它支持 Windows、OS X 和 Linux 系统,需要借助 VirtualBox(推荐)、VMware 或类似虚拟化软件来运行。

使用步骤简述如下:

  1. 下载 Warrior 虚拟机设备文件。
  2. 在 VirtualBox 中通过“导入设备”功能加载该文件并启动。
  3. 虚拟机启动后会自动更新,并提示用户进行浏览器访问。
  4. 访问本地地址 http://localhost:8001/ 的“设置”页面,选择一个用户名(将用于显示在进度排行榜上)。
  5. 在“所有项目”标签页中挑选一个项目参与,或直接选择“ArchiveTeam 的选择”以处理当前最紧急的项目。
27. Character.ai CEO Noam Shazeer Returns to Google (techcrunch.com)

核心事件:Character.ai 创始团队重返谷歌

Character.ai 联合创始人兼CEO Noam Shazeer 将重返谷歌,加入其 DeepMind 研究团队。另一位联合创始人 Daniel De Freitas 及部分员工也将一同加入谷歌。

  • 人物背景:Noam Shazeer 此前曾在谷歌领导团队开发了对话式语言模型 LaMDA,后于2021年10月离职并创立了 Character.ai。
  • 公司变动:Shazeer 和 De Freitas 离职后,Character.ai 的总法律顾问 Dominic Perella 将担任临时CEO。公司表示大多数员工将留任。

双重协议:技术许可与资金支持

谷歌与 Character.ai 签订了一项非独家的技术许可协议。

  • 对谷歌的意义:该协议使得谷歌可以使用 Character.ai 的技术。
  • 对 Character.ai 的意义:协议带来的资金将支持 Character.ai 继续发展,并专注于为全球用户打造个性化 AI 产品。公司此前已通过 a16z 等机构融资超过1.5亿美元。

战略调整:借助外部模型,聚焦产品体验

Character.ai 在公告中指出,其早期需要“全栈”方法(自研预训练、后训练及产品平台),但随着行业变化,预训练模型已更加普及。

  • 新策略:公司将更多利用第三方大语言模型(LLM),同时结合自研模型。
  • 资源重配:此举旨在将更多资源集中于“后训练”和创造新的产品体验,以服务不断增长的用户群体。

潜在监管风险

此类“反向人才收购”(acqui-hire)交易可能面临严格审查。

  • 先例参考:文章提及,英国竞争与市场管理局(CMA)正在审查微软从 Inflection AI 挖角关键人员一事,美国联邦贸易委员会(FTC)也对微软的类似交易展开了调查。
  • 本次关注:Character.ai 创始人及部分员工加入谷歌的交易,同样可能引发美国(如FTC、司法部)和欧盟监管机构的关注与审查。
28. Magnetically levitated space elevator to low-earth orbit [pdf] (2001) (publications.anl.gov)

磁悬浮太空电梯到近地轨道(2001年PDF文档)摘要

本文档是一份技术性PDF文件,标题为“Magnetically levitated space elevator to low-earth orbit”,发表于2001年。文档主要探讨利用磁悬浮技术构建太空电梯以实现向近地轨道运输的概念。基于提供的元数据,该文档创建于2002年7月10日,采用PDF 1.3格式,由Acrobat Distiller 5.0.5(Windows版本)生成,共包含7页内容。文档结构包括页面列表,但未提供具体文本细节,因此可能聚焦于磁悬浮太空电梯的设计原理、技术可行性、潜在优势及相关挑战。这类文档通常涉及工程学、物理学和太空探索领域的专业知识,旨在分析磁悬浮技术在太空基础设施中的应用前景。