Why I don't use Ruby

Let us as an example look at a program that looks at a directory of
Web pages, and traces through them. If it cannot find a link to a
certain page, then it creates a link on a page in a prescribed manner.

You've written the program and tested it on a small data set.
Now you want to test it on a large data set. It fails miserably
and you try to debug.
Phase one of the program gets a list of all the files in the directory
( recursively ).
Phase two is to scan the root files for hrefs. Then scan the files in
the hrefs. Then ... untill there are no more files to scan.
Phase three is to pick some file you didn't reach and create a link to
it.

So you work on Phase one and get it to run.
Then you work on Phase two. But it takes Phase one
ten minutes to run. So each time you test a fix in phase two
it takes at least ten minutes to run.

Although different than saving the whole program image,
It's pretty to load/save entire object hierarchies in
Ruby... For ex:

# A little boilerplate...

require 'yaml/store'
ystore = YAML::Store.new("my_persistent_data")

# At the end of phase one, we'll have our file list,
# which we can persist as easily as:

ystore.transaction { ystore["filelist"] = phase_one_filelist }

# At the beginning of phase two, we can load it:

phase_one_filelist = ystore.transaction { ystore["filelist"] }

. . . This would allow phase 1 and 2 to be totally separate
ruby programs, if you like.

Just one possibility...

Regards,

Bill

···

From: "TLOlczyk" <olczyk2002@yahoo.com>

There is no reason that you can't do this with Ruby. If I have code
that works like:

  file_list = find_files
  missing_files = file_list - find_hrefs(file_list)
  make_hrefs(missing_files)

Then I can simply do:

  file_list = find_files
  File.open("file_list.m", "wb") { |f| f.write Marshal.dump(file_list) }

Then, I can make the main loop do:

  file_list = Marshal.load(File.read("file_list.m"))
  missing_files = file_list - find_hrefs(find_files)
  make_hrefs(missing_files)

With a bit of work, you could integrate this into the main program; it
might even be desirable if find_hrefs takes even longer than
find_files; that way, you could choose to load a predetermined
file_list (making it possible to "version" such lists) or use the
stored file_list as a comparison point. Or, even, do something like:

  if File.exists?("file_list.m")
    file_list = Marshal.load(File.read("file_list.m"))
    File.rm("missing_files.rm")
  else
    file_list = find_files
  end

  begin
    if File.exists?("missing_files.m")
      missing_files = Marshal.load(File.read("missing_files.m")
      File.rm("missing_files.rm")
    else
      missing_files = file_list - find_hrefs(find_files)
    end
  rescue
    File.open("file_list.m", "wb") { |f| f.write Marshal.dump(file_list) }
    raise
  end

  begin
    make_hrefs(missing_files)
  rescue
    File.open("missing_files.m", "wb") { |f| f.write Marshal.dump(file_list) }
    raise
  end

Now, you have something repeatable that withstands all sorts of errors
without having to repeat portions that you don't need to do.

-austin

···

On Fri, 2 Jul 2004 11:37:48 +0900, TLOlczyk <olczyk2002@yahoo.com> wrote:

You've written the program and tested it on a small data set.
Now you want to test it on a large data set. It fails miserably
and you try to debug.
Phase one of the program gets a list of all the files in the directory
( recursively ).
Phase two is to scan the root files for hrefs. Then scan the files in
the hrefs. Then ... untill there are no more files to scan.
Phase three is to pick some file you didn't reach and create a link to
it.

So you work on Phase one and get it to run.
Then you work on Phase two. But it takes Phase one
ten minutes to run. So each time you test a fix in phase two
it takes at least ten minutes to run.

So you save an image at the end of phase one. Each time
you test phase two, you load the image from phase one
and just test phase two. Save ten minutes on each test run.

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Personally, I think languages are about the right tool for the job, and Perl, Python and Ruby have nicely proven that dynamic file-based scripting languages are more then sufficient for a huge variety of programming tasks. If you are looking for a secondary tool-language, I can't imagine images, native compilers, and REPL being so critical as to drop Ruby. What better options are there? And the points about native compilers in the responses are well put- it's a trade off, and in the Ruby world you can drop into C where you need to (not ideal, but sufficient). As Donald Knuth put it, "premature optimization is the root of all evil".

A question back to the original poster: I think that many Rubyists and Pythonists return to native compiled languages etc. only to drop them because the loss of productivity is too painful and costly. What effects do the problem domains you code in have on this tradeoff, and what solutions have you found?

Images would be nice, but the scale of most Ruby programs I write, and the methods that I write them by, don't make me lament them too much. One epiphany test driven development has produced in programmers is that tests drive the design, forcing good design early and often- e.g. the common statement that TDD isn't really about testing.

The reason for this is that unit testability requires clean interfaces, strong cohesion, loose coupling- i.e. good modular code. Constantly subjecting code to testing from the start forces continual design decisions and refactoring to maintain testability, and the modularity is easier to maintain as a result.

If your code requires 10 minutes to get to a certain point, and you can't easily capture that state with a data-only dump (e.g. Marshal or YAML), and then continue testing from that point, that would be a good motivation to refactor. However, if TDD hasn't been followed up to that point, the code may be hard to seperate due to the design debt built up by not having the code constantly challenged by small tests (my solution there is to use log4x to due a pseudo-design-by-contract, make core domain classes invariant, elimate trival singletons/globals, and then find a couple of good "cut" points to get pseudo-modularity, and then try to use TDD going forward).

(Aside: Personally, I learned more about design and design patterns via TDD and refactoring in six months then I did in 5 years of pattern reading. In my real world career, the problems and problem domains I coded tended to preclude writing the same program multiple times and personally trying various design approaches. And the nature of traditional coding practice is that the early design decisions tend to stick. So most projects get stuck with marginal designs. The nature of TDD/refactoring and there emergent design practices is that you get to see broken/fixed design elements continually in the same coding process, and the more elegant and robust end product result in a much more learning intense experience).

I guess the short summary to my long-winded point is that unit-tests and TDD somewhat obviate the need for images from a development process, and I think other responses indicated that REPL is well handled in Ruby and that the speed issue is well enough handled by using C to provide point optimization where necessary (in clear recognization that certain problems and problem domains would find this insufficient).

Regards.
Nick

TLOlczyk wrote:

···

On Thu, 01 Jul 2004 10:45:54 GMT, gabriele renzi ><surrender_it@remove.yahoo.it> wrote:

It would also be nice to have an optional core/image.
That way if I run tests where testing uses a lot of data,
I can save images when i debug later stages and
save myself some time initializing.
     

I'm not sure what you mean here. Do you want to freeze the interpreter
in a given state? Or do you feel the need for some serialization
format that can be retrieved at any time fast? (in this case Marshal
could fit, maybe?)
   

Sigh. The way things are going today, I've finally gotten to Usenet
today, but on the radio is a very good discussion of the American
Revolution. So I can't pay attention to the whole thread, but
I will discuss this part.

Let us as an example look at a program that looks at a directory of
Web pages, and traces through them. If it cannot find a link to a
certain page, then it creates a link on a page in a prescribed manner.

You've written the program and tested it on a small data set.
Now you want to test it on a large data set. It fails miserably and you try to debug.
Phase one of the program gets a list of all the files in the directory
( recursively ).
Phase two is to scan the root files for hrefs. Then scan the files in
the hrefs. Then ... untill there are no more files to scan.
Phase three is to pick some file you didn't reach and create a link to
it.

So you work on Phase one and get it to run.
Then you work on Phase two. But it takes Phase one
ten minutes to run. So each time you test a fix in phase two
it takes at least ten minutes to run.

So you save an image at the end of phase one. Each time
you test phase two, you load the image from phase one
and just test phase two. Save ten minutes on each test run.

The reply-to email address is olczyk2002@yahoo.com.
This is an address I ignore.
To reply via email, remove 2002 and change yahoo to
interaccess,

**
Thaddeus L. Olczyk, PhD

There is a difference between
*thinking* you know something,
and *knowing* you know something.

If Ruby is 2-6X more productive then Java, wouldn't it make sense for almost all software projects to use full lifecycle prototypes? That is, everything is built in Ruby, completely, and this forms a key part of the specification and requirements feedback for the lagging J2EE /etc. commerical implementation? Are there any cases of this being attempted and are there industry learning/best practices in this regard?

Nick

I get the impression that the J2EE world is starting to go ballastic over Jython. JRuby gets some mention, but not that much, and I get the impression that the long term prospects of JRuby are a bit mixed. For this reason, I felt compelled to learn some Jython so I could use a modern language in my day-to-day J2EE work.

Unfortunatly, I really can't stand using Python. The selfs, method __protection__ mechanism, and lack of expression-orientation (unlike Lisp and Ruby) make me weep. I'm still plinking at it here and there, giving it a chance, but my mindset is not improving, and I'm starting to think Python claims of readability are only relative to Perl- I find Java/C/C++ easier to read. But that's really irrelevant to this point, outside of my personal motivation for looking at JRuby more seriously.

So now I'm trying to use JRuby, and it's much better then I expected. However, I'm still concerned about:
1. it's robustness and how it impacts my chosing to use it, and
2. it's impact on Ruby longterm due to prevalence of Jython. I get the impression that Jython is becoming almost the defacto J2EE scripting language, with Groovy possibly taking off when it's more mature (is it just me, or does Groovy look a lot like a Ruby clone with a bit of Java baggage left in for more seamless interoperability?). Where Jython has followed Python into general usage, that could change with Jython being the reason people use Python.

Not sure what point is...I guess I'm looking for some experiences/ideas/feedback. I think dynamic JVM langauges are going to become an essential part of enterprise Java, and I'm hoping I don't have to use Jython on my next job. Those underscores and selfs- how can anyone stand it? And the lack of expression-kindness.

Thanks,
Nick

Lennon Day-Reynolds wrote:

why would anyone care that you are not using Ruby ?

Perhaps because we would like to see more people using Ruby? Or even
just because the sort of people who use "fringe" languages like Ruby
tend to enjoy discussion of obscure details of implementation and
semantics?

As much as we like that to happen, Ruby is not for everyone.

+ it has many Perlisms (not that it's bad) that many people can't bear.

+ it's purely object-oriented (unlike Python & Perl), thus functional or procedural guys might get offended or turned off.

+ it comes from Japan.

I am guessing that Python will always be more popular than Ruby in general, because the language is more acceptable to many people. However, that's fine. I myself think that the Ruby language is perfect for me. It has the nice balance of practicality and purity. It has a nice syntax. It is pretty popular (unlike, say, Ocaml or Haskell) so it's easier to find libraries or bindings for many things. It simply rocks.

···

--
dave

TLOlczyk a écrit :
(snip)

Let us as an example look at a program that looks at a directory of
Web pages, and traces through them. If it cannot find a link to a
certain page, then it creates a link on a page in a prescribed manner.

You've written the program and tested it on a small data set.
Now you want to test it on a large data set. It fails miserably and you try to debug.
Phase one of the program gets a list of all the files in the directory
( recursively ).
Phase two is to scan the root files for hrefs. Then scan the files in
the hrefs. Then ... untill there are no more files to scan.
Phase three is to pick some file you didn't reach and create a link to
it.

So you work on Phase one and get it to run.
Then you work on Phase two. But it takes Phase one
ten minutes to run. So each time you test a fix in phase two
it takes at least ten minutes to run.

So you save an image at the end of phase one.

What you have to save here is "a list of all the files in the directory"... Which is quite easy to write to/read from file, be it by serialization (ie : marshaling) or in a flat or structured text format - which is amazingly easy with langages like Ruby.

Having played with 'image-based' systems, I can well understand why you like it, but your example may not be that good... !-)

Bruno

OCaml is as dynamic as LISP and some implementations produce native
code that _is_ as fast as C. It's quite amazing.

···

On Fri, 2 Jul 2004 07:12:50 +0900, bruno modulix <onurb@xiludom.gro> wrote:

Robert Klemme a écrit :
(snip)
> And, for real high performance requirements it's likely that Ruby -
> whether compiled to native or whatever - will not reach the mark that can
> be set languages like C and C++. The dynamic nature does cost some
> performance.
Just for the record, Common Lisp is (more or less) as dynamic as Ruby,
and some implementations produce really good and fast native code...
(ok, perhaps not as fast as C !-)
(snip)

bruno

There are several reasons that Common Lisp can achieve much better
performance than Ruby. First and foremost is the fact that Lisp-like
languages in general have been around longer than C, and have been the
subject of extensive work in optimization and native code generation.
Second, CL, while being value-typed in a fashion similar to modern
scripting languages, also supports type annotations, which allow the
compiler to generate more efficient code for critical sections.

Performance has much less to do which language selection than it does
with abstraction and algorithm selection. Some languages (like C) are
excellent for manipulating data at the level of individual pointers
and registers, but require a great deal of infrastructure to approach
the productivity of higher-level languages. If you were to write C
code that emulated the Ruby object model, it would likely run in
approximately equivalent time.

Lennon

···

On Fri, 2 Jul 2004 07:12:50 +0900, bruno modulix <onurb@xiludom.gro> wrote:

Robert Klemme a écrit :
(snip)
> And, for real high performance requirements it's likely that Ruby -
> whether compiled to native or whatever - will not reach the mark that can
> be set languages like C and C++. The dynamic nature does cost some
> performance.
Just for the record, Common Lisp is (more or less) as dynamic as Ruby,
and some implementations produce really good and fast native code...
(ok, perhaps not as fast as C !-)
(snip)

bruno

Hello bruno,

Just for the record, Common Lisp is (more or less) as dynamic as Ruby,
and some implementations produce really good and fast native code...
(ok, perhaps not as fast as C !-)
(snip)

No. You need to use things like (the 'Integer i) all the time, and if
i would call this lisp anymore i don't know.

And even if you go this way, your program will then be as save as a
program in FORTH - or a C program where everything is casted to (void*)

Lisp guys write some routines in this "typed Lisp", rubyist's write
them in "C", so it's not so different.

···

--
Best regards, emailto: scholz at scriptolutions dot com
Lothar Scholz http://www.ruby-ide.com
CTO Scriptolutions Ruby, PHP, Python IDE 's

Take a look also at "Groovy". Much more ruby-ish.
(http://groovy.codehaus.org/\)

···

On Fri, 2 Jul 2004 14:27:09 +0900, Nicholas Van Weerdenburg <nick@activehitconsulting.com> wrote:

I get the impression that the J2EE world is starting to go ballastic
over Jython. JRuby gets some mention, but not that much, and I get the
impression that the long term prospects of JRuby are a bit mixed. For
this reason, I felt compelled to learn some Jython so I could use a
modern language in my day-to-day J2EE work.

Unfortunatly, I really can't stand using Python. The selfs, method
__protection__ mechanism, and lack of expression-orientation (unlike
Lisp and Ruby) make me weep. I'm still plinking at it here and there,
giving it a chance, but my mindset is not improving, and I'm starting to
think Python claims of readability are only relative to Perl- I find
Java/C/C++ easier to read. But that's really irrelevant to this point,
outside of my personal motivation for looking at JRuby more seriously.

So now I'm trying to use JRuby, and it's much better then I expected.
However, I'm still concerned about:
1. it's robustness and how it impacts my chosing to use it, and
2. it's impact on Ruby longterm due to prevalence of Jython. I get the
impression that Jython is becoming almost the defacto J2EE scripting
language, with Groovy possibly taking off when it's more mature (is it
just me, or does Groovy look a lot like a Ruby clone with a bit of Java
baggage left in for more seamless interoperability?). Where Jython has
followed Python into general usage, that could change with Jython being
the reason people use Python.

Not sure what point is...I guess I'm looking for some
experiences/ideas/feedback. I think dynamic JVM langauges are going to
become an essential part of enterprise Java, and I'm hoping I don't have
to use Jython on my next job. Those underscores and selfs- how can
anyone stand it? And the lack of expression-kindness.

Thanks,
Nick

David Garamond wrote:

As much as we like that to happen, Ruby is not for everyone.

...
+ it's purely object-oriented (unlike Python & Perl), thus functional or procedural guys might get offended or turned off.

Um, I don't see this as true. Certainly one can write all the procedural code one likes in Ruby (I know *I've* managed to do it), and I believe the same is pretty much true for writing functional code.

The numerous discussions here comparing Python and Ruby suggest that there is no reason one cannot do functional programming in Ruby at least to the same degree as one can in Python, if not more so.

There are enough previous ruby-talk threads on Python vs. Ruby, so we don't need another one. But while there are numerous reasons people may find Ruby not to their taste, the idea that one is obligated to do OO programming, or held back from doing non-OO development, isn't one of them.

One of the best things about Ruby is you can use OO modeling to get you most of the way through a program's design, then switch to functional or procedural techniques for the last mile.

Or vice versa.

See also:

http://www.ping.de/~flori/ruby/programs/functional.html
http://c2.com/cgi/wiki?FunctionalProgrammingLanguages
http://c2.com/cgi/wiki?PythonVsRuby (look for the discussion on functional programming)

> ...

I am guessing that Python will always be more popular than Ruby in general, because the language is more acceptable to many people.

That almost sounds like begging the question; Python's also more acceptable (to some) because it is more popular. Python may stay more popular because the differences between Ruby and Python are too subtle for most people to care (or too sophisticated for most people to understand), and Python (currently) has the edge on available libraries.

James

actually the python guys would strongly disagree. Python is pure-oo
since v2.2 IIRC

···

il Fri, 2 Jul 2004 16:02:34 +0900, David Garamond <lists@zara.6.isreserved.com> ha scritto::

+ it's purely object-oriented (unlike Python & Perl), thus functional or
procedural guys might get offended or turned off.

I believe Groovy had a greater acceptance than Jython beetween
javaers. The step is simpler from java to grrovy, they have both lots
of {} :slight_smile:

The advantage jython has, imo, over JRuby are:
- time. It existed before
- it has jythonc that allows use to compile to jvm bytecode.

OTOH JRuby is, well, ruby :slight_smile: while the stable jython is a python 2.1,
which is quite updated and inferior, imo, to current python.

PNuts is also interesting in the jvm scripting world

···

il Fri, 2 Jul 2004 14:27:09 +0900, Nicholas Van Weerdenburg <nick@activehitconsulting.com> ha scritto::

OCaml is, as far as I understand, actually much closer to C++ than
CLOS/Ruby/Smalltalk in object model and dynamism. Its object model
supports polymorphism, inheritance, and even parameterization, but
does not really allow redefinition of methods and instance variables
at runtime. In my usual thinking, "dynamic" and "statically typed" do
not often go together.

There's always going to be a certain amount of overhead incurred by
using a "pure", message-based object model. You can either try to
avoid it by having a restricted sub-language that can be turned into
fast native code (Psyco, Objective C, etc.), or by doing runtime JIT
compilation, with its implied assumption that changes to "hotspot"
code will be infrequent enough to make code cache invalidation a minor
cost compared to the savings provided by compilation.

In effect, the current solution for Ruby closely mirrors Objective C,
in that "high performance" code can be written in C (either using
Inline, or as a standalone extension). Personally, now that I'm
familiar with the Ruby C API, I don't really consider it to be that
bad having to drop into another language for performance-critical
code.

Lennon

Carl Youngblood <carl.youngblood@gmail.com> writes:

Robert Klemme a écrit :
(snip)
> And, for real high performance requirements it's likely that Ruby -
> whether compiled to native or whatever - will not reach the mark that can
> be set languages like C and C++. The dynamic nature does cost some
> performance.
Just for the record, Common Lisp is (more or less) as dynamic as Ruby,
and some implementations produce really good and fast native code...
(ok, perhaps not as fast as C !-)
(snip)

bruno

OCaml is as dynamic as LISP and some implementations produce native
code that _is_ as fast as C. It's quite amazing.

It's definitely not as dynamic as Lisp. It's entirely statically
typed: types do not exist at runtime. It has very few facilities for
introspection. The performance of its generated code and garbage
collector crucially depends on its static type system.

Not to say OCaml is a bad language for it. Dynamicity is a very nice
property -- but so is fast code. For me, the trade-off tends to favor
dynamicity, but if it didn't, I would love to use OCaml.

Except the lack of overloading would probably drive me crazy.

  mikael

···

On Fri, 2 Jul 2004 07:12:50 +0900, bruno modulix <onurb@xiludom.gro> wrote:

gabriele renzi wrote:

+ it's purely object-oriented (unlike Python & Perl), thus functional or procedural guys might get offended or turned off.

actually the python guys would strongly disagree. Python is pure-oo
since v2.2 IIRC

Whoa, depends on how you define 'pure-oo'. Maybe they are OO under the covers, but the interface (which has remained backwards-compatible) sure isn't very OO.

Take for example, 'len', it's not a property of Strings or Arrays, it's a function you apply to them to get their length. Same goes for 'map', it's not a property of lists or arrays, it's just a function.

Maybe behind the scenes Integers are now objects, but that sure doesn't make the language seem very 'pure-oo'.

Ben

I know I shouldn't, but I'm going to anyways ...

And even if you go this way, your program will then be as save as a
program in FORTH - or a C program where everything is casted to (void*)

Actually, my Forth (you may use lower case, nowadays) programs are quite
stable. I have much more faith in them than in other compiled programs,
where I don't know what's going on.

Lisp guys write some routines in this "typed Lisp", rubyist's write
them in "C", so it's not so different.

And you usually have a built in assembler available in Forth :slight_smile:

Have a nice weekend, everyone.
s.

···

On Fri, 2 Jul 2004 08:08:01 +0900, Lothar Scholz <mailinglists@scriptolutions.com> wrote:

Carl Youngblood a écrit :

OCaml is as dynamic as LISP

Due to static typechecking, it certainly ain't...

Bruno

James Britt <jamesUNDERBARb@neurogami.com> wrote in message news:<40E586A6.9040301@neurogami.com>...

Um, I don't see this as true. Certainly one can write all the
procedural code one likes in Ruby (I know *I've* managed to do it), and
I believe the same is pretty much true for writing functional code.

"Functional code" is a rather broad term, but one popular feature of
many functional languages is pattern matching[1], which Ruby doesn't
support. Indeed, the entire structure of functional programs is
generally alien enough to OO or procedural languages that any mapping
you could do would be difficult to describe as being functional,
except in the broadest sense.

Procedural and OO languages are very similar. Functional languages
require a different mindset, and I believe that it *is* a stretch to
claim that you can do functional programming in Ruby. Furthermore,
I'd say it would be difficult to do pure procedural programming in
Ruby -- you'd have to redefine most of the API to avoid calling
methods on objects -- however, it could be done.

[1] in the sense of matching the appropriate function based on the
arguments.
Consider the function sum(). Given a recursive procedural definition:

int sum( array ) {
  if ( length( array ) == 0)
    return 0;
  else
    return array[0] + sum( subset( array, 1, length( array ) - 1 ) );
}

In Ruby(procedural) this might be:

sum( array ) {
  return 0 if length( array ) == 0
  return array[0] + sum( subset( array, 1, -1 ) )
}

(being pedantic, and avoiding *all* OO methods). In Haskell, this
code would be:

func = 0
func (x:y) = x + func( y )

Converting the Haskell code to Ruby would give you the same code as
the procedural version (again, if you avoid all of the OO
constructions that you possibly can). I don't think I'd be
exaggerating if I said that, in general, Ruby( procedural ) == Ruby(
functional ), and yet, functonal and procedural programming are
fundamentally different styles.

--- SER