Ruby (programming language): Difference between revisions

From Citizendium
Jump to navigation Jump to search
imported>Pat Palmer
imported>Pat Palmer
Line 48: Line 48:
So-called inner classes in Java and C# may seem remarkably like closures in that they can access information in the surrounding class, but in practice, such inner classes are typically limited to handling events for the enclosing class.  Closures become really powerful when the inner procedure can be referenced (called) from anywhere else in the code, not just from within the enclosing procedure.  This is true in Ruby, and advocates love it.  But before now, use of closures has not been considered required learning for a majority of programmers, to whom they were usually not available anyway.  Knowing when and how to make use of a closure--what it can be good for--is neither obvious nor simple to many.  The Ruby kind of full-fledged closure is alleged to become easier for programmers, eventually, but the learning curve can be steep.   
So-called inner classes in Java and C# may seem remarkably like closures in that they can access information in the surrounding class, but in practice, such inner classes are typically limited to handling events for the enclosing class.  Closures become really powerful when the inner procedure can be referenced (called) from anywhere else in the code, not just from within the enclosing procedure.  This is true in Ruby, and advocates love it.  But before now, use of closures has not been considered required learning for a majority of programmers, to whom they were usually not available anyway.  Knowing when and how to make use of a closure--what it can be good for--is neither obvious nor simple to many.  The Ruby kind of full-fledged closure is alleged to become easier for programmers, eventually, but the learning curve can be steep.   


Ruby programmers need to learn about closures, however.  Closures are accepted as good style in Ruby, and are heavily encouraged.  The often-cited example of a recommended closure use in Ruby is the .each procedure, whose internal design uses a closure and a yield statement.  ".each" provides a more convenient way of iterating through collections than conventional loops.  This particular example fails to convert sceptics of the necessity for closures, because languages such as Java now provide their own extremely simple ways of iterating through collections (i.e., the "enhanced for loop").  After citing the ubiquitous iteration example, closure advocates often struggle to explain, in easily accessible terms, what such uses are.  A famous warning from the seminal 1995 Gang of Four Design Patterns book inevitable comes to mind: ""Dynamic, highly parameterized software is harder to understand than more static software."<ref name="DesignPattern1">{{cite web|url=http://www.awprofessional.com/title/0201633612|title=Design Patterns: Elements of Reusable Object-Oriented Software (page 21)|publisher=Addison-Wesley|year=2007|accessdate=2007-05-24}}</ref>  Even without the full power of Ruby-style closures, allowing scopes within scopes, which is at least part of what a closure does, may be seen as a hazard for unaware programmers.  In a deceptively simple-seeming language such as [[Javascript]], for example, it is not uncommon for programmers to use a variable defined in an outer scope without realizing the consequences of having done so (i.e., the variable will not be started over from scratch each time the inner procedure is called, but will act like a global instead).  This is a common source of bugs in so-called [[Ajax]] applications if there is a need to have multiple Ajax (Javascript) calls going on between a web browser and web server simultaneously.
Ruby programmers need to learn about closures, however.  Closures are accepted as good style in Ruby, and are heavily encouraged.  The often-cited example of a recommended closure use in Ruby is the .each procedure, whose internal design uses a closure and a yield statement.  ".each" provides a more convenient way of iterating through collections than conventional loops.  This particular example fails to convert sceptics of the necessity for closures, because languages such as Java now provide their own extremely simple ways of iterating through collections (i.e., the "enhanced for loop").  After citing the ubiquitous iteration example, closure advocates often struggle to explain, in easily accessible terms, what such uses are.  A famous warning from the seminal 1995 Gang of Four Design Patterns book inevitable comes to mind: ""Dynamic, highly parameterized software is harder to understand than more static software."<ref name="DesignPattern1">{{cite web|url=http://www.awprofessional.com/title/0201633612|title=Design Patterns: Elements of Reusable Object-Oriented Software (page 21)|publisher=Addison-Wesley|year=2007|accessdate=2007-05-24}}</ref>   
 
Even without the full power of Ruby-style closures, allowing scopes within scopes, which is at least part of what a closure does, may be seen as a hazard for unaware programmers.  In a deceptively simple-seeming language such as [[Javascript]], for example, it is not uncommon for programmers to use a variable defined in an outer scope without realizing the consequences of having done so (i.e., the variable will not be started over from scratch each time the inner procedure is called, but will act like a global instead).  This is a common source of bugs in so-called [[Ajax]] applications if there is a need to have multiple Ajax (Javascript) calls going on between a web browser and web server simultaneously.
 
On the other hand, the fact that unaware programmers may hang themselves due to the complexity of closures is not, perhaps, a compelling argument against Ruby.  Advocates claim the added power and elegance of design is worth the risk.  It is likely that the presence of true closures in the Ruby language attracts many programmers, while repelling others.


===Permissive syntax===
===Permissive syntax===

Revision as of 13:07, 11 October 2007

Main Article
Talk Template:Default button 3
 
Template:Cell style

Ruby is a general-purpose computer programming language made available as an open-source project in 1995 by its creator, Yukihiro Matsumoto (commonly called Matz), a Japanese computer professional with experience in open-source software and familiarity with a wide variety of programming languages. Matz has closely managed Ruby releases in the years since it first appeared, and by 2007, Ruby has been ranked tenth in usage among all programming languages. Furthermore, its use is still growing[1].

In 2004, Ruby's place in the U.S. computer industry was boosted by the independent release of Rails, a Ruby-based, open-source web application framework created in the United States by David Heinemeier Hansson, a Danish developer. This article is an overview of several often-cited Ruby characteristics, independent of Rails, for which the language is sometimes both praised and criticized.

Ruby Implementations

Like many "newer" programming languages (meaning those created or updated since 1990), Ruby is fully object-oriented and requires the installation of a runtime environment, or virtual machine before Ruby programs can be developed or run.

As of October 2007, ever-improving versions of the official open-source Ruby implementation have been released on several different operating systems. These runtimes are interpreted, rather than compiled, and thus Ruby is not yet considered to be a high-performance platform suitable for some heavy-load, enterprise applications. Ruby implementations have also been developed by other groups, including JRuby (an attempt to port Ruby to the Java platform), and Rubinius (an interpreter modeled after self-hosting Smalltalk virtual machines).

As of 2007, no formal written specification has been provided for validating Ruby implementations. So although Ruby can potentially can be used to create platform-independent programs, Ruby is not currently guaranteed to be identical across platforms, and newer versions are not always upwardly compatible with older versions. Furthermore, a burgeoning number of books, articles and other documentation are not always in complete agreement about the syntax, semantics, and conventions of the language. There is widespread agreement that Ruby would benefit from having a formal specification.

Things people like (and hate) about Ruby

Despite performance and cross-version and compatibility concerns, enthusiasts of Ruby wax eloquent in praising the language, including numerous subjective statements such as "it's fun". Something of Ruby's appeal may be seen in the brevity of this Hello World program:

puts "Hello, world"

But simple as it initially may seem, Ruby is described as having hidden depths, largely as a result of its support for a complex and powerful feature called closures. Peter Cooper, author of a 2007 book about Ruby, introduces the language by stating, "Ruby has more in common with more esoteric languages such as Lisp and Smalltalk than with better known languages such as PHP and C++"[2]. Cooper's book, and numerous other sources, list several characteristics of Ruby that may allow programs to be written with more ease, speed and "joy", than with other languages, including:

  1. closures
  2. a relatively permissive syntax, said to be more like the way people think and talk
  3. loose typing
  4. good string handling and regular expressions
  5. extensive libraries for networking and web services
  6. powerful support for making calls out to the native operating system if needful

Closures

A full discussion of closures deserves an article of its own but probably cannot be avoided in any serious discussion of Ruby. Closures are a powerful and complex feature, implemented in their most flexible form in only a few programming languages such as Smalltalk (and Ruby). With all the precision and politeness ubiquitous in the industry, even the definition of what constitutes a closure has been hotly debated.

Closures occur when a procedure (or a so-called block--an unnamed procedure) is physically situated inside another procedure, and the inner procedure can be referenced (called) from outside of the enclosing procedure. This is another way of saying that (at least usually), procedures may not live inside other procedures, which is mostly true in languages such as C, C++, Java or C# which implement local variables using stack frames. If procedures are nested, a so-called closure will occur if the inner procedure is allowed to access variables declared outside itself but within its enclosing procedure. In some languages, the inner procedure can only read the variables in the enclosing scope, whereas in others (such as Ruby), the inner procedure can also change the variables which are outside itself but still in the enclosing procedure.

So-called inner classes in Java and C# may seem remarkably like closures in that they can access information in the surrounding class, but in practice, such inner classes are typically limited to handling events for the enclosing class. Closures become really powerful when the inner procedure can be referenced (called) from anywhere else in the code, not just from within the enclosing procedure. This is true in Ruby, and advocates love it. But before now, use of closures has not been considered required learning for a majority of programmers, to whom they were usually not available anyway. Knowing when and how to make use of a closure--what it can be good for--is neither obvious nor simple to many. The Ruby kind of full-fledged closure is alleged to become easier for programmers, eventually, but the learning curve can be steep.

Ruby programmers need to learn about closures, however. Closures are accepted as good style in Ruby, and are heavily encouraged. The often-cited example of a recommended closure use in Ruby is the .each procedure, whose internal design uses a closure and a yield statement. ".each" provides a more convenient way of iterating through collections than conventional loops. This particular example fails to convert sceptics of the necessity for closures, because languages such as Java now provide their own extremely simple ways of iterating through collections (i.e., the "enhanced for loop"). After citing the ubiquitous iteration example, closure advocates often struggle to explain, in easily accessible terms, what such uses are. A famous warning from the seminal 1995 Gang of Four Design Patterns book inevitable comes to mind: ""Dynamic, highly parameterized software is harder to understand than more static software."[3]

Even without the full power of Ruby-style closures, allowing scopes within scopes, which is at least part of what a closure does, may be seen as a hazard for unaware programmers. In a deceptively simple-seeming language such as Javascript, for example, it is not uncommon for programmers to use a variable defined in an outer scope without realizing the consequences of having done so (i.e., the variable will not be started over from scratch each time the inner procedure is called, but will act like a global instead). This is a common source of bugs in so-called Ajax applications if there is a need to have multiple Ajax (Javascript) calls going on between a web browser and web server simultaneously.

On the other hand, the fact that unaware programmers may hang themselves due to the complexity of closures is not, perhaps, a compelling argument against Ruby. Advocates claim the added power and elegance of design is worth the risk. It is likely that the presence of true closures in the Ruby language attracts many programmers, while repelling others.

Permissive syntax

Loose typing

Strings and regular expressions

Networking, including web services

Calling into the OS

References

  1. "TIOBE Programming Community Index". TIOBE Software (2007). Retrieved on 2007-10-10.
  2. "Beginning Ruby: From Novice to Professional". Apress paperback book, Introduction p. xxix (2007). Retrieved on 2007-10-10.
  3. Design Patterns: Elements of Reusable Object-Oriented Software (page 21). Addison-Wesley (2007). Retrieved on 2007-05-24.