Stuff about software development, agile and testing

Showing posts with label scala. Show all posts
Showing posts with label scala. Show all posts

Thursday, January 7, 2010

Ruby inject in Scala

Do you have your favorite line in Ruby. Mine will be

(1..100).inject(&:+)

and I first saw that in Reg Braithwaite blog (very good read)

So what's going on here? Here is the explanation from Reg Braithwaite's blog


Explanation: (1..100) creates a Range. For our purposes, this is equivalent to a collection of the whole numbers from one to one hundred, inclusive (The major way in which it differs from an array for us is that it doesn’t actually require one hundred spots in memory. Ranges are also useful for matching.) The #inject method is called fold or reduce in other languages. Expressed like this, it applies the “+” function to the elements of our range, giving us the sum. Primary school students could tell you an easier way to obtain the sum, of course, but we will ignore that for now.

Ruby doesn’t actually have a function called +. What actually happens is that #inject wants a block. The & operator converts Proc objects into blocks and block into Proc objects. In this case, it tries to convert the symbol :+ into a block. The conversion uses Ruby’s built-in coercion mechanism. That mechanism checks to see whether we have a Proc object. If not, it sends the #to_proc method to the argument to make a Proc. If the Symbol :+ has a #to_proc method, it will be called. In Ruby 1.9 it has a #to_proc method. That method returns a Proc that takes its first argument and sends the + method to it along with any other arguments that may be present.



Well even though there are plenty different way you could add entries in collection, this line of code demonstrates the power of the language and what you could do with it.

Being Scala is my favorite programming language right now I wanted to implement something very similar in it. By default in Scala if you want some apply some binary operator to a range you could do

(1 until 100).reduceLeft { _ + _} and if you want your range to be inclusive then

(1 until 100).inclusive.reduceLeft { _ + _}

But still it is little bit verbose. So with some implicit trick I was able to come quite a bit close to the actual Ruby line above

1 ⟞ 10 inject '+

'⟞' is a unicode character and yes you could define method names with unicode characters. '+ is symbol is Scala. And here is rest of the implementation...

implicit def rich_range(r: Range) = new {
def inject(s:Symbol) = {
s match {
case '+ => r.reduceLeft { _ + _ }
case _ => //not supported yet
}
}
}

implicit def rich_int(start: Int) = new { def ⟞(end:Int) = (start until end).inclusive }




Well again point is not about using binary operator on a collection or range. Its about powerful and expressiveness of a programming language.

Monday, January 14, 2008

Scala: Surprise Part oNe

Ruby is a language of least surprises but I am not sure whether I can say that for Scala yet. I have already encountered some of them, here is one example

You can define method without '()'

def height: Int = 0 //This is a valid method

def width(): Int = 0 //This is valid too

Now you can invoke 'width' method with and without parenthesis but you cannot do that for height method.

SURPRISED


Update: The Scala convention is, use '()' for parameter less method if it has side effects otherwise don't

Thursday, December 13, 2007

scala book is out

Its now an open secret that Scala doesn't have good documentation/reference to help any developer to try their programming skills. But finally Scala book is out (pre-print edition) and I got my copy.

Labels