告别传统调试器:IntelliJ IDEA 的 Run to Cursor 和 Quick Evaluate Expression 功能

2025-03-28

作者厌倦了传统调试器的繁琐,尤其是gdb和lldb在原生代码调试中的无力感。他发现IntelliJ IDEA的“Run to Cursor”和“Quick Evaluate Expression”功能组合,可以将调试器转变为强大的REPL环境。通过“Run to Cursor”将程序运行到光标所在行,再用“Quick Evaluate Expression”在当前栈帧中评估表达式,甚至可以输入新的代码并执行,实现了高效的代码探索和实验。这种方式摒弃了传统的单行命令交互,而是利用编辑器的二维文本界面,提供代码补全等特性,极大提升了调试效率。

阅读更多
开发

在脚本中使用长选项

2025-03-22

许多命令行工具都支持短选项(-f)和长选项(--force)。短选项适用于交互式使用,而长选项更适合在脚本中使用。长选项更易于阅读和理解,提高了脚本的可维护性和可读性。例如,在Git命令中,使用`git switch --create release-{today} origin/main` 比 `git switch -c my-new-branch` 更清晰明了,尤其是在复杂的脚本中。

阅读更多
开发 长选项

硬核Rust:无动态内存分配的光线追踪器

2025-01-30

本文介绍了作者使用极简API(无动态内存分配)编写Rust应用程序的案例研究。作者批评了RAII(资源获取即初始化)机制导致资源管理混乱,并提出了一种“硬核模式”:将程序分割成`std`二进制文件和`#![no_std] no_alloc`库,仅允许二进制文件直接向操作系统请求资源。文章以一个玩具光线追踪器为例,详细讲解了在“硬核模式”下如何处理像素缓冲区、并行化、内存分配器和场景解析等问题,最终实现了一个无需动态内存分配的光线追踪器。

阅读更多
开发

不变式:编写正确代码的利器

2025-01-12

本文探讨了编程中“不变式”的概念及其应用。作者从一个小例子——编写一个计算插入点的二分查找变体——出发,阐述了如何通过明确定义并维护不变式来编写正确的代码。 文中指出,不变式是一种在系统动态演变过程中始终保持的属性,它能够简化推理过程,避免因考虑多种执行路径而带来的复杂性。 作者还以Cargo、rust-analyzer和TigerBeetle等项目为例,展示了在大型系统中应用不变式带来的好处,例如提高代码可维护性和性能。最终,作者总结了不变式在小规模和大型编程中的重要作用,强调了其在编写正确且高效代码中的价值。

阅读更多
开发

颠覆性设想:将Magit理念应用于jj版本控制系统

2024-12-13

作者提出了一种新颖的思路,将Emacs的Magit版本控制界面(以文本文件为UI)应用于新兴的jj版本控制生态系统。文章指出,Magit的文本化UI具有高效性和可移植性,通过LSP协议,可以在多种编辑器中实现类似Magit的体验,避免重复开发。作者设想通过生成特定文本文件(如.jj/status.jj),并利用LSP的语义标记、折叠范围和跳转定义等功能,实现与Magit类似的版本控制操作,最终目标是创建一个跨平台、高效的jj版本控制用户界面。

阅读更多
开发 jj Magit

缺失的IDE特性

2024-11-04

本文作者认为IDE中缺失一项重要特性:默认折叠方法体。该特性易于实现,能极大提升阅读代码的效率,却在多数编辑器中缺失。文章详细解释了该特性的工作原理:仅折叠方法体而非其他代码块,折叠是默认状态,并在跳转到定义时自动展开。作者认为该特性能隐藏80%的非核心代码,突出重要的函数签名,提升代码可读性。文章呼吁编辑器开发者添加此功能,并指出通过Tree-sitter或LSP可以相对容易地实现。作者本人六年前已在rust-analyzer中实现了该功能的服务端部分,但受限于LSP协议,未能完全实现。

阅读更多
未分类 代码折叠

更深层次地修复问题

2024-10-16

本文讲述了作者在一天的工作中,如何通过更深层次地思考问题,发现并修复了一系列潜在的错误和设计缺陷。从数据库磁盘空间不足的错误信息,到代码格式化问题,再到编译时参数的混淆,作者不断地挑战自己,寻找更优雅、更彻底的解决方案。最终,作者将问题归结到代码逻辑的重构上,并试图通过改进代码设计来避免此类问题的再次发生。

阅读更多
未分类

什么是 io_uring?

2024-09-24

io_uring 是一种全新的 Linux 内核接口,用于进行系统调用。与传统的同步、逐个提交系统调用的方式不同,io_uring 采用批量异步方式。应用程序通过将系统调用代码和参数写入无锁共享内存环形缓冲区来提交多个系统调用。内核读取并按自身节奏执行,结果异步写入第二个环形缓冲区供应用程序读取。

阅读更多
未分类 io_uring

软件依赖的基本法则

2024-09-04

文章指出,软件的规范源码应该包含所有依赖项内容的校验和,并列举了几个例子:源码管理应该使用类似Git的内容寻址版本控制系统;第三方库的依赖关系应该使用包含校验和的锁文件管理;编译器的哈希值也应该包含在锁文件中,以便验证编译器的可靠性。作者认为,校验和本身并不重要,重要的是获取校验和的过程能够促使开发者明确依赖项、自动化下载依赖项、确保依赖项构建的可重复性以及隔离项目依赖项,最终使得软件开发变得更容易。

阅读更多
未分类 软件依赖

Rust 的丑陋语法

2024-08-30

这篇文章探讨了Rust语法,作者认为人们对Rust语法的抱怨实际上是对其语义的反对。文章以一个读取文件的Rust函数为例,展示了其语法复杂性,并尝试用其他语言风格改写,以期找到更简洁的表达方式。作者进一步探讨了简化Rust语义的可能性,例如移除泛型、借用和错误处理机制,最终得到了一个更简洁但牺牲了性能和安全性的版本。

阅读更多
未分类

面向程序员的原始递归函数

2024-08-03

本文讨论了图灵完备性的概念,并指出在实践中,非图灵完备性并不像人们通常认为的那样重要。作者通过介绍有限状态机、图灵机和原始递归函数,证明了任何在图灵机上运行并在原始递归函数时间内终止的算法都可以用原始递归函数实现。文章还探讨了良好配置语言的特性,包括确定性、定义明确、纯洁性、安全性、沙盒化和简单性,并指出非图灵完备性本身并不能保证这些特性。

阅读更多
未分类 原始递归函数

我是如何使用 Git 工作树的

2024-07-26

文章介绍了作者如何利用 Git 工作树来管理并发任务,而不是将其作为分支的替代品。作者创建了五个工作树,分别用于查看原始代码、编写代码、审查代码、运行模糊测试以及处理其他临时任务。这种方法提高了作者的编码效率,并能更好地管理并发任务。

阅读更多
未分类 工作树

如何正确地测试并发数据结构

2024-07-06

文章介绍了一种测试并发数据结构的方法,通过模拟并控制线程的执行顺序,实现了对并发操作的精细化测试。作者首先解释了传统并发测试的不足,然后逐步推导了一种基于“管理线程”的测试方法,并用一个简单的计数器示例演示了如何使用该方法发现并最小化并发错误。文章最后还探讨了如何将该方法扩展到更复杂的场景,例如模拟弱内存模型和穷举所有可能的交错执行路径。

阅读更多
未分类 并发测试

正则、递归、受限

2024-06-05

本文探讨了如何使用一种称为“递归受限正则表达式”的新形式来描述算术表达式。作者首先指出现有语法(如上下文无关文法和解析表达式文法)在描述表达式优先级和结合性方面的局限性。然后,作者提出了一种使用正则表达式来定义树形结构的方法,并通过添加约束规则来消除歧义。最后,作者提出了一个问题:是否存在一种算法可以判定任意递归受限正则表达式是否具有歧义性。

阅读更多