So, you want to learn few scripting and dynamically typed language(s) for the Java platform? The following will get a Java programmer started with Groovy and (J)Ruby. It is said that you can write Fortran in any language! While you still have to learn language specific idioms, naming, coding conventions/styles etc., the table below would help you with "quick start". To reiterate: you need to pick up language specific idioms as Reg Braithwaite notes in his comment below.
I wrote simple script samples and tried the same with command line
wrappers of jrunscript. If
you CVS checked out script engines from
scripting.dev.java.net, these scripts are in
bin directories of respective script
engine directories. I used Groovy 1.0 JSR 06 and JRuby 0.9.0 versions respectively.
| Feature | Java | Groovy | JRuby |
|---|---|---|---|
| Type System | Static with few dynamic checks inserted as needed. | Dynamic, optional static types | Dynamic | Comments |
|
|
|
| Control Statements |
* break can be used in
loops to break out of loop. * continue statement skips the current iteration of a for, while, or do-while loop and valuates the boolean expression that controls the loop. |
* do.. while
is not supported. * for (init; condition; increment) is not supported. * null is treated as false. Truth value special cases for data structures. * Unlike Java, switch statement works for arbitrary expressions (not just for integral expressions and enums as in Java). isCase method is used on objects. * Labeled break and continue are not supported (yet?) |
* nil is treated as false. C/C++ Trap: 0 is true!
* break terminates loop immediately. * redo immediately repeats w/o rerunning the condition. * next starts the next iteration through the loop. * retry restarts the loop, rerunning the condition. |
| String Literals | "hello world" |
|
|
| Class Declaration |
|
|
|
| Instance Variables |
|
Same as Java or you can omit types.
Think "def" means java.lang.Object!
John Wilson notes that 'def' is really untyped. If I declare a variable as being of type Object it is not 100% the same as 'def'ing it. Please refer to his comments below.
|
instance variable names start with '@'
|
| Static Variables |
|
Same as Java or you can omit types.
Think "def" means java.lang.Object!
John Wilson notes that 'def' is really untyped. If I declare a variable as being of type Object it is not 100% the same as 'def'ing it. Please refer to his comments below.
static def i; static def f; static def d; static def s; static k; |
Static variable names start with '@@'
|
| Global Variables | Not supported. Use public static final variables in a class or use enum as appropriate. | Top-level variables are supported. No special naming enforced. [Actually, these are contained in "Script" class - which contains all "global" definitions] |
Has to start with "$"
|
| Method Definition |
|
|
|
| Static Method Definition |
|
|
use className.methodName as method name.
|
| Returning from a method |
|
Same as Java. But can leave the return statement - in that case the last expression evaluated is returned. | Same as Java. But can leave the return statement - in that case the last expression evaluated is returned. |
| Object Creation |
|
|
'new' is a method in Ruby!
|
| Method Call |
|
can omit parans in some cases
* If no arguments, need to use parans* Parans can be omitted only for method calls in top-level statements Example:
|
can omit parans in some cases
|
| Static Method Call |
|
* If no arguments, need to use parans* Parans can be omitted only for method calls in top-level statements Example:
|
|
| Object Initialization |
|
|
|
| Referring to the current object | this | this | self |
| Null | null |
null - Guillaume Laforge notes that "Null Object Pattern" is supported in Groovy. See also: NullObject.
So, you can call null.toString() for example.
|
nil -
but "nil" is a proper object. So, methods
can be called on it without getting NullPointerException.
|
| Arrays |
|
|
|
| Array Literals |
|
Note that Groovy has List literals (represented
by a java.util.List instance). The following
list literal syntax can be used.
|
|
| RegEx Literals | Not supported. Regular Expressions are specified as Strings. |
/pattern/
Note from Guillaume Laforge: The "slashy" string syntax creates strings, in fact, it's not a regular expression per se, but it allows one to avoid to have to escape each and every character as it's the case in Java. But, this syntax doesn't really create some kind. Thanks! |
/pattern/ |
| Hash Literals | Not supported |
|
|
| varargs methods |
Use JDK 1.5+. The "..." after the last formal
argument means this is a vararg method.
|
Declare the last argument of the method as an array
with that Groovy packs "excess" arguments in method
call into that array argument
|
|
| Keyword arguments (a.k.a Named Parameters | Not supported |
Not directly supported. But hash literals can be
passed as an argument. When passing a hash literal
as an argument, the "[" and "]" chars can be omitted.
|
Not directly supported. But hash literals can be
passed as an argument. When passing a hash literal
as an argument, the "{" and "}" chars can be omitted.
|
| Operator Overloading | Not supported - except for built-in String + operator |
Special methods are defined in the class to overload
operators. For example, "plus" to overload "+".
|
Method names can be operators. Also, when calling
operator methods, you need not say obj.methodName.
instead you say obj methodName param1. But, you
can use usual method call syntax as well.
|
| Extending another class |
|
|
|
| Referring to super class method | super.foo(); | super.foo(); |
Unlike Java and Groovy, super
keyword calls the super class method of the currently executing
method. You are not calling arbitrary super method.
|
| Nested, inner and anonymous classes |
|
* Nested and inner classes are not supported (yet?). * Local and anonymous classes are not supported (yet?) But, we can use closures
|
From what I read, nested class is possible but
not "inner" classes. Please correct me if I am
wrong!
|
| Closures |
* Not yet part of Java. But, may become! * Nominal Closures for Java (version 0.2) * Full Disclosure * For now, use local and anonymous classes
|
For detailed explanation, refer to
Closures in Groovy
|
* Blocks must follow a method invocation. * Proc objects can be created by Proc.new or proc method (in Kernel).
For detailed critic, refer to
closures-in-ruby.rb
|
| Exception Handling |
|
Exception handling is same as Java - except that declarations of exceptions in method signature are optional - even for checked exceptions. |
In addition, there is another way to do non-local
jump:
The catch is searched by symbol (symbol is an
internalized string).
|
| Modules, Namespaces |
There may be
future
improvements in this area.
|
Same as Java |
require is like import.
There is also load -
but unlike "require", "load" loads the file everytime
when called (i.e., require loads and caches - subsequent
require on the same file is a no-op).
|
| Mixins | Not supported. |
Mix-in categories can be used. But, there seems to
another Mixin
proposal as well.
Guillaume Laforge notes that the @Property notation (striked above) is not needed anymore and will be forbidden in the RC-1 release. See also Groovy Beans
|
|
| Accessing Class object | obj.getClass(); | obj.class // or obj.getClass() | obj.class |
| Constructing object using reflection |
|
Same as Java - except that not forced to handle exceptions |
|
| Calling a method using reflection |
|
|
|
Posted by stotti.blog() on September 18, 2006 at 02:13 PM IST #
Rubyists generally prefer to iterate over collections using each, collect, inject and other methods mixed in by the Enumerable module.
Class methods are not really static methods. For example, Ruby class methods are polymorphic. The syntax given works, but most Rubyists use:
class << self def some_class_method_name ... end def another_class_method_name ... end endPosted by Reg Braithwaite on September 18, 2006 at 07:08 PM IST #
Posted by A. Sundararajan on September 18, 2006 at 07:19 PM IST #
Posted by Gary Furash on September 18, 2006 at 07:20 PM IST #
Posted by A. Sundararajan on September 18, 2006 at 07:51 PM IST #
Posted by John Wilson on September 18, 2006 at 08:54 PM IST #
You wrote:
switch (target) { case constant_expr:while this is basically right, the expression there does not have to be a constant expression. It could be a range, a class, regexpr or anything else, that supports an isCase method. For exampleswitch ("foo") { case String: println "it is a string" case /.+/: println "it matches a regexpr" case {it.length()==3}: println "it has a length of 3" }should print out all 3 comments.Then global variables... we define classes and scripts in groovy, where classes is what you introduce with the class expression and scripts is anything else. Global variables are in fact more a Hashmap named Binding. Each script can have one, mulitple scripts can share the same binding and via MetaClass also "normal" classes can have them without using any extra syntax. But having a script and a class sharing a binding is uncommon.
Then for Closures, it is not on the page, and maybe little known, but the closures parameters can also have a type. The type is checked at runtime, so you get no "type savety in the java way" from it, but it allows you to add an additional runtime check. For example you can have a String[] as parameter and the closure then takes any arbitary number of Strings as parameters.
Next is for hash literals. def m = [foo:bar] creates a map and uses the String "foo" as key for whatever bar is and saves the map in m. Then you can not only do m["foo"], you can also do m."foo" or simply m.foo.
Modules and Namespaces... Groovy does have the "import foo.Bar as foobar" syntax. Meaning that the class foo.Bar is now known as foobar.
Ah, yes, array literals... Groovy does have list literals, yes, but you can do to get an array of ints.
Next is Mixins... what Groovy has is.. I would call it runtime mixins. Yes there is another proposal and Groovy will have an implementation of that on the AST level for 1.0, but there wil possibly no syntax right now. Grails will then use the mixins as additional compiler phase.
Then.. "Calling a method using reflection". Thanks to duck typing I can use p.getName("Sundar"). I don't recommend the usage of invokeMethod in this case.
And one last thing maybe.. you can use Strings and Gstrings not only as normal Strings, but also for method, property or field names.
def printMethod = "println" System.out."$printMethod"("I am using a print method customized through a GString")Oh, and maybe you should think about adding "builder" to the page as well? But well, I am sure, there are more missing elements. but this is not thought as complete overview, just a quick start ;)Posted by Jochen Theodorou on September 18, 2006 at 10:30 PM IST #
Posted by Lawrence Oluyede on September 18, 2006 at 10:32 PM IST #
Posted by Christian Caldeiro on September 18, 2006 at 11:16 PM IST #
java: 1.0 is a double.
System.out.println(1.1 + 0.1) -> 1.2000000000000002
System.out.println((1.1 + 0.1) == 1.2)) -> false
groovy: 1.0 is a BigDecimal
println (1.1 + 0.1) -> 1.2
println ((1.1 + 0.1) == 1.2) -> true
ruby: 1.0 is double
puts (1.1 + 0.1) -> 1.2
puts (1.1 + 0.1 == 1.2) -> false
Posted by Scott Hickey on September 18, 2006 at 11:42 PM IST #
Posted by Scott Hickey on September 18, 2006 at 11:53 PM IST #