Why isn't REPL-style development more common in Ruby?
It looks like Lisp and Clojure programme开发者_运维问答rs 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?
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.
I use Emacs for Clojure and Ruby and often load my ruby modules into irb and play interactively in emacs the same way I do the 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.
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.
Maybe these will help:
- interactive_editor is an IRB extension that adds in the ability to open vim, emacs, MacVim, nano and TextMate and do editing of the irb buffer.
- irbtools includes interactive_editor along with some other nice additions.
- Utility Belt is another collection of IRB gems extending its functionality and also includes something to allow editing the buffer.
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.
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...
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?)
精彩评论