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.
Multiply each item in a list by 2
(1..10).map { |n| n * 2 }
Sum a list of numbers
(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(:+)
Verify if tokens exist in a string
words = ["scala", "akka", "play framework", "sbt", "typesafe"] tweet = "This is an example tweet talking about scala and sbt." words.any? { |word| tweet.include?(word) }
Reading a file
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/)
Happy Birthday
4.times { |n| puts "Happy Birthday #{n==2 ? "dear Tony" : "to You"}" }
Filter a list of numbers
[49, 58, 76, 82, 88, 90].partition { |n| n > 60 }
Fetch and parse an XML web service
require 'open-uri' require 'hpricot' results = Hpricot(open("https://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.
Find minimum (or maximum) in a list
[14, 35, -7, 46, 98].min [14, 35, -7, 46, 98].max
Parallel Processing
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.
Sieve of Eratosthenes
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.
Get more stuff like this
Subscribe to my mailing list to receive similar updates about programming.
Thank you for subscribing. Please check your email to confirm your subscription.
Something went wrong.
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. 😉
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.
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
I liked the concept pf ||= in ruby
a ||= b