The Artima Developer Community
Sponsored Link

Java Community News
Why Add Syntax When You Have Ruby?

2 replies on 1 page. Most recent reply: Oct 1, 2006 11:53 AM by Morel Xavier

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 2 replies on 1 page
Frank Sommers

Posts: 2642
Nickname: fsommers
Registered: Jan, 2002

Why Add Syntax When You Have Ruby? Posted: Sep 29, 2006 11:28 AM
Reply to this message Reply
Summary
Developers new to Ruby tend to think that Ruby's conciseness is mostly due to an expressive core API. As Charles Nutter shows in a recent blog entry, however, Ruby's elegance is to a similar extent due to its flexible grammar, keeping high-level features, such as field-initializing constructors, void of syntactic sugar.
Advertisement

In a recent blog entry, Why Add Syntax When You Have Ruby?, Charles Nutter, one of the core JRuby developers shows how Ruby's flexible syntax makes syntactic sugar in API-level features unnecessary.

His example is a result of a discussion about Jython and Groovy syntax, which allow you to instantiate a JLabel as such:

JLabel(text, bounds = bounds, foreground = color)

This syntax is a shorthand in those languages to assign an array of instance variables to the specified set of values. Nutter notes in his blog that JRuby does not provide such a feature, and wonders what it would take to provide similar functionality in JRuby.

First, he notes that equivalent Ruby syntax would look like:

SomeClass.new(text, :bounds => bounds, :foreground => foreground)

Or this:

SomeClass.new(text) { @bounds = bounds, @foreground = foreground }

These versions use the Ruby new method, which is part of every Ruby class, to create a new instance of a class. In this case, text is a parameter defined in JLabel, and, in the second version, the following is a block that assigns the object's instance variables to the specified values.

While these would syntactically work in Ruby, Nutter notes that:

There's no existing accommodation in the semantics of Ruby for these syntax to work out of the box. It would not be hard to write a short bit of code to allow constructing objects in this fashion, of course (using the block approach as an example):

class Class 
  def construct(*baseargs, &initializer)   
    x = self.new(*baseargs)   
    x.instance_eval(&initializer) if initializer   
    x 
  end
end

The above code snippet passes an array argument (*baseargs), and a block argument (&initializer) to the construct method. The base arguments array is passed to the static new method, which is the Ruby way of creating a new instance of a class, and the &initializer block is subsequently evaluated for the newly created instance.

Nutter notes at this point that Ruby's grammar allows an even more concise definition. That's because a Ruby method can dynamically tell if a block was passed as one of the method's arguments. That's done through the block_given? method, which is part of the Kernel module (the Kernel module in Ruby is "mixed into" the Object class, making Kernel methods available anywhere in Ruby code).

In Ruby, the yield keyword will return the block passed into a given context, such as a method. Combining the block_given? kernel method with yield allows Nutter to define the above functionality in a simpler way:

class Class 
  def construct(*baseargs)   
    x = self.new(*baseargs)   
    yield.each_pair { |k,v| x.send("#{k}=", *v) } if block_given?   
    x 
    end
end

The above implementation also takes advantage of the send method, which invokes a method identified by x, passing that method the specified arguments.

Nutter concludes that the above implementation of construct would allow the following syntax in JRuby:

JLabel.construct(text) {{ :bounds => bounds, :foreground =>foreground }}

Here, the outer {} defines a block, and the inner pair of curly braces a hash of initializers.

Nutter concludes that:

The bottom line is that this kind of syntactic sugar in other languages can easily be added to Ruby through various techniques, and so features like field-initializing constructors don't need to be part of the core language or any of the implementations.

Nutter's blog post is a good demonstration of how relatively complex functionality can find a fairly simple expression in a combination of Ruby's syntax and APIs. JRuby promises to bring some of the expressive richness to Java as well. In what areas of your applications would you find this sort of expressivity most helpful?


Daniel Berger

Posts: 1383
Nickname: djberg96
Registered: Sep, 2004

Re: Why Add Syntax When You Have Ruby? Posted: Sep 29, 2006 12:42 PM
Reply to this message Reply
Why not just use Kernel?

module Kernel
def JLabel(*args, &block)
JLabel.new(*args, &block)
end
end

JLabel(text, :bounds => bounds, :foreground => color)

And let JLabel.new handle the arguments, etc.

Regards,

Dan

Morel Xavier

Posts: 73
Nickname: masklinn
Registered: Sep, 2005

Re: Why Add Syntax When You Have Ruby? Posted: Oct 1, 2006 11:53 AM
Reply to this message Reply
Fun thing is, even Matz recognized that Ruby's lack of "true" keyword arguments (à la Python) and tentative emulation via the use of literral hashes was a kludge, which lead to the proposed inclusion of native keyword arguments in Ruby 2.0

Flat View: This topic has 2 replies on 1 page
Topic: Why Add Syntax When You Have Ruby? Previous Topic   Next Topic Topic: Daniel Steinberg on Jini, and How Assumptions Influence Technology Choices

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use