编程与软件工程vvvvalvalval.github.io
什么造就了好的 REPL?
What makes a good REPL?
2017 — 2022,它一次次回到首页
黑点是上首页(≥ 50 分)的那次投稿,空心点是没冲上去的投稿,点越大分数越高。
导读
这篇文章讨论什么样的 REPL 才算好用。作者从 Clojure 等交互式开发经验出发,谈到可读的输出、REPL 与源文件/编辑器的顺畅协作,以及避免把 REPL 当成临时草稿再手工拷回代码等实践。文中也涉及不可变数据、测试与 REPL 的关系等容易被误解的点,评论对此有不少争议。
为什么经久不衰:REPL 驱动开发在 Lisp、Clojure、Smalltalk 等社区长期重要,这篇文章提炼了可操作的原则,而围绕不可变性、测试和工作流的争论让它今天仍值得一读。
HN 评论精选
认为把不可变性当作好 REPL 的关键是 Clojure 视角的偏见,Lisp 传统 REPL 并无不可变数据。
我不确信不可变性有那么重要;这看起来像一种偏见。毕竟最初的 REPL(连这个名字本身)来自 Lisp(注意最早的 Lisp 实现并非交互式,但 Lisp 是第一种交互式语言),而 Lisp 并没有不可变数据结构。(READ、EVAL、PRINT 都是古老的 Lisp 原语,REPL 字面上就是用它们实现的。还有一个叫 LOOP 的复杂宏,但它是很久以后才加入的,并不是语言的核心。)
gumby查看英文原文
I am not convinced that immutability matters; this seems like a bias. After all the original REPL, and the name itself, was in Lisp (note that the first Lisp implementations were not interactive, but it was the first interactive language) and Lisp doesn't have immutable data structures. (READ, EVAL, and PRINT are all old Lisp primitives, and the REPL was literally implemented with them. There's also a complex macro called LOOP but it was added much later, and is not integral to the language)
推荐从源文件求值 form 到 REPL,而不是在 REPL 里写再拷回文件;这是应避免的 REPL 反模式。
用了一阵 Emacs 的 Elisp 之后,我改掉了一些在 Clojure 开发中养成的 REPL 反模式(不幸的是,本文也提到了其中一些),尤其是这一点:与其在 REPL 里输入、执行,再把代码复制回真正的源文件,你可以直接在源文件里写,然后用“求值当前 form”或“求值光标前的 form”把它发送给 REPL 进程求值,而不必费劲地在 REPL 里输入再复制回来。注意这不是传统意义上的热重载,而是把这个 form 作为字面量发送给 REPL(其间可能间接发生热重载)。
_pmf_查看英文原文
Using Emacs' Elisp for a short while helped me unlearn some REPL antipatterns I acquired during Clojure development (some of them unfortunately presented in this article), especially this: instead of typing something in the REPL, executing it, then copying it back into your actual source file, you can just write it in your source file and use "evaluate current form" or "evaluate form before current point" to send it to the REPL process for evaluation instead of painstakingly entering it in the REPL and copying it back. Note that this is not a conventional hot-reload, but the form is sent as literal to the REPL (where indirectly, hot-reload may occur).
指出 REPL 的临时性和静态类型限制,作者更偏好可重复的单元测试与静态分析。
对于编译很快的语言,单元测试离 REPL 并不远。在 Java 里我就把 JUnit 当 REPL 用。其实我更喜欢单元测试而不是 REPL,就像我喜欢 bash 脚本胜过一行命令、喜欢 SQL 脚本胜过在解释器里敲命令一样……我不喜欢 REPL 的短暂/易失性质。另外,与我提到的 Java 调试式单元测试不同,真正的 REPL 确实要求语言是动态的。我不完全确定原因,但静态类型语言似乎不太擅长在运行时修改代码(我有一些猜想,但不知道是否存在真正的理论限制)。我想我还是更喜欢静态分析,而不是在运行时完全修改代码库的能力。之所以说这些,只是因为文章没有提到 REPL 的任何缺点。
agentgt查看英文原文
With fast compiling languages a unit test is not for off from being a REPL. In Java I use JUnit as a REPL. Actually I prefer unit tests over a REPL the same reason I prefer bash scripts over one liners or SQL scripts instead of typing into the interpreter... I don't like the ephemeral nature of REPLs. Also with true REPLs unlike the debug unit test approach I mention with Java you really need the language to be dynamic. I'm not entirely sure why but static type languages are not very good at allowing code modification while running (I mean I have ideas but I don't know precisely if there is an actual theoretical limitation). I guess I prefer static analysis over the complete ability to modify the code base while running. Only add my 2 cents because the article doesn't mention any negatives to REPLs.
REPL 不能替代可重复的自动化测试,但能帮助快速探索并更快写出测试。
REPL 不会让你少写测试。是你自己因为误以为手动测试可以替代任何人都能再次运行的代码化测试,而让自己少写了测试。一旦有人需要修改代码并验证没有破坏东西,在 REPL 里做过的测试就全都失效了。REPL 可以让你更快到达可测试状态。比如你在做 TDD,需要一个失败测试来证明代码改动的必要性;如果你还在探索问题和可能方案,可能并不确切知道那个测试是什么。你用 REPL 快速迭代,等确定了想要的代码改动,再写测试并验证它在没有改动时失败。
kazinator查看英文原文
A REPL doesn't let you write fewer tests. You let yourself write fewer tests because of the mistaken idea that manual testing replaces a coded test that anyone can run again. Any testing that had been done in the REPL goes out the window as soon as someone needs to change the code, and verify that things haven't broken. A REPL can get you faster to a testable state. Say you're following TDD and so you need a failing test which passes in oreder to justify a code change. You might not exactly know what that test is, if you're exploring the problem itself and possible solutions. You use the REPL to iterate quickly on things. Then when you settle on the code change you want, you can write the test, and verify that it fails without the change.
历次讨论
同类还值得读
开源应用架构
The Architecture of Open Source Applications
《开源软件架构》(AOSA)是一本在线免费书,邀请知名开源项目的作者亲自剖析其内部设计,涵盖 SQLAlchemy、LLVM、Audacity、Apache、Bash 等系统。
编程与软件工程上首页 9 次 · 2011–2024aosabook.org编辑精选编程语言简史:简短、不完整且多半错误
A Brief, Incomplete, and Mostly Wrong History of Programming Languages
一篇以戏谑、故意不准确的方式回顾编程语言史的博客文章,用夸张轶事和讽刺定义串起 Lisp、C、C++、Java、JavaScript、PHP 等语言。
编程与软件工程上首页 8 次 · 2009–2021james-iry.blogspot.comSQLite 是如何测试的
How SQLite is tested
SQLite 官方文档页,系统介绍 SQLite 的测试体系:多种测试方法(TCL 测试、模糊测试、回归测试、静态分析等)和海量测试用例,展示了这个小型开源项目如何靠极致测试获得…
编程与软件工程上首页 8 次 · 2009–2025sqlite.org编辑精选高级编程语言(2009)
Advanced programming languages (2009)
Matt Might 的经典文章,按用途推荐“高级编程语言”:如果追求就业就选主流语言,如果追求表达力、学术研究或创业,则推荐 Haskell、OCaml、Scala 等函数式语…
编程与软件工程上首页 8 次 · 2009–2022matt.might.net我的 Forth 与栈机器经历
Yosefk - My history with Forth & stack machines
作者以亲身经历回顾了使用 Forth 语言和栈式机器的历程:既赞叹其简洁优雅、代码量小、可自举的优点,也坦率指出栈操作在实际编程中的痛苦,以及 Forth 社区文化中的问题。
编程与软件工程上首页 8 次 · 2010–2024yosefk.com编辑精选