为什么 REPL 风格的开发在 Ruby 中没有更常见?
看起来 Lisp 和 Clojure 程序员经常直接在 REPL 中开发程序。参见Clojure 开发:IDE 还是 REPL?
我的问题是,为什么这种方法不更在 Ruby 中很常见,通过 irb?这仅仅是文化差异,还是存在结构(特定于语言)的原因,导致以 REPL 为中心的开发在 Lisp 中比在 Ruby 和 Python 等语言中更常见?
It looks like Lisp and Clojure programmers often develop programs directly in the REPL. cf. Clojure Development: IDE or REPL?
My question is, why isn't this approach more common in Ruby, via irb
? Is this just a cultural difference, or are there structural (language-specific) reasons why REPL-centric development is more common with Lisps than with languages like Ruby and Python?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
Lisp 语法似乎非常适合结合 REPL 和源文件的方法。当每种表单的文本限制明确时,以编程方式移动代码片段会容易得多。
Lisp syntax seems to lend itself very nicely for a combined REPL-and-source-file approach. It is much easier to move code snippets around programmatically when the textual limits of each form are clear.
实际上,这就是我开发 Ruby 的方式。
通常我编写代码,然后将其部分粘贴到 irb 中,调整它们,再次粘贴它们等等。
Lisps 中没有办法打印出您在程序中开发的 REPL 风格的“当前状态”吗?我认为这在红宝石中是不可能的。
Actually that is my way of developing Ruby.
Usually i write my code, then i paste portions of it into irb, adapt them, paste them again and so on.
Isn't there a way in Lisps to print out the "current state" you developed REPL-style in a program? I think that's not possible in ruby.
我认为这很大程度上是由于 Rubyists 倾向于使用的编辑器造成的。我使用 vim,它没有很好的方式与 REPL 交互。 Textmate 也有同样的情况(据我所知)。另一方面,Emacs、Dr Racket 等都有一个与 REPL 交互的奇妙机制。我相信 Lispers 会倾向于使用这些类型的编辑器/环境。
I think a lot of this is due to the editors that Rubyists tend to use. I use vim, which doesn't have a great way to interact with a REPL. Textmate is in the same boat (AFAIK). Emacs, Dr Racket, etc., on the other hand, all have a wonderful mechanism for interacting with a REPL. I believe Lispers would tend to use those types of editors/environments.
也许这些会有所帮助:
我是老派,所以我通常会打开一个编辑器并在终端窗口中运行 irb;你知道,旧习惯很难改掉。我确实使用 irbtools,但打算切换到 Utility Belt 来看看相比之下感觉如何。
Maybe these will help:
I'm old-school so I usually have an editor open and irb running in a terminal window; Old habits die hard you know. I do use irbtools, but intend to switch over to Utility Belt to see how it feels in comparison.
通常,运行单元测试比通过 Ruby 的 REPL 等价物输入内容要省力。话又说回来,有时我必须在代码中添加一些 printf 调试......
Often running your unit tests is less effort than typing things in via Ruby's equivalent to the REPL. Then again, sometimes I have to add some printf debugging to the code...
我使用 Ruby 已经有 17 年了,总是使用 REPL 来帮助我处理所有事情,通过使用纯 IRB,或者使用 Rails 控制台来处理 Rails 应用程序,我通常在我想要调查/调试的东西中间打开 IRB 会话,所以在很多情况下,实际上 IRB 通常是我的主要调试器。
当然,我在 Ruby 中使用 REPL 的工作不会回忆起 LISP 中的整个体验,我可能会在 Ruby 中打开和关闭解释器,比在 CL 或 Scheme 中打开和关闭解释器要多数百倍,在 CL 或 Scheme 中它会保持打开状态更长的时间(而且我也直接从终端使用它,而不是在 emacs 中使用它,但这是个人选择,因为我的工作环境方便)。
由于 Ruby 的检查功能非常强大且灵活,因此我在某些情况下使用 IRB 是非常常见的,例如,我不记得方法的名称,但我记得它的一部分......我只是问直接获取对象的方法列表,并使用枚举器方法过滤数组以“选择/检测”与我想要的类似的方法,然后调用正确的方法,检查结果等(
my_object.methods.select{ |m| m =~ /that_part_of_the_name_i_remember/ }.sort
)。在任何需要 IRB 会话的地方,您都可以调用
binding.irb
,因此,如果您想在正在运行的测试中或在 Web 服务器上的请求处理期间打开它,实际上并不重要,等等,您都可以总是很容易地打开它,并从那里了解您需要的有关您的对象的任何信息,我一直这样做。由于 Ruby 具有开放类和开放对象,与您在 CL 中找到的方式相同,因此您可以在 IRB 会话中一次又一次地重写方法,直到达到您可能想要的结果,唯一需要注意的是您需要复制并将这个新版本“手动”粘贴到正确的位置(但即使使用 Ruby,这实际上也变得更容易,因为您可以通过简单地调用类似
my_obj.method(:that_specific_method) 来询问 Ruby 到底在哪里定义了一个方法。 source_location
它适用于来自 Gems/库的方法。更让我感到自豪的是,我认为自己只是调用`emacs #{my_obj.method(:that_specific_method).source_location.join(":" )}`
这不仅是个人风格,而且解释器对于社区来说也非常重要,实际上开发人员为了拥有一个功能强大、始终可用且易于使用的工具付出了很多努力。 -use 工具。 IRB 总是与 lib readline 一起提供,最近它有了一个更强大的编辑器,但在它里面编辑东西总是比在 CL 或 Scheme REPLS 中容易得多(因为我在学习 LISP 之前就学了 Ruby 好几年了,当时我刚开始学习 LISP)直接使用 CL 和Scheme REPLs 我总觉得它们实际上很糟糕,我花了很多时间才习惯了解释器不是为了以同样的方式使用的想法,并习惯了 Slime 和盖瑟;在命令行中打开 SBCL 并且默认情况下至少没有包装基本的 readline - 感谢 rlwrap! - 一开始是非常奇怪的事情,即使在今天,有时我也不明白为什么某些事情在 LISP REPL 中不正常,或者我应该如何做它们。
(我无法表达在一个 LISP REPL 中开始键入我选择不使用的一行是多么令人沮丧,键入 Ctrl-C 而不是仅仅“取消”我的行它为我提供了一个重新启动选项,因为我这样做了我知道所有的 LISP 开发人员都是神,他们永远不会输入他们不想要的行,但由于我不是其中之一,我通常想重新启动该行,即使在 emacs+Slime 上,这也需要更多的努力。而不仅仅是“Ctrl-cing”该行)
我不是在谈论那些要比较的东西,也不是说 IRB 比这个或那个 REPL 更好,而是为了表明这是 Ruby 开发人员生活的一部分,就像 CL 或 Scheme 一样REPL 已经融入了 lispers 的生活,除了将其嵌入到 emacs 或您选择的文本编辑器中的部分(有些人这样做,有些人不这样做),但它的内置编辑器变得如此强大,以至于今天当您在块内时,它会自动缩进代码,默认情况下具有语法突出显示,它会使用 TAB 自动完成方法的名称,但如果您已经输入了方法的完整名称并再次到达 TAB,它将显示你可以通过简单地输入“q”来关闭该方法的文档...这种集成使其使用起来非常简单,以至于我很少将它与使用 Slime 的方法进行比较,但它对我所有人都有帮助时间,它推动了我大量的探索性工作,学习新工具、新库,通过到处的小实验创建代码等等。这与编写测试的习惯一起经常推动我的工作方式,我以疯狂的方式混合测试和 IRB 会话,包括从测试中打开 IRB 来检查内容,当我达到我认为可以的程度时关闭它们,在更改代码的情况下再次运行测试,然后继续。
我唯一感受到的超越我的体验是使用 Smalltalk 和 Pharo,其中编码、检查、实验之间的障碍比这更低。
(观察:我知道有人使用 Slime 和 Ruby 创建了一个 Swank,但我从来没能让它正常工作......但这也许意味着有人拥有世界上最好的,对吧?)
I'm working with Ruby for 17 years and always used the REPL to help me with everything, by using pure IRB, or using Rails console for Rails apps, I usually open IRB sessions in the middle of something I want to investigate/debug so often that actually IRB is the main debugger for me in a lot of situations.
For sure, my work using the REPL in Ruby would not recall the whole experience in LISP, I probably would open and close the interpreter hundreds of times more in Ruby than in CL or Scheme where it would stay open for a longer time (also I use it directly from the terminal instead of using it inside emacs, but that is a personal choice due to convenience on my work environment).
Since Ruby is very powerful and flexible to inspect itself, it is very very common for me to use the IRB in situations where for example I don't remember the name of a method but I remember part of it... I just ask the object directly for its list of methods and filter the array using Enumerator methods to "select/detect" the ones that are like what I want, then call the proper method, inspect the result, etc (
my_object.methods.select{|m| m =~ /that_part_of_the_name_i_remember/ }.sort
).Anywhere you need an IRB session you can just call
binding.irb
so it doesn't matter actually if you want to open it inside a running test or during a request processing on your web server, etc you can always open it very easily and learn whatever you need about your objects from there, I do this all the time.And since Ruby has open classes and open objects in the same way you could find in CL, you can rewrite a method again and again inside your IRB session until you reach a result you may want, the only caveat is that you will need to copy and paste this new version "manually" to the proper place (but even this is actually made easier using Ruby, since you can ask Ruby where exactly a method was defined by simply calling something like
my_obj.method(:that_specific_method).source_location
which works including for methods from Gems/libraries. More than what I would be proud about I took myself just calling`emacs #{my_obj.method(:that_specific_method).source_location.join(":")}`
.And this is not only a personal style, but the interpreter is also so important for the community that actually the devs did a lot of effort in order to have a powerful, always available, and easy-to-use tool. IRB since always came with lib readline and recently it received a much more powerful editor, but editing things inside it was always much easier than in CL or Scheme REPLS (since I learned Ruby years before learning LISP, when I first started using CL and Scheme REPLs directly I always felt that they were actually horrible, it took me a lot of time until I got used to the idea that the interpreters were not made to be used in the same way, and to get used to Slime and Geiser; opening SBCL in a command line and not having at least the basic readline wrapped by default - thanks rlwrap!!! - was something very strange in the beginning, and even today sometimes I do not understand why certain things are not normal in LISP REPLs or how I'm supposed to do them.
(I can't express how frustrating it is to be in one LISP REPL to start typing a line that I chose to not use, type Ctrl-C and instead of just "canceling" my line It presents me a restart option because I did something wrong. I know all LISP developers are gods who would never type a line that they would not want, but since I'm not one of them, I usually want to restart the line and even on emacs+Slime this requires much more effort than just "Ctrl-cing" the line)
I'm not talking about those things to compare and say IRB is better than this or that REPL, but to show that this is so much part of a Ruby developer's life as the CL or Scheme REPLs are on lispers' life, except maybe for the part of embedding it on emacs or text-editor of your choice (some people do this, some others don't), but its build-in editor is becoming so much powerful that today it automatically indents the code when you are inside a block, it has syntax highlighting by default, it auto-completes with the name of a method using TAB, but if you already typed the entire name of the method and reach TAB again it will show you the documentation of that method, which you can close by simple typing "q"... this kind of integration makes it so simple to use that rarely I compare it with what I would have using Slime for example, but it helps me all the time and it drives a lot of my exploratory work learning about a new tool, a new library, creating my code by little experiments here and there, etc. This together with the habit of writing tests often drives my way of work, and I mix tests and IRB sessions in crazy ways, including opening IRBs from a test to check things, closing them when I reached the point I thought it was ok, running the tests again with the code changed, and going on.
The only experience I felt has gone beyond what I have with this was using Smalltalk and Pharo, where the barrier between coding, inspecting, experimenting was lower than this.
(Obs.: I know someone created a Swank using Slime with Ruby, but I never was able to make it work properly... but maybe this means someone has the best of all worlds, right?)