A Rational number class in Ruby

As is my custom when learning a new language, I implement a basic custom Rational class in Ruby:

# implementation of a Rational number class in Ruby

module MyRational
    class Rational
        attr_reader :numerator, :denominator

        def initialize(num, denom = 1)
            if denom == 0
                raise "Denominator cannot be 0 for a rational number"
            end
            
            @numerator = num
            @denominator = denom

            normalize
        end

        
        # += etc all come for free when the basic operator is overloaded!
        def +(other)
            @numerator = @numerator * other.denominator + @denominator * other.numerator
            @denominator = @denominator * other.denominator

            normalize
            self
        end
        

        def -(other)
            @numerator = @numerator * other.denominator - @denominator * other.numerator
            @denominator = @denominator * other.denominator

            normalize
            self
        end

        
        def *(other)
            @numerator = @numerator * other.numerator
            @denominator = @denominator * other.denominator

            normalize
            self
        end

        
        def /(other)
            @numerator = @numerator * other.denominator
            @denominator = @denominator * other.numerator

            normalize
            self
        end


        def to_s
            if @denominator == 1
                @numerator.to_s
            else
                @numerator.to_s + "/" + @denominator.to_s
            end
        end

        
        # generics class methods
        def self.+(f, s)
            n = f.numerator * s.denominator + f.denominator * s.numerator
            d = f.denominator * s.denominator
            
            Rational.new(n, d)
        end

        def self.-(f, s)
            n = f.numerator * s.denominator - f.denominator * s.numerator
            d = f.denominator * s.denominator
            
            Rational.new(n, d)
        end


        def self.*(f, s)
            n = f.numerator * s.numerator
            d = f.denominator * s.denominator
            
            Rational.new(n, d)
        end


        def self./(f, s)
            n = f.numerator * s.denominator
            d = f.denominator * s.numerator
            
            Rational.new(n, d)
        end


        private

        def gcd(x, y)
            if y == 0
                x
            else
                gcd(y, x%y)
            end
        end

        
        def normalize()
            g = gcd(@numerator, @denominator)

            @numerator /= g
            @denominator /= g
        end
    end
end

Taking it for a test spin:

irb(main):003:0> load "my_rational.rb"
load "my_rational.rb"
=> true
irb(main):004:0> x = MyRational::Rational.new(1,2)
x = MyRational::Rational.new(1,2)
=> #<MyRational::Rational:0x007fd02a09bc88 @numerator=1, @denominator=2>
irb(main):005:0> y = MyRational::Rational.new(3,4)
y = MyRational::Rational.new(3,4)
=> #<MyRational::Rational:0x007fd02a0a21a0 @numerator=3, @denominator=4>
irb(main):006:0> x += y
x += y
=> #<MyRational::Rational:0x007fd02a09bc88 @numerator=5, @denominator=4>
irb(main):007:0> puts x
puts x
5/4
=> nil
irb(main):008:0> x -= y
x -= y
=> #<MyRational::Rational:0x007fd02a09bc88 @numerator=1, @denominator=2>
irb(main):009:0> puts x
puts x
1/2
=> nil
irb(main):010:0> x *= y
x *= y
=> #<MyRational::Rational:0x007fd02a09bc88 @numerator=3, @denominator=8>
irb(main):011:0> puts x
puts x
3/8
=> nil
irb(main):012:0> x /= y
x /= y
=> #<MyRational::Rational:0x007fd02a09bc88 @numerator=1, @denominator=2>
irb(main):013:0> puts x
puts x
1/2
=> nil
irb(main):014:0> MyRational::Rational.+(x, y)
MyRational::Rational.+(x, y)
=> #<MyRational::Rational:0x007fd02a0bad90 @numerator=5, @denominator=4>
irb(main):015:0> puts MyRational::Rational.+(x, y)
puts MyRational::Rational.+(x, y)
5/4
=> nil
irb(main):016:0> puts MyRational::Rational.-(x, y)
puts MyRational::Rational.-(x, y)
-1/4
=> nil
irb(main):017:0> puts MyRational::Rational.*(x, y)
puts MyRational::Rational.*(x, y)
3/8
=> nil
irb(main):018:0> puts MyRational::Rational./(x, y)
puts MyRational::Rational./(x, y)
2/3
=> nil

Of course, operations like number op rational, rational op number, where “op” is an operation will not work. These could be added by extending the number classes, etc, and also adding support in the class methods, but perhaps there is a better way that I will learn when I improve my Ruby knowledge! For now, the more I use Ruby, the more I like it!

A Rational number class in Ruby

Hoyte’s Line Number closure in a few choice languages

Douglas Hoyte, in his excellent (if a bit fanatical) book, “Let over Lambda” gives a simple and pithy example to demonstrate the concept of closures – little anonymous functions that can capture variables in the environment in which the closure was created.

The example is very simple – create a mini-logging facility by capturing a variable representing the current line number (initially set to 0), incrementing it for every invocation of the closure, and printing it out.

An implementation in Common Lisp might look so –

(defun get-line-logger ()
  (let ((line-num 0))
    #'(lambda (id)
        (incf line-num)
        (format t "[~a] Line number: ~d~%" id line-num))))


(defun logger-demo ()
  (let ((logger-1 (get-line-logger))
        (logger-2 (get-line-logger)))
    (flet ((f (id logger)
             (dotimes (i 5)
               (funcall logger id))
             (terpri)))
      (f "logger-1" logger-1)
      (f "logger-2" logger-2))))

Sample run:

CL-USER> (logger-demo)
[logger-1] Line number: 1
[logger-1] Line number: 2
[logger-1] Line number: 3
[logger-1] Line number: 4
[logger-1] Line number: 5

[logger-2] Line number: 1
[logger-2] Line number: 2
[logger-2] Line number: 3
[logger-2] Line number: 4
[logger-2] Line number: 5

NIL

As expected, we can not only capture local variables in the lexical environment during the time of the closure’s creation, but also modify them independently of any other instances of the closure. This is what makes is a proper closure. Also note that the capture is automatically done (whether we actually use the variables or not is irrelevant).

The Racket version is, unsurprisingly, almost identical not only in syntax, but also semantics:

#lang racket

(define (get-line-logger)
  (let ([line-no 0])
    (lambda (id)
      (set! line-no (+ 1 line-no))
      (fprintf (current-output-port)"[~a] Line number: ~a~%" id line-no))))

(define (logger-demo)
  (let ([logger-1 (get-line-logger)]
        [logger-2 (get-line-logger)])
    (letrec ([f (lambda (id logger)
                  (do
                      ((i 0 (+ i 1)))
                      ((= i 5))
                    (logger id))
                  (newline))])
      (f "logger1" logger-1)
      (f "logger2" logger-2))))

And the behaviour is exactly the same:

hoyte-closure.rkt´╗┐> (logger-demo)
[logger1] Line number: 1
[logger1] Line number: 2
[logger1] Line number: 3
[logger1] Line number: 4
[logger1] Line number: 5

[logger2] Line number: 1
[logger2] Line number: 2
[logger2] Line number: 3
[logger2] Line number: 4
[logger2] Line number: 5

Racket is, in some ways, more elegant than even Common Lisp. I especially love the part where lambdas don’t need any funcallS or applyS to make them run (unlike in Common Lisp). Still, pretty much a branch off the same family tree.

Moving on, let’s try the same in Java, shall we?

import java.util.function.Function;

public class HoyteClosure {
    private static Function<String, Void> getLineLogger() {
        int lineNum = 0;

        return (String id) -> { lineNum++; System.out.printf("[%s] Line number: %d\n",
                                                                 id, lineNum); return null; };
    }

    private static void invokeLogger(String id, Function<String, Void> logger) {
        for (int i = 0; i < 5; i++) {
            logger.apply(id);
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Function<String, Void> logger1 = getLineLogger();
        Function<String, Void> logger2 = getLineLogger();

        invokeLogger("logger1", logger1);
        invokeLogger("logger2", logger2);
    }
}

Okay, looks good. However, if we try to run it, we run into issues immediately:

Timmys-MacBook-Pro:Java8 z0ltan$ javac HoyteClosure.java 
Timmys-MacBook-Pro:Java8 z0ltan$ javac HoyteClosure.java 
HoyteClosure.java:7: error: local variables referenced from a lambda expression must be final or effectively final
        return (String id) -> { lineNum++; System.out.printf("[%s] Line number: %d\n",
                                ^
HoyteClosure.java:8: error: local variables referenced from a lambda expression must be final or effectively final
                                                                 id, lineNum); return null; };
                                                                     ^
2 errors

The problem is that Java really does not have real closures. The lambda support in Java 8 is just syntactic sugar for the good old anonymous class which can read local variables in the environment, but cannot modify them. So what can we do?

To make Java happy, we can create a new object for every logger instance i.e., use instance variables in lieu of local variables so that the modification of local variables is not an issue any more:

import java.util.function.Function;

public class HoyteClosureModified {
    static class Closure {
        private int lineNum;
        
        private  Function<String, Void> getLineLogger() {
            return (String id) -> { lineNum++; System.out.printf("[%s] Line number: %d\n",
                                                                 id, lineNum); return null; };
        }
    }

    private static void invokeLogger(String id, Function<String, Void> logger) {
        for (int i = 0; i < 5; i++) {
            logger.apply(id);
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Function<String, Void> logger1 = new Closure().getLineLogger();
        Function<String, Void> logger2 = new Closure().getLineLogger();

        invokeLogger("logger1", logger1);
        invokeLogger("logger2", logger2);
    }
}

Taking it for a test spin, we get:

Timmys-MacBook-Pro:Java8 z0ltan$ javac HoyteClosureModified.java
Timmys-MacBook-Pro:Java8 z0ltan$ java -cp . HoyteClosureModified
[logger1] Line number: 1
[logger1] Line number: 2
[logger1] Line number: 3
[logger1] Line number: 4
[logger1] Line number: 5

[logger2] Line number: 1
[logger2] Line number: 2
[logger2] Line number: 3
[logger2] Line number: 4
[logger2] Line number: 5

It’s not the same though, is it? The whole point of using a closure was so that we wouldn’t have to do this explicit management of state ourselves. As such, Java doesn’t really have full-blown closures, just a poor man’
s version of it. Better luck next time, Java.

Finally, the same using Ruby. As I have said before, Ruby feels remarkably like a Lisp despite the syntactic differences.

module HoyteClosure 
    class Demo
        def self.get_line_logger
            line_no = 0

            lambda do |id|
                line_no += 1
                puts "[" + id + "] Line number: " + line_no.to_s
            end
        end

        def self.logger_demo(id, logger)
            5.times {
                logger.call(id)
            }
            puts ""
        end

        def self.main
            logger1 = get_line_logger
            logger2 = get_line_logger

            logger_demo("logger1", logger1)
            logger_demo("logger2", logger2)
        end
    end
end

And the final test run:

irb(main):009:0> load "./hoyte_closure.rb"
load "./hoyte_closure.rb"
=> true
irb(main):010:0> HoyteClosure::Demo.main
HoyteClosure::Demo.main
[logger1] Line number: 1
[logger1] Line number: 2
[logger1] Line number: 3
[logger1] Line number: 4
[logger1] Line number: 5

[logger2] Line number: 1
[logger2] Line number: 2
[logger2] Line number: 3
[logger2] Line number: 4
[logger2] Line number: 5

=> nil

Short, non-idiomatic, and sweet!

Hoyte’s Line Number closure in a few choice languages

Python & Django, Ruby on Rails or PHP on Symfony? And why Java sucks…bigtime

Just over a year back and I wouldn’t have had an inkling of what lay beyond Java/J2EE for web development. That’s how scarily claustrophobically blind-sighted I was. Many reasons for that – both personal and professional but let me concentrate on the latter :-).
In my extremely humble opinion, the greatest misconception that many students have and which is further reinforced by the half-baked information they are “imparted” in school by folks who, congenial enough in person, are clearly in the wrong profession and also by the lazy and narrow-minded one-track-mindedness of the students themselves, is that when it comes to the web, there is only one way that you can go – the Java/J2EE path (of course, if one can afford to shell out some decent moolah, there is always the MS way – .NET et al). Add to this the tremendous propanganda by SUN ( “We are the ‘dot’ in ‘dotcom’ ” etc. ) and its lackeys – IBM and Oracle, Java has been hyped and overhyped to death. The plain truth is that it is a compromise. A very bad compromise at that! Portability? By installing a platform-specific JVM on each and every machine, and the size of which is bloating by the day? It’s laughable! And performance wise too it is a poor compromise between purely compiled languages and purely interpreted languages. The only reason why Java has survived and indeed flourished is the industry backing that it has received from stalwarts like the two sell-outs mentioned above.
This may seem a particularly harsh review from a novice in the “industry” but then again, one cannot gain “common sense” by being in the industry for five, ten or twenty years. Capisce? I do code in Java and am learning J2EE on my own, but the impression that I have is that it is way too cumbersome to go from initial conception of the idea to the actual deployment in any short period of time. The frameworks hide too much actual detail and add unnecessary gunk in the wrong places. I may do it for my main job, but not for my personal projects.

That is when I started looking at the options. Actually it was Paul Graham’s excellent essay Beating the Averages where he clearly stated that any language could be used when the code itself was entirely located within the server. And I quote :

“Back in 1995, we knew something that I don’t think our competitors understood, and few understand even now: when you’re writing software that only has to run on your own servers, you can use any language you want. When you’re writing desktop software, there’s a strong bias toward writing applications in the same language as the operating system. Ten years ago, writing applications meant writing applications in C. But with Web-based software, especially when you have the source code of both the language and the operating system, you can use whatever language you want.”

Now that made a tremendous amount of sense to my logical mind. For a while, I even toyed around with the idea of using Lisp itself but then after a bit of research, I decided that the lack of any decent repository of libraries made it a huge (and I mean huge) amount of effort and time investment. So for now, as far as Lisp for web development is concerned, I would rather wait and see if it matures to the point of feasibility.

Python and Django

That brings me on to Python and the excellent framework Django. Python is quite an old language but it seems to have become a huge favorite with all sorts of programmers – from beginners to the mighty brains at Google. The pros are many – cross platform, Object-oriented, bindings with C/C++/java and powerful enough to quickly create and deploy applications ( from simple CGI scripts to complex GUIs ) in record times! Around 4-5 times faster than in Java and around the same ratio of shorter code. The only drawback(s)? Its pathetic performance which trails even that of Java and yet it is much faster than Ruby. However,I came across this wonderful piece of software called Psyco which practically speeds up Python code by unbelievable factors ( over 100% ). A must have for any serious Python developer, Okay, about Django, my research tells me that it is the best web framework out there, And it is so indeed. I suppose Aaron Swartz’ Web.py framework is the
only serious competition. In fact, the whole of Reddit was rewritten from Lisp into Python using this framework. In the words of the authors of the site, the powerful threading capabilities of web.py was a strong reason of choosing that framework. All in all, Django seems the sanest choice for Python. The only nagging problem with the whole setup is
that Python needs a templating language ( which varies from framework to framework ) which is not Python. So one would have to know Javascript and the templating language for the front-end and the use pure Python for the back-end. Not bad though. I suppose the effort would not be much and I agree that it is a cleaner construct. And with Python’s rapid development features, the time spent in learning the templating language etc., will be offset by the gain in productivity.

My Rating – 4.5/5

Ruby on Rails

Next up is Ruby on Rails. I must confess upfront that the more I see of this language, the more I like it. Of course, the fact remains that Ruby by itself is not much of a head turner. It is the whole Rails framework which has given it a much needed boost. After all, both Ruby and Python have been around for almost the same time. When I mentioned that I like the language the more I see of it, I meant strictly in terms of the features and power that it provides. Not in terms of the aesthetic beauty of the language itself. In fact, the syntax is even more cryptic than that of Perl. Going by all the research that I have put in ( Phew!!! ), Ruby on Rails is a much more popular combination that Python with Django, but in terms of performance, the Python combo beats it fair and square. The one advantage that it does have is that there is no need for any extra templating language as in the case of Python. This would save me a lot of time, but considering my personal dislike of Ruby’s syntax and a slight leaning towards Python’s, I would say that it comes a close second, but still second compared to Python-Django. Another important reason is that there are more jobs oriented on Python per se than Ruby. Which is to say, from a career perspective, Python alone provides better opportunity than Ruby alone. RoR ( Ruby on Rails ) does provide more opportunities than Python-Django but till when?

My Rating – 4/5


PHP and Symfony

At last we come to arguably the most popular web development technology – PHP. Let us also consider the commonly used framework – Symfony. There is no doubt that PHP is the easiest and the smallest of the three – Python, Ruby and PHP, especially developed for rapid web development. However, the places where it suffers terribly – performance ( the worst of the three combinations ), security ( a major major drawback ) and a not-so-friendly developer community as the Python and Ruby communities. All in all, not as much potential for the future as the other two.

My Rating – 3/5

So the overall winner (again) in my most-humble-but-well-researched opinion
is Python with Django. Here is an instructive little video from Google Techtalks but presented by one of the creators of Django – Jacob kaplan Moss.

Enjoy creating the next web!

Python & Django, Ruby on Rails or PHP on Symfony? And why Java sucks…bigtime