header image

Sometimes less is more
October 19th, 2006

Update: A lot of people were disappointed that 10.minutes.ago etc. is not working in pure Ruby. Well, after executing the line require ‘active_support’ it does - I think this is a fairly small thing to do to enable these powerful features.

Every guide published on favorable writing principles emphasizes the power of brief and concise style. This is especially true in the case of technical texts, and in my opinion, in the case of well-designed programming languages as well.

Note the word well-designed. I did not say in the case of any (programming) language, since that would just not be true: conciseness can come at the cost of readability. (If you ever tried to read kanji, you know what I am talking about ;-) . However, I am claiming that in the case of a really well-designed programming language, succinctness helps readability, reduces bloat and leads to easier and faster understanding of the code. In my experience, the amount of boilerplate code to write is decreasing proportionally with the terseness of the programming language, ultimately leading to a coding style where you (nearly) don’t need to write boilerplate at all.

I will demonstrate this on a few Java vs. Ruby code examples. However, this is NOT a Ruby-bashing-Java article, but a few examples of idioms and interesting constructs; C++ vs Haskell or Lisp could serve equally well (sometimes even better), but since I am currently working with Java and Ruby on a daily basis, it is easier for me to use them.

If you are a pro Ruby and/or Java programmer, and/or you think the article is too long for you, please jump to the “Random Code Snippets” section.

Possibly the most straightforward reason why Ruby code is more readable even in shorter form is that really everything is an object [1] in Ruby-land. For example in Java, primitives need wrapper classes to ‘become’ objects., while in Ruby they are first class objects on their own. This makes constructs like

10.times { print "ho" }  #=> "hohohohohohohohohoho"
or (will output the same string)
print "ho" * 10 #=> "hohohohohohohohohoho"
possible.

There are a handful of other reasons which make Ruby more readable and elegant, but before I get bogged down in the explanation too much, let’s see the examples!

Whetting your appetite

In the first part I will describe some basic constructs which would make the life of any Java developer much easier. These techniques are neat, but they are not using any really sophisticated stuff yet: I will try to take a look at those in the next bigger section.

The empty program

Java:

class Test
{
    public static void main(String args[]) {}
}

Ruby:


I did not forget the Ruby snippet; You can not see anything there because actually a Ruby program doing nothing is exactly 0 characters long. On the other hand, the Java version is slightly longer. I is kind of weird to explain to a newcomer what do ‘class’, ‘public’, ’static’, ‘void’, ‘String’, the [] operator and several braces here and there mean, and why are they needed if the program does literally nothing

Fun with numbers

Note:For some of the next examples you will need to use Rails Active Support.
Java:

if ( 1 % 2 == 1 ) System.err.println("Odd!") #=> Odd!

Ruby:

if 11.odd? print "Odd!" #=> Odd!
Does not the first example make more sense (even for a non-programmer)?. I believe it does. More of this type:
Java:
102 * 1024 * 1024 + 24 * 1024 + 10 #=> 106979338

Ruby:

102.megabytes + 24.kilobytes + 10.bytes #=> 106979338

OK, maybe this is an unfair comparison since Java does not have (?) those functions. However, the point is that even if it had, the best I could come up with would look like:

Util.megaBytes(102) + Util.kiloBytes(24) + Util.bytes(10) #=> 106979338

Which is far from the elegance and readability of the Ruby example.
In the next example we will assume that we have a Java function similar to ordinalize in Ruby.
Java:

System.err.println("Currently in the" + Util.ordinalize(2) + "trimester");

Ruby:

 print "Currently in the #{2.ordinalize} trimester"    #=> "Currently in the 2nd trimester"

In this example we can observe variable interpolation: anything wrapped in #{} inside double quotes gets evaluated and substituted in the string, providing a more readable form without a lot of + + Java constructs (which is cool mainly if you have more variables inside the double quotes).

Dates

In my opinion, handling dates and times is a great PITA in Java, especially if you are implementing some complex code.
Java:

System.out.println("Running time: " + (3600 + 15 * 60 + 10) + "seconds");

Ruby:

puts "Running time: #{1.hour + 15.minutes + 10.seconds} seconds"

Java:

new Date(new Date().getTime() - 20 * 60 * 1000)

Ruby:

20.minutes.ago

Java:

Date d1 = new GregorianCalendar(2006,9,6,11,00).getTime();
Date d2 = new Date(d1.getTime() - (20 * 60 * 1000));

Ruby:

20.minutes.until("2006-10-9 11:00:00".to_time)

I think you do not have to be biased towards Ruby at all to admit which code makes more sense instantly…

I have recently found a very cool way of parsing dates in Ruby: using Chronic. However, I would not like to present it here since it is not a feature of the language, ‘just’ a nifty natural-language date parser [2].

A little bit more advanced stuff

Classes

Java:

Class Circle
  private Coordinate center, float radius;

  public void setCenter(Coordinate center)
  {
    this.center = center;
  }

  public Coordinate getCenter()
  {
    return center;
  }

  public void setRadius(float radius)
  {
    this.radius = radius;
  }

  public Coordinate getRadius()
  {
    return radius;
  }
end;

Ruby:

class Circle
  attr_accessor :center, :radius
end

Believe it or not, the two code snippets are absolutely equal; The getter and setter methods in Ruby code are generated automatically, so not only you do not have to write them, but they are not even there to clutter the code.

I have seen argumentation from Java guys that stuff like this (i.e. the public static void main … thing, getters/setters and other boilerplate code) can be generated with any decent GUI like Eclipse (or by tools like XDoclet etc) is a non-issue. Well, as for their generation, let us say this is true. But for the readability of code it is absolutely not!

For example. take getters/setters: Every variable in Java ads 8 more lines of code (not counting the lines between the function declarations) compared to the Ruby :attr_accessor idiom. That is, a simple class definition having 10 fields in Java will have 80+ lines of code compared to 1 lines of the same code in Ruby. For me, this definitely means a big difference.

Arrays (and other containers)

This section was inspired by a blog entry by Steve Yegge.

Arrays are interesting citizens of Java: They are not really objects in the “classical” sense , so they have very limited functionality compared to first-class Java objects. On the other hand, they are offering a huge advantage over the other container classes: they can be easily initialized.
Java:

String languages[] = new String[] {"Java", "Ruby", "Python", "Perl"};
instead of
List<String> languages = new LinkedList<String>();
languages.add("Java");
languages.add("Ruby");
languages.add("Python");
languages.add("Perl");
which is kind of lame when you quickly need to hack up some testing data.

However, they have also some serious problems: you have to define the number of the elements upon construction time, like so:
Java:

String someOtherLanguages<String>[] = new String[15];
which sometimes really cripples their functionality. [3]

How does this work in Ruby? Let’s see on three different examples (All three code snippets provide the same result):
Ruby:

stuff = [] #An empty array - as you can see there is no need to define the size
stuff << “Java”, “Ruby”, “Python” #Add some elements
#Initialize the array with the values
stuff = [”Java”, “Ruby”, “Python”]
#Yet another method yielding the same result
stuff = %w(Java Ruby Python)

In my opinion, these forms (especially the last one) are more straightforward and can save a lot of typing.

Another major shortcoming of Java arrays is that besides the [] operator you have only the methods inherited from Object and a single instance variable : length [4]. This means that even essential functionality like sorting, selecting elements based on something etc. has to be done via a ‘third party’ function, like this:
Java:

Arrays.sort(languages);
which seemed quite normal to me when I have been learning Java and have had no previous experience with dynamic languages, but now it looks kind of annoying.

Another Java-container-woe compared to Ruby is that in Java, an array is an array. A list is a list. A stack is a stack. If you are wondering what the hell I am talking about, check out these Ruby code snippets: Ruby:

stuff = %w(Java Ruby Python)
#Add the string “Perl” to the array
stuff << “Perl”
#Prepend the string “Ocaml” 
stuff.unshift “Ocaml”  
=> [”OCaml”, “Java”, “Ruby”, “Python”, “Perl”]
#Use the array as a stack
stuff.pop 
=> “Perl”  #stuff is now [”OCaml”, “Java”, “Ruby”, “Python”] 
stuff.push “C”, “LISP”
=> [”OCaml”, “Java”, “Ruby”, “Python”, “C”, “LISP”]
#Update C to C++ 
stuff[4] = “C++”
=> [”OCaml”, “Java”, “Ruby”, “Python”, “C++”, “LISP”]
#Remove the fisrt element
stuff.shift
=> “OCaml” #stuff is now [”Java”, “Ruby”, “Python”, “C++”, “LISP”] 
#Let’s just stick with Java and Ruby - slice out the  rest!
stuff.slice!(2..4)
=> [”Python”, “C++”, “LISP”] #stuff is now [”Java”, “Ruby”]
As you can see, the Ruby Array class offers functionality that could be achieved only by mixing up several Java containers into one (to my knowledge, at least) [5]. In practice, this usually speeds things up a lot.

Another thing that really annoys me when using containers in Java is the lack of this functionality:
Ruby:

stuff = ["OCaml", "Java", "Ruby", "Python", "C++", "LISP"]
#Lua is just gaining steam, add it to the 7th place
stuff[7] = “Lua”
=> [”OCaml”, “Java”, “Ruby”, “Python”, “C”, “LISP”, nil, “Lua”]
i.e. that if I am adding an element to an index which is bigger than the size of the array, the empty space inbetween is filled with nils. Now seriously, who would not exchange this for the Java behaviour (an IndexOutOfBoundsException is thrown) - after all, if I would need this functionality (which is VERY seldomly the case) in Ruby, I could check it myself and raise an exception if I don’t like what I see.

I wanted to write a bit about differences between hashes and files in Ruby and Java, but the post is already longer now then I wanted it to be so I guess I will just show some concrete code snippets to conclude.

Random Code Snippets

In this section I would like to present some real cases I have been solving with Ruby recently. Since I am still new to Ruby, I was totally amazed just how much more simpler, shorter yet much more understandable the code can be in Ruby compared to Java.

Files and Regular Expressions

As Bruce Eckel once put it, In Java, it’s a research project to open a file. Well, I have to agree. Maybe I am the only one Java programmer (besides Bruce) who - even after using Java professionally for five years - still can not write to a file without using google first. Maybe I should learn it one day?

Regular expression support in java is OK (at least one does not have to use external packages as in the pre-1.4 era), however, compared to Ruby the syntax is quite heavy.

Let’s see a demonstration on the following task: Open the file ‘test.txt’ and write all the sentences to the console (one sentence per line) which contain the word ‘Ruby’. First, the Java solution:
Java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test 
{
    public static void main(String[] args)
    {
        try {
            BufferedReader in = new BufferedReader(new FileReader("test.txt"));
            StringBuffer sb = new StringBuffer();
            String str;
            while ((str = in.readLine()) != null) 
              { sb.append(str + "\n"); }            
            in.close();
            String result = sb.toString();
            Pattern sentencePattern = Pattern.compile("(.*?\\.)\\s+?");
            Pattern javaPattern = Pattern.compile("Ruby");
            Matcher matcher = sentencePattern.matcher(result);
            while (matcher.find()) {
                String match = matcher.group();
                Matcher matcher2 = javaPattern.matcher(match);
                if (matcher2.find())
                    System.err.println(match);
            }
        } catch (IOException e) 
          {
            e.printStackTrace();
          }     
    }
}
It is quite straightforward what this relatively simple code snippet doing - but if this is straightforward, what should I say about the Ruby version?
Ruby
File.read('test.txt').scan(/.*?\. /).each { |s| puts s if s =~ /Ruby/ }

Well, umm… I guess this example quite much expresses the point I am talking about from the beginning: sometimes less is more, a.k.a. Succinctness is Power!

Again, I wanted to show much more examples, but I have the feeling that since the article is already too long, no one would read it :-) It is a big pity since I did not even talk about hashes, blocks, closures, metaprogramming (well, I will mention it briefly in the last (really :-) ) example) and other goodies - maybe in part 2?

If this is still not enough…

Although I find it very easy and natural to express a lots of things in Ruby, the language can not offer anything I would ever need. However, there is a powerful concept to invoke in such situations, called metaprogramming.

A few days ago I needed to test some algorithms on trees, so I needed to hack up a lot of tree test data. Here is how I would go about this in Java using the example below (let’s assume in both languages that we have a simple data structure Tree):

               a
            /      \
          b         c
         /  \      / | \
        d    e    f  g  h

Java

Tree a = new Tree("a");

Tree b = new Tree("b");
Tree c = new Tree("c");
a.addChild(b);
a.addChild(c);

Tree d = new Tree("d");
Tree e = new Tree("e");
b.addChild(d);
b.addchild(e);

Tree f = new Tree("f");
Tree g = new Tree("g");
Tree h = new Tree("h");
c.addChild(f);
c.addChild(g);
c.addChild(h);

Another possibility would be to create an XML file with the description of the tree and parse it from there. This solution is even more convenient since though you have to write the parsing code, you just have to edit an XML file once it is written. One possibility how the tree of this example could look something like
XML

  <node name="a">
      <node name="b">
          <node name="d"/>
          <node name="e"/>
      </node>
      <node name="c">
          <node name="f"/>
          <node name="g"/>
          <node name="h"/>
      </node>
  </node>

The latter solution is quite cool. After all you do not need to write any code, just alter the XML file and that’s it.

Now let’s see the Ruby solution I came up with:
Ruby

tree = a {
            b { d e }
            c { f g h }
          }

Well… suddenly even the XML file seems too heavy, does not it? :-) Not to mention the fact that the latter example is pure Ruby code - there is no need to open an external file and parse it - you just run it and the variable tree will contain your tree. That’s it.

Of course Ruby can not handle this code as it is - for this we need to invoke some metaprogramming magic. [6]

Metaprogramming is a way to drive Ruby with Ruby. Java (especially J2EE) is usually driven by XML (which is not always really a good thing in my opinion) As you could see, Ruby is driven by Ruby instead :-)

This example merely scratched the surface of Ruby’s possibilities through metaprogramming. However, as with the other examples, my goal was not to advocate a concrete pattern/method over a different one, but rather to show how a specific toolset can change the way of thinking about the task at hand, and the way of code design/implementation in general.

Final thoughts

When I was a child, I spoke as a child, I understood as a child, I thought as a child: but when I became a man, I put away childish things. - The Bible, I Corinthians 13:11

This thought pretty well expresses how I felt about Java/C++/(substitute any non-dynamic language here) when I came to know (some of) Ruby’s true dynamism and expressive power through terse yet powerful idioms which transformed my whole thinking about programming. Of course I do not claim that I ‘became a man’ because that’s still a very long way to go, but still, even with my very limited knowledge of Ruby, the way to express things in Java/C++ now seems… well… childish ;-) . [7]


Creating a site on online tutorials is not a completely bad idea. One should include courses for 642-054, 642-054, 642-176, ruby on rails, cissp certification. If you have the knowledge for creating the tutorials, the rest is very simple. By using dot5hosting company’s site you can purchase a web hosting package that is economical. Even dedicated servers can be found for low prices. Then through the use of ip telephony one can directly reach its potential clients. Other internet marketing methods should also be considered to create awareness the site.


Notes

[1] I wonder whether this déjà vu will happen to me in the future once again: I have had this ‘Wow, everything is an object’ feeling when coming from C++ to Java; Then after coming from Java to Python; and most recently, after coming from Python to Ruby. Back


[2] Some examples that Chronic can handle:
  summer
  6 in the morning
  tomorrow
  this tuesday
  last winter
  this morning
  3 years ago
  1 week hence
  7 hours before tomorrow at noon
  3rd wednesday in november
  4th day last week
Kudos… Back


[3] In the previous array initialization example this was not needed since it is trivial when all the elements are stated beforehand.Back


[4]which somewhat confusing given that all the other containers use the method size() (and not a field!) to determine the count of elements. To nicely mesh with the confusion, the String object provides the method length() (and not a field, as with array) to query the number of characters… Back


[5] I mean it is not possible to construct any container - other than an array - with literals, you can use the [] operator on arrays only, you can not get the i-th element of a stack etc. Back


[6] The code I have been using to accomplish this task relies on the method_missing idiom:
class Object
  @stack = []
  @parent = nil

  def method_missing(method_name, *args, &block)
    tree = Tree.new(method_name)
    @parent.add_child(tree) if @parent != nil
    if block_given?
      @stack ||=[]
      @parent = tree
      @stack.push @parent
      yield block
      @stack.pop
      @parent = @stack.last
    end
    tree
  end
end
Back


[7] This does not necessarily mean that Java is bad and Ruby is good - just that it was the ‘Ruby way’ that struck a chord in me after trying/playing around with programming in many programming languages. Many of the features I adore in Ruby are there in Java as well, but they did not ‘came through’ whereas with Ruby there was a point of enlightenment when I really understood a lot of generic, non-language specific principles. Back
tags:

If you liked the article, subscribe to the rubyrailways.com feed!  


      

63 Responses to “Sometimes less is more”

  1. Anonymous Says:

    Sometimes less is more…

    “Interesting review of some Ruby vs Java idioms, with source code. More problems are solved with both languages for comparison. One of them is pretty funny: it requires 25+ lines of Java code (can you shrink it in a meaningful way?), and 1 line of Rub…

  2. warpedvisions.org » Blog Archive » Ruby: less is more Says:

    […] October 19th, 2006 in Links Sometimes less is more, a comparison of several Java and Ruby constructs. […]

  3. Anonymous Says:

    Sometimes less is more…

    Review of some Ruby vs Java idioms, with source code. More problems are solved with both languages for comparison (to show how much Ruby rocks! :-) ….

  4. Jochen "blackdrag" Theodorou Says:

    Most Ruby code in this article runs nearly 1:1 in Groovy. I think that is very funny, because many people say that Groovy looks too much like Java… wouldn’t that mean that Ruby does look too much like Java too? Anyway, the tree example would have to be changed a little in Groovy:

    tree = a {
    b { d; e }
    c { f; g; h }
    }

    which gives them a little different meaning than in the Ruby version, but the result would look the same.

    For all not knowing it, Groovy is a dynamic language working on the JVM with very good integration in Java, closures, meta programming, operator overloading, native syntax for lists, maps, BigInteger/BigDecimal and much more http://groovy.codehaus.org

  5. Peter Says:

    Maybe a stupid question, but how are Groovy and JRuby related? I don’t mean technically but whether the functionality they offer makes them competitors or they serve a different purpose, or … ?

  6. Chris Says:

    102.megabytes + 24.kbytes + 10.bytes #=> 106979338

    Where exactly do these methods (and ordinalize) come from? I don’t recall them being part of Ruby’s standard library, and indeed, if you fire up irb, they’re not there. Perhaps these are specific to Rails?

  7. John Wilson Says:

    Peter:

    JRuby is an attempt to implement the whole Ruby language on the JVM. So it’s like Jython in that respect. The advantage is that programmers who understand the Ruby idioms can apply them to the JVM. The disadvantage is that it sufferes from a degree of “impedance mismatch” when interfacing to Java APIs (e.g. selecting between methods with the same name and number of parameters but with different parameter types when making a method call).

    Groovy is a language specifically designed to run on the JVM and to interface tighly with Java libraries. The advantage is that Groovy can easily call Java APIs and can expose APIs which are directly callable from Java. Groovy supports optional typing of variables and Groovy compiles to bytecode (JRuby does not compile to byecode yet but they plan to in the future). The disadvantage is that you have to learn a new language (although if you know java it’s pretty easy to get started) and you can’t apply your language knowlege outside the JVM.

    So Groovy does not compete with Ruby outside the JVM.

    Disclosure: I’m a Groovy comitter. I joinded the Groovy project 3 years ago because I wanted a dynamic language on the JVM and I didn’t like the Ruby Perlishness. (and I still don’t like Ruby’s Perl influences!)

  8. Peter Says:

    @Chris:
    The section “Fun with numbers” begins with the line:

    “Note: For some of the next examples you will need to use Rails Active Support.”

    My goal was to show the “5.do_something” syntax on interesting examples, and I have thought the functions I have used were more self-explanatory and interesting than say 5.step or 5.round.

  9. Thomas Enebo Says:

    Just as an extra data point in addition to John Wilson’s contrast between JRuby and Groovy and the blog entry in general.

    The original article shows two aspects when comparing Java and Ruby:
    1. Disparity between syntactical/language features (pure OO, blocks, misc convenience syntax)
    2. Library comparison (Ruby library has these features Java is lacking)

    JRuby and Groovy help in both these areas for a Java programmer. For 2 in particular:
    -Groovy has made a bunch of additional helpful libraries
    -JRuby leverages Ruby’s existing libraries (and we are starting to also create our own helpful libraries where it is not solved by a Ruby library)

    -Tom
    JRuby Core developer

  10. Ricky Clarkson Says:

    I didn’t like the Java versions of these, so I rewrote them myself, with a few other general comments too.

    See http://rickyclarkson.blogspot.com/2006/10/fairer-brevity-comparison-between-ruby.html

    Cheers. I wish more of the Ruby examples hadn’t needed external libraries, I wanted to see 20.minutes.ago run! I’m not a Ruby developer, just happen to have it installed via Cygwin.

  11. peter Says:

    @Ricky:
    Nice article. I liked the “Peter Szinek, who appears to like being photographed with camels” part the most :-) 10.times { ROTFL } I knew I should have put there my picture where I am posing in my Armani suit so I would look more professional. Too late now.

    About the rest: Some very good points and some I would argue with. However, my goal is not to argue at all, because the point of my post was something different.

    The thing is that the title of my article was neither ‘Java can not be forced to do things that are natural in Ruby’ nor ‘How to golf Java code to reduce it’s size’ or
    ‘Simulating Ruby idioms with weird external Java packages’.

    I think my examples reflect the way a typical Java/Ruby programmer would try to solve such a problem on a typical workday, and that was what I wanted to show.

    It is not likely that Java Joe will go to google code search to find a function that repeats a string n times. The other problem is that this does not change the fact that 20 is not an object in Java. Besides this, his method will work for strings only, while in Ruby ‘times’ accepts a custom block. That’s a big difference.

    OK, anyway, as I said I don’t want to argue too much. I did not want to bash Java - I just blogged about that I like the “Ruby way” more. We are different, and Ruby (or Java) is not for everyone - and this is very good so.

  12. Kevin Says:

    I really have to agree with the properties area. C# improved over Java but the Ruby example made it a lot easier for simple properties. Of course most of my GET methods return something simple but my SET methods might perform various actions which was not addressed here.

    My point being - I wish Java had a better property syntax instead of the forced separate Get / Set methods

  13. Ricky Clarkson Says:

    I know what you mean about the block, and I don’t doubt your points, I just thought it was slightly unfair. My guess is that your Ruby code was better than your Java code, though it’s only a guess, as I don’t know Ruby.

    The block thing is why I am interested in functional programming in Java, so I can do things like (generics with [] because there is no preview button):

    public static [T] T times(Block[T] block,int reps,Function[Pair[T,T],T] combinator)
    {
    }

    Block defines a single method, T run(), and Function[T,R] defines a single method, R run(T input);

    Then that can be called as, imagining Java had closures already:

    times({”ho”},10,(pair){pair.first()+pair.second()});

    Without closures, I tend to do things like make an anonymous class and assign an instance of that to a local variable; works well for me:

    Block[String] ho=new BlockString
    {
    public String run()
    {
    return “ho”;
    }
    };

    etc., then times(ho,10,concat);

    I know Java’s far from ideal for this, but it’s what I know best, what I get paid for, and apart from not supporting tail recursion optimisation, it is ‘just enough’ for functional programming. Haskell’s syntax still scares me, even though the concepts make a lot of sense. Probably sometime I’ll view Haskell’s syntax as the logical next step, and the result of the closures debate for Java will probably help me decide whether to stick or twist!

    “nor ‘How to golf Java code to reduce it’s size’ “

    I considered calling it Ruby and Java golf ;)

    The camel thing was cool, when I find a picture of me doing salsa dancing without looking really sweaty, I’ll probably use that. I only looked at that page because I couldn’t see your name here.

  14. Derek Says:

    Nice post Peter, it was a fun read. I took the liberty of implementing some of your examples in the most recent version of Java’s closest analogue, C# … I think it bridges the brevity gap to some extent.

    http://derekslager.com/blog/posts/2006/10/channeling-ruby-in-csharp-3.ashx

  15. Isaac Gouy Says:

    “basic constructs which would make the life of any Java developer much easier”
    imo it would be better to say exactly what kind of programming you’re talking about and to only use realistic examples - I don’t know any programmers who are paid to write empty programs :-)

    “evaluated and substituted in the string, providing a more readable form without a lot of + + Java constructs”
    iirc System.err.printf(”Currently in the %s trimester”, Util.ordinalize(2));
    Java 5 has been around for a long time now ;-)

    “Arrays (and other containers)”
    If “this is NOT a Ruby-bashing-Java article” why make a bogus comparison between Ruby Arrays and Java arrays? I would expect someone who is “currently working with Java and Ruby on a daily basis” to compare Ruby Arrays with java.util.Vector and java.util.ArrayList

    “the Ruby Array class offers functionality that could be achieved only by mixing up several Java containers into one”
    That’s because the Ruby Array class has /mixed-up/ several different abstract containers. Why is that a good thing?

    “#Lua is just gaining steam, add it to the 7th place”
    LOL! Why wouldn’t we just add Lua as the last item?

    “you can not get the i-th element of a stack etc.”
    Not being able to get the i-th element is what makes it a stack!

    “Java/C++/(substitute any non-dynamic language here)”
    What do you mean by “any non-dynamic language” - do you mean any language that uses static type checking?

  16. Peter Cooper Says:

    I’m a Ruby fan, but even I wonder whether the ‘Ruby way’ of throwing an endless amount of methods into base classes is such a great idea. Java may lack a lot of the shortcuts and hacks of more dynamic languages, but it makes up for this with a reassuring verbosity. Compelling arguments can be made in both directions, and it depends whether you prefer a lighter base with extensions caked on top or a heavier base with extensions caked on top ;-)

  17. daveg Says:

    This post is further proof of a point I’ve made numerous times: Ruby developers are obsessed with Java.

  18. Isaac Gouy Says:

    it’s a research project to open a file

    new FileReader(”mystuff.txt”);

    still can not write to a file without using google first

    FileWriter f = new FileWriter("mystuff.txt");
    f.write("stuff");
    f.close();
    

    Ruby /is/ more concise than Java - there’s no need to exaggerate. Ruby was designed to be an object-oriented scripting language - Java was not designed to be a scripting language.

  19. Isaac Gouy Says:

    Ricky Clarkson showed appropriate use of readFully to read all of a file.

    The Regular Expressions example has other wierdness, why would we take off “\n” and then put them back

    while ((str = in.readLine()) != null)
       { sb.append(str + "n"); }
    

    instead of doing block reads?

    while ((charsRead = in.read(cbuf, 0, 8192)) != -1)
       sb.append(cbuf, 0, charsRead);
    
  20. yoggie Says:

    Well, I guess someone has missed the point here…
    I think this is a great article, that shows ONE aspect of MANY. It does not point out that Ruby is THE solution for everything and is the gem of all programing languages. It simply said: Ruby handles some sort of problems with greater ease. I do not feel that there is a need to prove that Java is the best, or at least as good at these aspects as Ruby. Well, if you think that, I have to disappoint you: both of the languages have their strong and weak points.

  21. Gábor Farkas Says:

    @Isaac:

    you said: “Ricky Clarkson showed appropriate use of readFully to read all of a file.”

    could you maybe point me to a function in java, that simply reads the whole content of a file into a byte-array,
    WITHOUT having me to manually allocate a buffer to hold the file-content?

    for me it simply seems strange/stupid/idiotic to not have such a method in a standard library.

    YES, i realize that sometimes that file might be very large, so it’s not always a good idea to read in the whole file etc, etc, etc.but sometimes i KNOW that the file is small enough, so why can’t i just load in the file?

    @everyone-who-thinks-that-it-is-not-fair-to-compare-the-libraries-of-the-languages:

    a programming language is not just the syntax and the compiler/virtual-machine/etc… it’s also it’s standard library. so i don’t think there’s anything wrong with comparing them.

  22. Isaac Gouy Says:

    @yoggie

    It simply said: Ruby handles some sort of problems with greater ease

    Ruby /does/ handle some problems with greater ease - the problem is that this article presents some Java examples which will seem bogus to Java programmers

    @Gábor Farkas

    for me it simply seems strange/stupid/idiotic to not have such a method in a standard library

    Why?
    afaik Ruby doesn’t handle UTF-16 in a standard library - does that seem strange/stupid/idiotic?

  23. Roland Hesz Says:

    “102.megabytes + 24.kbytes + 10.bytes”

    And you have 102.véka, 24.mázsa, 10.tenyér too?
    Or only precoded units of measure? I know, I know. The point is: you have a predefined set, which are either useful for you, or they are not.

    And if I would say “102.kilogram + 24.inch + 10.bytes” would it throw an error?
    Or the compiler will scream?

    print “Currently in the #{2.ordinalize} trimester” #=> “Currently in the 2nd trimester”

    I don’t know if it helps, when most of the time I would like something like:

    print “Jelenleg a #{2.ordinalize} félévben” #=> “Jelenleg a 2-dik félévben”

    A lot of these “make it easier” stuff only helps if you write for english locales.
    Would it work with danish, czecha, slovakian, russian, hungarian etc. ?
    I doubt.

    It is eye-candy, but not much use for a lot of people - yeah, everyone should change to english, forget the other languages, would make it easier, wouldn’t it? :) - when they write for a local audiance.

    “The getter and setter methods in Ruby code are generated automatically”

    Do I really want that? Can I prevent it from happening? I want to :)

    “[2] Some examples that Chronic can handle:

    summer
    6 in the morning
    tomorrow
    this tuesday
    last winter
    this morning
    3 years ago
    1 week hence
    7 hours before tomorrow at noon
    3rd wednesday in november
    4th day last week

    See my problems with these stuff being useless when you are not an english speaking person.
    I wonder if it could handle : “Holnap, 7 órával dél előtt”.

    BTW, I am not a java programmer - though I code in java at times -, I am a Delphi programmer, outcast of both tribes :p

    Ruby is a cool language, with strong points (and weaknesses), but some of the examples are just “nice to have at times” features.

    Just my two cents.

  24. peter Says:

    Na, ezt is megértem hogy egy magyar ember commentolt a blogomon (bár a Gábor is magyar, de ő nem ér mert a haverom :-)

    No, you don’t have those, although I guess no one would use them even in the Hungarian version of Ruby :-) BTW what kind of measure is ‘tenyér’ (palm in English :-)

    However, you can add them very easily:

    class Fixnum
    def tenyer
    self77
    end
    def mazsa
    self
    546
    end
    def kisujjesszemgolyo
    self*1956
    end
    end

    Yeah, yeah, without the diacritics, but after this you can write

    5.tenyer + 12.mazsa + 7.kisujjesszemgolyo

    Cool, isn’t it?

    There is no compiler in Ruby. It’s an interpreted language.
    The interpreter (obviously) knows nothing about semantics so why would it scream (given that the operator + is defined for all the types the 5.something calls return)

    About the language issues - well, yes you are right. Nothing is perfect :-)

  25. ben Says:

    These examples are flawed. Sure the basic stuff is correct: no methods on primitives, no methods on arrays.

    The problem with java isnt the language, its the developers who have no idea what they are doing. Look at the crap they produce, over and over again to solve the same problems, yet creating more.

    Most of the examples you post from Classes onwards can be done very well in java, elegant even.

    Some minor points: The Circle class is not equivalent by any stretch of the imagination, here is the equivalent java code:

    class Circle {
    Object coordinate;
    Object radius;
    }

    Then, at runtime use reflection or byte code enhancement to add the getters/setters etc. That is now equivalent to the ruby code; ruby cant do this in your example:
    refactor coordinate -> coord

    The file example is stupid - you are pointing out problems with design, not the language. Any halfway decent library could provide a one liner to do this.

    The tree example is worse: here is a “nicer” implementation.

    tree = new Tree(”A”){{
    add(new Tree(”b”){{
    add(new Tree(”d”));
    add(new Tree(”e”));
    }};
    add(new Tree(”c”){{
    add(new Tree(”f”));
    add(new Tree(”g”));
    add(new Tree(”h”));
    }}
    }};

    This is silly anyway: we would never create this structure (apart from in tests), but would load it from a database in a single method.

    With varargs, it would be easy to do this:

    tree = new Tree(”A”){{
    add(new Tree(”b”){{
    add(”d”, “e”);
    }};
    add(new Tree(”c”){{
    add(”f”, “g”, “h”);
    }}
    }};

    Which isnt bad, but still isnt as “nice”. But who cares: we never do this anyway!

    Anyway: one last comment:

    for( String s : Files.read(”test.txt”).scan(”(.*?\.)\s+?”) )
    // process s

    This is an excerpt from our Files library at work. While not as “one-linery” as ruby, it does the job with extra benefits.

    Ruby has BETTER programmers in general, because it is more obscure, exactly as paul said.
    You wait for the boatload of rubbish code that comes when the masses arrive at rails doorsteps.

    By the way, we deployed 5 rails apps using apache, postgres and debian, had no end of troubles with maintainability (no lighty wouldnt have helped), — does no one else have the urge to rename or refactor?—, took rake deploy back to java + gwt and never looked back.

    Lovely language, but is a toy when wanting to scale manpower. Small teams who dont have to maintain code: AWESOME! Pity the customer next year though, or the poor sod having to refactor the test cases (ouch!!!).

    Ben.

  26. Roland Hesz Says:

    “No, you don’t have those, although I guess no one would use them even in the Hungarian version of Ruby”

    My point: eye candy / nice to have :)

    “However, you can add them very easily:”

    I don’t know if I am comfortable with the idea of one billion different number classes. :)

    “Cool, isn’t it?”

    Yes, like extreme rafting. It’s cool, scary and dangerous.

    /One thing I don’t like in Ruby is that you never know who “extended” your class, and you can easily end up with two operations of the same name but different behaviours. Then good luck with debugging.

    “About the language issues - well, yes you are right. Nothing is perfect”

    That’s why I said that these are a bit of “peasant blinding” ;)

    Useful, but I don’t see it as too relevant.

    Nonetheless, yes, Ruby examples are easier to read. That’s true, and it is a nice language. :)

    “BTW what kind of measure is ‘tenyér’ “

    Like “marok”. Height if I’m not mistaken :)

  27. Kevin Says:

    This comparision always iritate me. It is true that Ruby has a lot of built in functions. But any even semi-compotent programmer would make methods to encapsulate functionality that they needed more than once. Have a lot built in functions does not make a language any more powerful than a language that allows you to write your own functions. I can make any hugely complex program into a one liner if I make a function that runs that program.

  28. peter Says:

    @Kevin:

    This way, COBOL or BASIC are equally powerful, eh?

    Of course if you have time/power/ability to write everything and encapsulate everything and use cool external libraries and have the brightest programmers around then every language is cool.

    Thus, Java power = COBOL power. Q.E.D.

  29. peter Says:

    @Roland:

    No pain, no gain. Sure the world was safer when people were bashing each other with clubs - but that does not mean nuclear ICBMs are not much more powerful. Of course they also cause much more damage, sometimes uncontrollable and devastating.

    You can be sure, when I was a Java early adopter (yes, I was even a Java zealot once) I got LOT of bashing from C and C++ fanboys that went like this:

    Java is a toy. It’s for children under 6 years of age who can not use malloc(). Real programmers use C++. Java is for stupid programmers who can not optimize and think so they leave everything to the JVM. And boy, it is slow like hell… And and
    and …

    I am not commited to ANY language. I have times when I like this or that, but when a more powerful (or interesting) language comes along I don’t have any problem for use it paralelly with my other programming languages.

  30. peter Says:

    @Roland:

    “About the language issues - well, yes you are right. Nothing is perfect”

    That’s why I said that these are a bit of “peasant blinding” ;)
    Useful, but I don’t see it as too relevant.

    Umm, you maybe forgot that english is estimated to be spoken by 0.5 to 2 BILLION people around the globe, whereas Hungarian by 15 million. So it is possibly that a language/package/framework which can do NLP ‘only’ in English is ‘pleasant blinding’ and irrelevant for you, however I guess the few hundred millions of English guys are fine using it…

  31. Roland Hesz Says:

    “I am not commited to ANY language.”"”

    Sensible. Each has its forte :)

    “Umm, you maybe forgot that english is estimated to be spoken by 0.5 to 2 BILLION people around the globe”

    That was not my point. I just noted that I would not base the use of a program language on whether I can type 2.megabyte or I would use some other methods (like create a constant int MEGABYTE=1024).

    That’s all I wanted to say :)

    Never met any programs where I needed 2.megabyte - though I can imagine a few places where it would be usefule - but I would have been glad to have 2.euro.convert.usd or something like that, ’cause I worked with financial programs.

    “Umm, you maybe forgot that english is estimated to be spoken by 0.5 to 2 BILLION people around the globe, whereas Hungarian by 15 million.”

    That’s why I asked about danish, sweden and such. The other 4 billion people around the globe :)
    I was not promoting hungarian, it was just an easy example for obvious reasons.

    So, the promotion of a programming language with a - in my opinion of course - nice, but only marginally useful feature was what I picked on. :)

  32. Roland Hesz Says:

    “No pain, no gain. Sure the world was safer when people were bashing each other with clubs - but that does not mean nuclear ICBMs are not much more powerful. Of course they also cause much more damage, sometimes uncontrollable and devastating.”

    I don’t know. Really. I mean, you can have a class definition spread over god knows how many files, half of them forgotten somewhere, 5 of the eight programmers who started the code base have gone to greener pastures, the documentation is almost nonexistent, and yes, maybe we had something like this, but where is it, and why, and, hey let’s write it anyway.

    “You can be sure, when I was a Java early adopter (yes, I was even a Java zealot once) I got LOT of bashing from C and C++ fanboys that went like this:”

    I know the feeling. :)

    “when a more powerful (or interesting) language comes along I don’t have any problem for use it”
    I don’t doubt it. And I never said Ruby is worse or better than Java.
    Actually, I did not judge either language. Just said that some of your examples were not convincing for me as being so important features.

    Ruby is cool. I like it. Java is cool. I like it. Never coded in either of them in a 9-5 job. So, I don’t consider myself as someone who could pass judgement :)

    Delphi is. Good. With that I have work experience and I have a solid opinion about that. But that’s irrelevant :)

  33. Paul Mansour Says:

    Roland makes a good point regarding the eye candy.

    In APL, we simply write:

    1024 102 24 10

    where is a single character primitive function that looks like an up tack (also known as the “base value” function.)

    Regardless of whether or not you use a character or a word, the point is that a well-defined, small set of primitive functions is much more powerful than a zillion specific methods.

    For example, if I want to see what 1 0 1 is in base 2, I use the same function:

    2 1 0 1

    Less is definitely more!

    I would have assumed Ruby had a base value method on its array class that would be similar to the APL base balue primitive. I guess you can always write your own.

  34. Paul Mansour Says:

    Woops,

    I used brackets and it got lost in the translation. Here is is again:
    Roland makes a good point regarding the eye candy.

    In APL, we simply write:

    1024 {decode} 102 24 10

    where {decode} is a single character primitive function that looks like an up tack (also known as the “base value” function.)

    Regardless of whether or not you use a character or a word, the point is that a well-defined, small set of primitive functions is much more powerful than a zillion specific methods.

    For example, if I want to see what 1 0 1 is in base 2, I use the same function:

    2 {decode} 1 0 1

    Less is definitely more!

    I would have assumed Ruby had a base value method on its array class that would be similar to the APL base balue primitive. I guess you can always write your own.

  35. denka Says:

    About handling Dates and Calendaring stuff, could you elaborate:
    - how does Ruby know that some parts of the globe have weeks starting on Monday, vs parts where weeks start on Sunday?
    - does it carry translations for days of week and names of months for all languages localization of which is supported (30 to 50, maybe more?)
    - is Ruby aware of daylight savings? How many time zones is it aware of? what will be the result of 20.minutes.ago if now is 3:01 a.m. PST on Sunday after 3rd Saturday in October in US?

    An example of doing that would be nice to have…

  36. arno nymous Says:

    and I can describe your article with just one word: BULLSHIT

  37. ben Says:

    Ruby isnt an ICBM. Lets leave the “fanfic” for another language that makes things simpler, more maintainable, faster, more scalable (cores + machines), more readable, and solves all the existing problems with one easy strike.

    Its more like a shotgun vs a pistol in accuracy - not as pronounced.

  38. peter Says:

    @arno nymous:

    BULLSHIT

    well, but at least the message came through: succinctness is power :-)

  39. AndrewN Says:

    Look kids, many Java developer’s will agree with you - Ruby+RoR are Great! And one day, when you grow up, get a real job, and need to solve real world business problems - ie, do more than write poxy haxx0r scripts and pretty little web 2.0 sites, you too may realize that little things like vendor support, a decent IDE, and any other number of things that Java has over Ruby are more important than silly little “10.times { }” examples.

    Now, off to bed, it’s past yer bedtime.

  40. Labnotes » Rounded Corners - 51 Says:

    […] Sometimes less is more. Take this Java code and lose some serious weight by writing it in Ruby. […]

  41. links for 2006-10-26 -- Chip’s Quips Says:

    […] Ruby, Rails, Web2.0 » Blog Archive » Sometimes less is more Contrasting Java’s loquaciousness with Ruby’s laconism. Thanks, assaf. (tags: ruby java programming languages) […]

  42. Turin2London Weblog » Ruby, Rails, Web2.0 » Blog Archive » Sometimes less is more Says:

    […] Ruby, Rails, Web2.0 » Blog Archive » Sometimes less is more Sometimes less is more […]

  43. Soft-dev: mainly about software development » Less code is groovy Says:

    […] Java vs Ruby […]

  44. Leonardo Quesada Blog » Contrast of Java and Ruby code… Says:

    […] Link: http://www.rubyrailways.com/sometimes-less-is-more/ […]

  45. Cliff Says:

    Though it’s already been menetioned I’ll just reiterate. If you drop the Groovy-all.jar (roughyl 1.5MB last I checked) in your classpath then you can practically match feature for feature from Ruby. You’ll also have additional features that wouldn’t exist in the Ruby equivalents, native Java integration, the ability to drop into any popular App server, and no impedence mismatch talking to existing legacy Java code as what would exist in JRuby.

  46. DotMana » » Ruby vs Java Says:

    […] http://www.rubyrailways.com/sometimes-less-is-more/ […]

  47. dottycfn Says:

    Probably you dont like java. Many of this java examples i can write faster.

  48. peter Says:

    That’s not the point. Of course they can be written faster (also the Ruby ones can be shortened - I have seen a 150 Byte long FizBuzz implementation in Ruby) - however, it will still be much longer than the Ruby version (mainly if you make the Ruby ones shorter, too). The real point is, however, the readability stemming from the succinctness - which you can not achieve in Java, no matter what you do. (Ok, ok, you can use groovy or JRuby but I mean pure Java)

  49. Trevor Says:

    You have a typo in your post. This:

    102.megabytes + 24.kbytes + 10.bytes

    should be this:

    102.megabytes + 24.kilobytes + 10.bytes

  50. peter Says:

    Thanks, Trevor! Fixed.

  51. Coding By Intention « Wherever I go, there I am Says:

    […] Implementation aside, this is clean, useful code, which is inherently concise and descriptive. I’m not a language bigot, but that doesnt mean I don’t appreciate it when a language makes it easier for me to get my job done […]

  52. Language Zealots « Wherever I go, there I am Says:

    […] After listening to me rave about Ruby for hours on end, it would be easy to conclude that I am a Language Zealot, a Ruby Jihadi bent on destroying all Java using infidels. Nothing could be further from the truth — I’m happy to use the best language for the situation. I’ve coded C on embedded set top boxes due to processor and memory constraints, Java server side processes now that no one codes in C anymore :) , and Perl when I had to rip through a thousand files quickly. […]

  53. Anikrichard Says:

    hello , my name is Richard and I know you get a lot of spammy comments ,
    I can help you with this problem . I know a lot of spammers and I will ask them not to post on your site. It will reduce the volume of spam by 30-50% .In return Id like to ask you to put a link to my site on the index page of your site. The link will be small and your visitors will hardly notice it , its just done for higher rankings in search engines. Contact me icq 454528835 or write me tedirectory(at)yahoo.com , i will give you my site url and you will give me yours if you are interested. thank you

  54. maikmidlooks Says:

    Hi everyone 

    Check out a funny video :

    http://www.youtube.com/watch?v=Z7jUnptjqZE

    Bye 

    maik midlooks

  55. javoman Says:

    Is Ruby dead?

    I haven’t once seen it being used to create a large, enterprise level web application employing transparent persistence built using a thing that all the interpreted language people like to live in denial of: ARCHITECTURE

    If you engineer enterprise level software for a living rather that obsess about manipulating the contents of text files or printing out the same string 10 x times in the least number of key presses then you’re most likely a fellow Java developer and I’d like to say congratulations. Keep up the good work. I’m sure this page was an interesting diversion but it’s time to get back to earning $100/hr providing your boss with the value and productivity he has come to know and expect from you as a professional Java software engineer.

  56. Mikel Says:

    Instead of this
    Util.megaBytes(102) + Util.kiloBytes(24) + Util.bytes(10)

    you can use static imports (Java 5 required)

    import static package.ByteUnitsUtil.*
    ….
    megaBytes(102) + kiloBytes(24) + bytes(10)
    ….

    Not as clean as the Ruby one but at least cleaner than your Java example

  57. Автомобильный форум Says:

    отзывы автофорум

  58. I am just a programmer » Sometimes less is more Says:

    […] read more | digg story […]

  59. AtrotoBoamb Says:

    subj
    ?

  60. Halo Says:

  61. ruby & java « em Desenvolvimento Says:

    […] http://www.rubyrailways.com/sometimes-less-is-more/ […]

  62. jack.lan Says:

    very nice!!!

    see you introduce, i just to learn ruby …

    i want to make friend with you , what about you disposition?

  63. jack.lan Says:

    if you want contact to me , I look forward to you mail !

Leave a Reply



Comment Preview


 Site feed

Support
Ruby Railways



ambien generic drug generic viagra online generic viagra online viagra with health men amazing blonde fucked cialis high off tramadol hcl dosage hazards of mixing xanax and valium hypnotics ambien valium photo phentermine deals 2 comparison levitra viagra cost of viagra covered by insurance cialis use with alcohol phentermine no prescrip non perscription viagra viagra bph about valium for anxiety add depression actos phentermine cvs pharmacy career get phentermine online phentermine no prescription required online consultation ending ativan using valium what if cialis does not work can you mix tramadol and benedryl viagra oral sex difference between tramadol and ultracet generic viagra cialis photo of ambien cheap cheap drug propecia tramadol weight loss clinic phentermine redondo beach acupuncture oct ivf women viagra phentermine lysergic acid diethylamide ranitidine order ambien with a prescription commview ambien ambien generic pills order free phentermine 37.5 mg 90 tablets ambien imitrex order viagra air travel viagra and alcohol buying valium online pharmacy online caverta vs viagra soma tramadol fioricet phentermine 37.5 no prossesing fee order phentermine cheap online buy viagra onli dogs tramadol artritus no doc phentermine viagra boys clips difference between meridia and phentermine beta blockers and cialis dose valium viagra 3 phentermine 37.5 diet pills 5 sildenafil viagra overnight generic viagra buy viagra online web meds viagra party drug online pharmacy with phentermine phentermine cheap script uk viagra supplier cardizem cd aciphex actos phentermine imitrex phentermine pill achat valium valium for colonoscopy compare levitra viagra cialis u 15640 cialis phentermine usa grapefruit and cialis order valium on line ambien xanax viagra aids male fertility viagra generico barato panic disorder after phentermine phentermine discussion forums purchase viagra on line take viagra who woman cheapest phentermine no presc phentermine and heart valium on line with prescription real phentermine diet pills viagra c-ring benefits of valium mixing valium with xanax discover viagra buy phentermine fedex no prescription tramadol free overnight shipping phentermine overnight delivery pharmacy online viagra overseas chep valium erections using cialis viagra best price sildenafil to buy valium cheapest generic substitute viagra when does viagra patent expire presidents in viagra commercial viagra for women cuba gooding jr cialis spoof cialis alchohol phentermine but no prescription viagra and generic drug tramadol online om cheap cialis pillstore ambien brazil miss viagra phone order ambien oklahoma phentermine sale 30mg cheap phentermine 3 cialis generic viagra mexico phentermine brand name viagra by mail viagra drug info cheap drug prescription prilosec tramadol zyrtec buy cost low viagra viagra mc mimo na jem mp3 generic valium and alert vet valium compare lunesta with ambien cr phentermine free doctor consultation no prescription 4 blue 30mg phentermine buying cheap discount sale viagra viagra priapism viagra c o d phentermine buy on-line online pharmacy phentermine free consultation cialis and suboxone trial generic viagra cheapest brand cialis ultram ultracet tramadol little helper valium 2nd day fedex phentermine phentermine online prescriptions brand generic online viagra depression phentermine cheap phentermine without prescription phentermine cheapest fioricet carisoprodol hydrocodone tramadol phentermine consultation free what nascar driver has viagra viagra soft tab 12.5 ambien cr band mitra viagra falls crushing tramadol for quick release viagra flowlan phentermine no rx overnight cheap career in pharmacy tramadol manufactures of viagra cialis levitra online contact forum buy cheap phentermine cialis discussion group phentermine without doctors script needed mixing vicodin viagra dosage for tramadol er viagra cocaine died ambien blood problems cialis comparison diflucan viagra buy medication phentermine detection drug in phentermine screen urine doesnt viagra work discount pill viagra viagra generic viagra from canada uprima viagra cialis can you take viagra with lexapro tramadol hydrochloride acetaminophen cheap price on phentermine phentermine no prescription phentramine valium point acupuncture phentermine 37 5mg online california pharmacy phentermine online diet pill tramadol without perscription cialis sale viagra for heart attack appetite suppressants and phentermine cialis cialis generic viagra generic medication cialis cheap phentermine net phentermine quick site order tramadol online express delivery cialis viagra comparisons life cialis phone free ambien online order generic ambien ambien and muscle pain diet free phentermine pill shipping generic fror ambien compare cialis viagra levitra free trial cialis drug approved buy phentermine on line doctors prescribing phentermine online cheaper viagra levitra cialis order viagra online a href tramadol drug medication phentermine with online docter consultation phentermine gained weight back herbal phentermine ingredient view more info generic viagra review vardenafil vs viagra phentermine overnight fedex no prescription 37.5 cialis qu es cheap phentermine cod pharmacy online perscription drug stores ultram tramadol online rx phentermine phentermine mastercard accepted phentermine price comparisons manufacturer of viagra tramadol hcl chemical supplier white soluble generic online pharmacy viagra risks of taking ambien and alcohol buy deal deal price viagra 180 tramadol cod valium for sale cheap valium fast buy cialis soft tabs viagra best used buy ambien buy cheap ambien online viagra triangle chicago adipex side effects phentermine hydrochloride adipex online sales phentermine order viagra prescription online adipex meridia phentermine prescription viagra get a free viagra pen drug interaction sibutramine and phentermine tramadol ultram 300ct phentermine mg index viagra portland oregon vancouver washington cheap cialis generic tramadol ultram ultram ambien and xanax together purchase tramadol with online prescription online pharmecies that sell phentermine funny picture viagra valium percoset drug generic generic viagra ambien 3 14 2007 tramadol online img available cheap cod phentermine viagra cialis heart problems cheap valium online phentermine irvington 85746 keyword phentermine online order shop baikalguide site ebaycouk kamagra viagra sildenafil ambien insert information sj lvmord tramadol the city that viagra built brand drug generic name viagra description of tramadol hcl-acetaminophen par ambien and celexa hydrocodone tramadol pain purchase viagra buy phentermine w out a prescription keyword valium buying online 150 generic cialis softtabs describe ambien cialis sublingual advantage with viagra overnight shipping ambien consultation is zora ambien ambien and expire online weight loss clinic phentermine viagra online order guide tramadol tenuate buy siesta ambien online phentermine on line pharmacy you tramdol tramadol 180 pills weightloss and phentermine compare fastin phentermine adipex phentermine and heart valve problems tramadol lethal od ambien alcohol effects thai valium viagra headaches ball forging bed buy cialis monster drinks and cialis genic viagra does public aid pay for viagra phentermine warnings ambien sleeping pills side effects cheap phentermine cheap phentermine online here phentermine buying valium united states pharmacy no prescription cod phentermine phentermine pharmacy discount phentermine tramadol is prescribed for aciphex aciphex phentermine discount pharmacy ambien zolpidem show available update lawsuit on viagra 2007 buy viagra in new zealand no rx valium cialis and levitra viagra medications internet ambien laws information on abuse of valium canada generic viagra keywords viagra mp3 liability prescription drug vioxx viagra viagra cheap online phentermine diet pills cod 30 generic cialis softtabs buy cheap phentermine onli ne ambien 7day free trial phentermine 2037.5 valium toxic dose 37.5mg phentermine no perscription tramadol seizure price of viagra compared to cialis 1cialis comparison levitra viagra order phentermine online cheap canada no prescription viagra which is best viagra livetra cialis cheap 30mg phentermine without prescription zoloft and viagra buy online viagra where valium at american pharmacy valium us brand name online does herbal phentermine work viagara and cialis cialis liver problems phentermine no scripts getting a valium enema investment returns for viagra tramadol hcl 200mg 6 free viagra cialis addiction buy online phentermine xenical ambien on line consulatation overnight cialis tadalafil php cheapest online tramadol buy in uk valium buy viagra online 35008 buy side effects of ambien sun sensitivity zolpidem vs ambien phentermine without dr ssri and phentermine drugs you shouldn't take with viagra buy phentermine no prescription required viagra makes you last longer cheap phentermine no prescription photos of viagra effect cialis and viagra together phentermine cod next day delivery what brand phentermine is the best tadalafil vs generic viagra phentermine onlien viagra cialis phentermine soma picture of phentermine capsule phentermine online overnight cardizem cd actos phentermine norvasc phentermine serotonin buying tramadol with paypal generic cialis uk online pharmacy pill price viagra viagra drug store best buys viagra drink affect side valium generic review viagra mg phentermine without prescription viagra cod phentermine delivered cod no prescription get viagra dont visit a doctor viagra for paxil side effects cialis und viagra forum cialis sex tramadol best buy 120 tramadol and free shipping ambien and manufacturer cialis viagra joint corporate renewal orn viagra phentermine xenical diet pill buying cialis generic mt viagra side effects dangers online ambien prescription ambien works tramadol maximum dosage cialis tablet which is better meridia or phentermine ambien interaction average price of phentermine florida online phentermine resident sold tucson cialis viagra from uk buy phentermine 37.5 tennessee overnight ship viagra selges phentermine no shipping to kentucky valium type drugs taking phentermine and chantrex together least expensive phentermine online name brand viagra viagra stafford po box viagra comics phentermine is it safe to intra nasal viagra cialis genuinerx net viagra viagra viagra online valium prescriptions cialis viagra propecia levitra erectile dysfunction flonase nasonex aldara tramadol ambien solubility am buy looking overseas phentermine tramadol online cod phentermine $99 no script celexa phentermine online pills huge discounts insta phentermine valium for cats cialis side affect phentermine erection libido cardizem cd phentermine actos phentermine imitrex mixing cocaine and viagra addiction plan self tramadol treatment cialis viagra combination viagra free sites find search pages generic viagra 24 hours delivery viagra cialis generic can woman take viagra viagra phone prescription tramadol experience discount online phentermine without doctor ambien sleep walk drive sex viagra casino poker blackjack tip to purchase phentermine online cheap retin tramadol generic cialis pills best price viagra buy oonline eon labs phentermine without a script tramadol wikipedia the free encyclopedia viagra penis pump next day shipping phentermine water phentermine slow release tramadol loratadine ambien buy phentermine or adipex discount phentermine discount phentermine phentermine viagra uden recept buy phentermine online no prescription required side effects viagra tramadol line canada viagra cialis on line purchase valium quickly buy xanax valium ambien zolpidem what drug category is ambien cr pill purchase online offers diet phentermine phentermine blue no prescription needed check phentermine and wellbutrin order tramadol order lipitor doctor specialist phentermine with out a prescription cheap 30mg yellow phentermines no membership 1cialis levitra viagra vs vs cialis texas auto insurance order phentermine without calling doctor cirrhosis frequency viagra overseas mail order valium is viagra effective for hypertension bush buy porn viagra buy phentermine levitra cialis pills discussion tramadol s tramadol and phlebitis viagra dizziness phentermine aciphex aciphex phentermine actos risperdal phentermine on line consultation cialis causes high blood pressure viagra party brans of phentermine ambien correct dosage valium lorazepam 37.5mg cause hair loss phentermine will pakistan generic ambien canada buy viagra online viagra vs phentermine diet pill overview 2005 ambien mt november tbcgi phentermine phentremine viagra invention valium and wellbutrin phentermine photo pill cialis drug description tadalafil healthscout valium dosage amount ambien cr coupons online pharmacy for ambien effects of lexapro and phentermine ambien overnight prescription online pharmacy pill viagra zoloft phentermine adipex viagra tramadol withot prescriptions picture of generic phentermine no prescription cheap tramadol overnight fedex ambien prescription buying prescription phentermine ambien cr no prescription cr natural viagra vitamin world weight loss forums phentermine pcp specialist forced ejaculation male viagra buy cheap online phentermine cialis tadalafil american express phentermine ups shipping acyclovir famvir tramadol clarinex ambien questions cheap tramadol free shipping cheapest phentermine 30 mg colorado phentermine real valium cheapest place to buy viagra online nrop iop forum phentermine tadalafil cialis vs viagra buy diet phentermine pill site free trail viagra ambien sirius commercial is there any legitimate viagra detox diet buy tramadol ambien 5mg price valium phentermine no prescription fed-ex day viagra cialis levitra dose comparison phentermine suspended phentermine 37 5mg shipped to kentucky addictive phentermine ambien sleepsex viagra taken ranitidine phentermine overnight to california tramadol airmail buy cialis softtabs referers top viagra phentermine 37.5 overnight phentramine hoodia cheapest viagra tramadol hydrocodone addiction viagra free sites computer find online valium effective pain relief medical uses of a valium splitting cialis generic lunesta myonlinemedsbiz propecia viagra viagra chat physican's desk reference phentermine what does phentermine look like can ambien cause a stroke lowest phentermine 37 5 prices viagra t shirt 1buy generic cialis tramadol and gallbladder ambien hep c cheapest get phentermine combining orlistat and phentermine drug tramadol ultram cialis price uk viagra discount sale buy cialis tadalafil at horizon drugs effexor and tramadol contradictions order phentermine at rassellueban org guaranteed overnight phentermine online pharmacy viagra cialis levitra manufactures addicted ambien cialis soft tab description phen phen phentermine budget rx phentermine viagra cortisone cream and valium together phentermine and leg cramps viagra cialis levitra href page 60 10mg ambien overnight celexa and valium action ambien class lawsuit phentermine side effects menstruation phentermine online cheap money order can ambien cause priapism over night phentermine enhancing the viagra review cheap discount viagra viagra out of control price on phentermine cialis cost low tramadol apap tb can women take men's viagra adipex cheap phentermine lowest price adipex viagra new zealand free sample florida phentermine online viagra and zyban canada generic cialis buy ambien cr no rx buy phentermine 37 5mg cialis and adverse effects tramadol and flushed feeling oral phentermine hydrochloride buy card debit online phentermine comparison viagra levitra cialis valium injectable addictive drugstore ambien cheap overnight phentermine phentermine and soma online pharmacy geberic viagra 50mg n phentermine best online pharmacy add buy comment line phentermine combined phentermine sibutramine 1cheapest cialis viagra for geritol song ambien baikalguide buy keyword phentermine interaction tramadol hcl-acetaminophen par weight viagra rx phentermine or meridia viagra shorts be