Someone came up with a list of 10 one-liner examples that are meant to showcase Scala’s expressiveness. A CoffeeScript version quickly emerged, so I thought I’d publish a Ruby one. I find Ruby’s syntax to be a bit cleaner than Scala’s, but the substance (at least as far as these examples are concerned) is relatively similar.
(1..10).map { |n| n * 2 }
(1..1000).inject { |sum, n| sum + n }
Or using the (built in) Symbol#to_proc syntax that’s been available since Ruby 1.8.7:
(1..1000).inject(&:+)
Or even just passing a symbol directly:
(1..1000).inject(:+)
words = ["scala", "akka", "play framework", "sbt", "typesafe"]
tweet = "This is an example tweet talking about scala and sbt."
words.any? { |word| tweet.include?(word) }
file_text = File.read("data.txt")
file_lines = File.readlines("data.txt")
The latter includes “\n” at the end of each element of the array, which can be trimmed by appending .map { |str| str.chop } or by using the alternative version:
File.read("data.txt").split(/\n/)
4.times { |n| puts "Happy Birthday #{n==2 ? "dear Tony" : "to You"}" }
[49, 58, 76, 82, 88, 90].partition { |n| n > 60 }
require 'open-uri'
require 'hpricot'
results = Hpricot(open("http://search.twitter.com/search.atom?&q=scala"))
This example requires open-uri and hpricot or equivalent libraries (you could use builtin ones if you wish). It’s not too much code, but Scala clearly wins here.
[14, 35, -7, 46, 98].min [14, 35, -7, 46, 98].max
require 'parallel' Parallel.map(lots_of_data) do |chunk| heavy_computation(chunk) end
Unlike Scala, multicore support is not built-in. It requires parallel or a similar gem.
The Scala one liner is very clever, but entirely unreadable. A simpler implementation that is no longer a one-liner in Ruby would be:
index = 0
while primes[index]**2 <= primes.last
prime = primes[index]
primes = primes.select { |x| x == prime || x % prime != 0 }
index += 1
end
p primes
This last example is straight from StackOverflow. Not the prettiest code ever, but you get the idea.
If you enjoyed this post, then make sure you subscribe to my Newsletter and/or Feed.
I sincerely welcome and appreciate your comments, whether in agreement or dissenting with my article. However, trolling will not be tolerated. Comments are automatically closed 15 days after the publication of each article.
Sum can also be written as:
(1..1000).inject(&:+)
Yes, the Symbol#to_proc syntax is very handy. I added it as a shorter alternative.
I think “reduce” is a clearer term for this than “inject”. Either way, you can feed this a symbol without needing the ampersand:
(1..1000).reduce(:+)
Sorry for the double post:
Words can be written as:
words.any? {|word| tweet.include?(word)}
No worries, Florian; comment any time you want. Agreed that the any? method makes it clearer. I updated that one liner.
use p or puts
words.any? { |word| tweet.include?(word) }
inject is fancy, but there’s almost always a better method to use.
> inject is fancy, but there’s almost always a better method to use.
Indeed.
There is much shorter solutions for prime example, like:
def prime?(x)
(’1′ * x) !~ /^1?$|^(11+?)\1+$/
end
Also ruby already contains library called “prime”.
require ‘prime’
7.prime? # => true
Prime.take(3) # => [2, 3, 5]
99.prime_division # => [[3,2], [11,1]]
> There is much shorter solutions for prime example, like:
Yeah, I read that article too. But again, it’s pretty unreadable and using a Regexp to verify primes just feels wrong.
> Also ruby already contains library called “prime”.
That’s a bit different than implementing a Sieve of Eratosthenes algorithm yourself though. It’s cheating, if you will.
[...] 10 Scala / Ruby / Clojure / CoffeeScript one liners to impress your friends, i thought it might be interesting to [...]
I don’t know if you can really call this an implementation of the sieve, but it works in a similar way and shows how you could write similar one-liners in Ruby.
(2..1000).inject([]){|r, v| r.inject(false){|k, j| k or v % j == 0} ? r : r.push(v)}
BTW, the second inject is just an implementation of the any? method, which i forgot exists already
If you’re in rails (or have ActiveSupport at least), summing a range/array is easy:
(1..100).sum
[1,2,3].sum
Here’s my Sieve, slightly shorter than the one you posted.
nums = (2..n).to_a
nums.each { |num| nums.map! { |i| i % num == 0 && i != num ? nil : i }.compact! }
$ ruby -rprime -e ‘p Prime.take(10)’
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
$ ruby -rprime -e ‘p Prime.take_while{|x|x < 20}'
[2, 3, 5, 7, 11, 13, 17, 19]
I like these one liners.
However the Sieve of Eratosthenes implementations should perhaps be named something else. Here is a very nice explanation for a true sieve by Melissa E. O’Neill, http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf
Its very interesting read and fun to implement in ruby (or Erlang, etc).
This is a bit disappointing. I was expecting some wicked tricks but it’s just basic stuff any Ruby developer would know. Maybe a better title would be “Ruby one liners for beginners”.
Al, these are definitely basic one liners. They are just a Ruby translation of a Scala post made by someone else. They’d probably look more impressive to people used to mainstream statically typed languages like Java or C++.
> I find Ruby’s syntax to be a bit cleaner than Scala’s
As far as I understood the author of “10 Scala One Liners to Impress Your Friends” really decided to use some more complicated constructs tobe sure to impress.
> (1..1000).inject(&:+)
> [14, 35, -7, 46, 98].min
> [14, 35, -7, 46, 98].max
could be written as
> 1 to 1000 sum
> List(14, 35, -7, 46, 98) min
> List(14, 35, -7, 46, 98) max
in Scala.
The Ruby code (as well as the original Scala example have the problem that their algorithm (accumulating the result of adding every number of the range) is O(n) which is really really slow!
Summing 1 to Int.MaxValue takes ~35 seconds in Scala (so probably a few minutes in Ruby).
There exists a ticket for #sum in Scala to make it an O(1) operation.
[...] the meme (scala, ruby, clojure, python, f#, coffeescript, [...]
[...] days ago, Antonio posted a list of 10 Ruby one-liners. The 1-liners saga started [...]
I thought
(1..1).inject { |sum, n| sum + n } and
(1..1).sum will return 2 but it is 1. Can anybody please explain
def fib(n, h= n < 2? 1 : fib( n -1) + fib(n-2)); h; end
I recall seeing this Fibonacci function somewhere, makes an interesting one liner I suppose
[...] 10 Scala One Liners to Impress Your Friends, which then led to (not in this order) 10 Ruby One Liners to Impress Your Friends, 10 Python one liners to impress your friends, 10 Clojure One Liners to Impress Your Friends, F# [...]
I liked the concept pf ||= in ruby
a ||= b