This article hopes to give you a feel for the following languages: Erlang, Haskell , Lua, Mozart/Oz, OCaml, Perl, Prolog, Python, Scala. Each of these is worth knowing at least a little. There is something "really different" about these languages from C/C++/Java. All these languages have open source implementations, readily available in Linux Ubuntu.
Acknowledgement: This article is nothing more than a copy-and-paste of paragraphs from various web sites. Programming Tasks
"Haskell offers: Substantially increased programmer productivity (Ericsson measured an improvement factor of between 9 and 25 using Erlang, a functional programming language similar to Haskell, in one set of experiments on telephony software); Shorter, clearer, and more maintainable code; Fewer errors, higher reliability; A smaller "semantic gap" between the programmer and the language; Shorter lead times. " [From http://www.haskell.org/haskellwiki/ ]
module Main (main) where main = putStrLn "Hello, World!"
qsort [] = [] qsort (x:xs) = qsort [y | y <- xs, y < x] ++ [x] ++ qsort [y | y <- xs, y >= x]
import Control.Concurrent main = mapM_ forkIO [process1, process2, process3] where process1 = putStrLn "Enjoy" process2 = putStrLn "Rosetta" process3 = putStrLn "Code"
-- http://shootout.alioth.debian.org/
-- contributed by Bryan O'Sullivan
-- modified by Eugene Kirpichov: pidgits only generates
-- the result string instead of printing it. For some
-- reason, this gives a speedup.
import System
pidgits n = 0 % (0 # (1,0,1)) where
i%ds
| i >= n = []
| True = (concat h ++ "\t:" ++ show j ++ "\n") ++ j%t
where k = i+10; j = min n k
(h,t) | k > n = (take (n`mod`10) ds ++ replicate (k-n) " ",[])
| True = splitAt 10 ds
j # s | n>a || r+n>=d = k # t
| True = show q : k # (n*10,(a-(q*d))*10,d)
where k = j+1; t@(n,a,d)=k&s; (q,r)=(n*3+a)`divMod`d
j&(n,a,d) = (n*j,(a+n*2)*y,d*y) where y=(j*2+1)
main = putStr.pidgits.read.head =<< getArgs
Buzz Words: associative arrays for extensible embedded scripting
"Lua is a powerful, fast, lightweight, embeddable scripting language. Lua combines simple procedural syntax with powerful data description constructs based on associative arrays and extensible semantics. Lua is dynamically typed, runs by interpreting bytecode for a register-based virtual machine, and has automatic memory management with incremental garbage collection, making it ideal for configuration, scripting, and rapid prototyping.""Lua has been used in many industrial applications (e.g., Adobe's Photoshop Lightroom), with an emphasis on embedded systems (e.g., the Ginga middleware for digital TV in Brazil) and games (e.g., World of Warcraft). Lua is currently the leading scripting language in games. Lua has a solid reference manual and there are several books about it." [From http://www.lua.org/ ]
print "Hello, World!"
function quicksort(array)
var list lessOrEqual, greater
if length(array) ≤ 1
return array
select a pivot value pivot
for each x in array
if x ≤ pivot then add x to lessOrEqual
if x > pivot then add x to greater
return concatenate(quicksort(lessOrEqual),
concatenate(pivot, quicksort(greater)))
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall
-- requires LGMP "A GMP package for Lua 5.1"
local g = {}; require"c-gmp"(g, {})
local add, mul, submul = g.mpz_add, g.mpz_mul_si, g.mpz_submul_ui
local mul2x, div, cmp = g.mpz_mul_2exp, g.mpz_fdiv_qr, g.mpz_cmp
local init, get, write = g.mpz_init_set_d, g.mpz_get_d, io.write
local N = tonumber(arg and arg[1]) or 100
local i, n, a, d, t, u = 0, init(1), init(0), init(1), init(0), init(0)
for k=1,1000000 do
mul2x(n, 1, t) mul(n, k, n) add(a, t, a) mul(a, k+k+1, a) mul(d, k+k+1, d)
if cmp(a, n) >= 0 then
mul2x(n, 1, t) add(t, n, t) add(t, a, t) div(t, d, t, u) add(u, n, u)
if cmp(d, u) > 0 then
local y = get(t)
write(y); i = i + 1; if i % 10 == 0 then write("\t:", i, "\n") end
if i >= N then break end
submul(a, d, y) mul(a, 10, a) mul(n, 10, n)
end
end
end
if i % 10 ~= 0 then write(string.rep(" ", 10 - N % 10), "\t:", N, "\n") end
Buzz Words: dataflow computing, open distributed computing, constraints and logical inference, concurrent object-orientation, cross-platform compatibility, powerful development environment
The Mozart Programming System is a platform for intelligent, distributed applications. Oz language supports declarative programming, object-oriented programming, constraint programming, and concurrency. [From http://www.mozart-oz.org/ ]
{Browse 'Hello World!'}
declare
fun {QuickSort Xs}
case Xs of nil then nil
[] Pivot|Xr then
fun {IsSmaller X} X < Pivot end
Smaller Larger
in
{List.partition Xr IsSmaller ?Smaller ?Larger}
{Append {QuickSort Smaller} Pivot|{QuickSort Larger}}
end
end
in
{Show {QuickSort [3 1 4 1 5 9 2 6 5]}}
for Msg in ["Enjoy" "Rosetta" "Code"] do
thread
{System.showInfo Msg}
end
end
% http://shootout.alioth.debian.org/
%
% Contributed by YANG Shouxun
functor
import
System(showInfo printInfo) Application(exit getArgs)
define
fun {Next Z}
case Z of [Q R S T] then (3*Q + R) div (3*S + T)
else raise invalidArg(Z) end
end
end
fun {Safe Z N}
case Z of [Q R S T] then N == ((4*Q + R) div (4*S + T))
else raise invalidArg(Z) end
end
end
fun {Comp Z1 Z2}
case Z1#Z2
of [Q1 R1 S1 T1]#[Q2 R2 S2 T2] then
[(Q1*Q2+R1*S2) (Q1*R2+R1*T2) (S1*Q2+T1*S2) (S1*R2+T1*T2)]
else raise invalidArg(Z1#Z2) end
end
end
fun {Prod Z N} {Comp [10 ~10*N 0 1] Z} end
fun {Cons Z K} {Comp Z [K 4*K+2 0 2*K+1]} end
proc {PrintNSpace N}
proc {Aux _} {System.printInfo " "} end
in {For 1 N 1 Aux} end
proc {Digit K Z N Row Col}
if N > 0 then Y in
Y = {Next Z}
if {Safe Z Y} then
if Col == 10 then
{System.printInfo "\t:"#(10+Row)#"\n"#Y}
{Digit K {Prod Z Y} N-1 10+Row 1}
else
{System.printInfo Y}
{Digit K {Prod Z Y} N-1 Row Col+1}
end
else
{Digit K+1 {Cons Z K} N Row Col}
end
else
{PrintNSpace 10-Col}
{System.showInfo "\t:"#(Row+Col)}
end
end
proc {Digits N} {Digit 1 [1 0 0 1] N 0 0} end
in
{Digits {String.toInt {Application.getArgs plain}.1}}
{Application.exit 0}
end
Buzz Words: modular type-safe strict functional programming plus objects.
Objective Caml (OCaml) is an object oriented derivative of ML functional language. The acronym CAML originally stood for Categorical Abstract Machine Language, although OCaml abandons this abstract machine. Ocaml has a large standard library that makes it useful for many of the same applications as Python or Perl, as well as robust modular and object-oriented programming constructs that make it applicable for large-scale software development. In recent years, many new languages have drawn elements from OCaml, most notably F# and Scala. See www.ocaml.org .
print_endline "Hello World!"
let rec quicksort gt = function
| [] -> []
| x::xs ->
let ys, zs = List.partition (gt x) xs in
(quicksort gt ys) @ (x :: (quicksort gt zs))
let _ =
quicksort (>) [4; 65; 2; -31; 0; 99; 83; 782; 1]
#directory "+threads"
#load "unix.cma"
#load "threads.cma"
let sleepy_print msg =
Unix.sleep ( Random.int 4 );
print_endline msg
let threads = List.map ( Thread.create sleepy_print ) ["Enjoy"; "Rosetta"; "Code"];;
let () = List.iter ( Thread.join ) threads;;
(*
* http://shootout.alioth.debian.org/
* contributed by Christophe TROESTLER
* modified by Mat�as Giovannini
*)
open Printf
open Big_int
let ( +$ ) = add_big_int
let ( *$ ) = mult_int_big_int
let ( /$ ) = div_big_int
(* Entier part of the linear fractional transform qrst of x *)
let ext (q,r,s,t) x = int_of_big_int ((x *$ q +$ r) /$ (x *$ s +$ t))
(* Multiply small int matrix qrst by big int matrix qrst' (small on left) *)
let mml (q,r,s,t) (q',r',s',t') =
q *$ q' +$ r *$ s', q *$ r' +$ r *$ t',
s *$ q' +$ t *$ s', s *$ r' +$ t *$ t'
(* Multiply big int matrix qrst by small int matrix qrst' (small on right) *)
let mmr (q,r,s,t) (q',r',s',t') =
q' *$ q +$ s' *$ r, r' *$ q +$ t' *$ r,
q' *$ s +$ s' *$ t, r' *$ s +$ t' *$ t
let unit = (unit_big_int,zero_big_int,zero_big_int,unit_big_int)
let next z = ext z 3
and safe z n = ext z 4 == n
and prod z n = mml (10, -10*n, 0, 1) z
and cons z k =
let den = 2*k + 1 in
mmr z (k, 2*den, 0, den)
let rec digit k z n row col =
if n == 0 then printf "%*s\t:%i\n" (10-col) "" (row+col) else
let d = next z in
if safe z d then
if col = 10 then begin
let row = row + 10 in
printf "\t:%i\n%i" row d;
digit k (prod z d) (n-1) row 1
end else begin
print_int d;
digit k (prod z d) (n-1) row (col+1)
end
else digit (k+1) (cons z k) n row col
let digits n = digit 1 unit n 0 0
let () = digits (try int_of_string (Array.get Sys.argv 1) with _ -> 27)
Buzz Words: regular expressions, object-oriented, procedural and functional programming. interfaces with external C/C++ libraries through XS or SWIG, ideal web programming language, 20 thousand modules.
Hello World
#!/usr/bin/perl "Hello, world!\n";
use threads;
use Time::HiRes qw(sleep);
$_->join for map {
threads->create(sub {
sleep rand;
print shift, "\n";
}, $_)
} qw(Enjoy Rosetta Code);
# http://shootout.alioth.debian.org/
#
# contributed by Robert Bradshaw
# modified by Ruud H.G.van Tol
# modified by Emanuele Zeppieri
use strict;
use Math::BigInt lib => 'GMP';
die 'Math::BigInt::GMP missing!'
if Math::BigInt->config->{lib} ne 'Math::BigInt::GMP';
my $z0 = Math::BigInt->new(1);
my $z1 = Math::BigInt->new(0);
my $z2 = Math::BigInt->new(1);
sub extract_digit { return scalar( ($z0 * $_[0] + $z1) / $z2 ) }
sub compose {
if ( defined $_[3] ) {
$z1->bmul( $_[0] )->badd( $_[1] * $z2 )
} else {
$z1->bmul( $_[2] )->badd( $_[1] * $z0 )
}
$z0->bmul( $_[0] );
$z2->bmul( $_[2] );
return
}
my $n = $ARGV[0];
($,, $\) = ("\t", "\n");
my ($i, $s, $d); my $k = 0;
# main loop
for $i (1..$n) {
while (
$z0->bcmp($z2) == 1 || ( $d = extract_digit(3) ) != extract_digit(4)
) {
# y not safe
$k++; compose($k, 4*$k+2, 2*$k+1)
}
compose(10, -10*$d, 1, 1);
$s .= $d;
unless ( $i % 10 ) { print $s, ":$i"; undef $s }
}
$s .= ' ' x (10-$i) if $i = $n % 10;
print $s, ":$n" if $s
Prolog is a general purpose logic programming language associated with artificial intelligence and computational linguistics. Prolog is declarative: The program logic is expressed in terms of relations, represented as facts and rules. A computation is initiated by running a query over these relations. Modern Prolog environments support the creation of graphical user interfaces, as well as administrative and networked applications. [From http://en.wikipedia.org/wiki/Prolog ]
http://www.swi-prolog.org/ is one of the best and free implementations.
write('Hello world'),nl.
I think you can guess what the next program does.
bottles(0):-!.
bottles(X):-
writef('%t bottles of beer on the wall \n',[X]),
writef('%t bottles of beer\n',[X]),
write('Take one down, pass it around\n'),
succ(XN,X),
writef('%t bottles of beer on the wall \n\n',[XN]),
bottles(XN).
:- bottles(99).
qsort( [], [] ). qsort( [X], [X] ). qsort( [H|U], S ) :- splitBy(H, U, L, R), qsort(L, SL), qsort(R, SR), combine(H, SL, SR, S). splitBy( H, [], LS, RS). splitBy( H, [U|T], [U|LS], RS ) :- U =< H, splitBy(H, T, LS, RS). splitBy( H, [U|T], LS, [U|RS] ) :- U > H, splitBy(H, T, LS, RS). combine( H, L, R, S ) :- append(L, [H|R], S).
Buzz Words: introspection, object orientation, exception-based error
handling, high level dynamic data types, extensive standard libraries,
extensions and modules easily written in C, C++, Java for Jython, or .NET
languages for IronPython, embeddable within applications as a scripting
interface.
The standard library covers everything from asynchronous processing to zip
files. Advanced language features: meta-classes, duck typing and decorators.
Python can integrate with COM, .NET, and CORBA objects. [From
http://python.org/ ]
print "Hello world!"
import threading
import random
def echo(string):
print string
threading.Timer(random.random(), echo, ("Enjoy",)).start()
threading.Timer(random.random(), echo, ("Rosetta",)).start()
threading.Timer(random.random(), echo, ("Code",)).start()
# http://shootout.alioth.debian.org/
# contributed by anon
# modified by Pilho Kim (first GMP version)
# modified by 2to3 and Daniel Nanz
import sys
from itertools import islice
from gmpy import mpz
(MPZ0, MPZ1, MPZ2, MPZ3, MPZ4, MPZ10) = (mpz(i) for i in (0, 1, 2, 3, 4, 10))
def gen_x(zero=MPZ0, one=MPZ1, two=MPZ2, four=MPZ4):
a, b, d = zero, two, one
while True:
a += one
b += four
d += two
yield (a, b, zero, d)
def compose(q1, q2):
a, b, c, d = q1
e, f, g, h = q2
return (a * e, a * f + b * h, c * e + d * g, c * f + d * h)
def extract(q, j):
a, b, c, d = q
return (a * j + b) // (c * j + d)
def pi_digits(x=gen_x(), extr=extract, comp=compose, zero=MPZ0,
one=MPZ1, three=MPZ3, four=MPZ4, ten=MPZ10, mten=-MPZ10):
z = (one, zero, zero, one)
while True:
y = extr(z, three)
while y != extr(z, four):
z = comp(z, next(x))
y = extr(z, three)
z = comp((ten, mten * y, zero, one), z)
yield str(y)
def main(n, digits=pi_digits(), width=10, line='{}\t:{}'):
for i in range(width, n+1, width):
print(line.format(''.join(islice(digits, width)), i))
if n % width > 0:
print(line.format(''.join(islice(digits, n % width)).ljust(width), n))
main(int(sys.argv[1]))
Buzz Words: Type inferencing, everything-is-an-object, function passing, compiles to JVM, scalable.
"Scala is a general purpose programming language designed to express common programming patterns in a concise, elegant, and type-safe way. It smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive. Code sizes are typically reduced by a factor of two to three when compared to an equivalent Java application." "Scala programs run on the Java VM, are byte code compatible with Java so you can make full use of existing Java libraries or existing application code." "... natural fusion with functional programming concepts which are critical for tackling concurrency." "Type inferencing, everything-is-an-object, function passing, and many other features cut away unneeded syntactic overhead." http://www.scala-lang.org/
object HelloWorld with Application {
Console.println("Hello, World!");
}
Quick Sort
def quicksortInt(coll: List[Int]): List[Int] =
if (coll.isEmpty) {
coll
} else {
val (smaller, bigger) = coll.tail partition (_ < coll.head)
quicksortInt(smaller) ::: coll.head :: quicksortInt(bigger)
}
import scala.actors.Futures
List("Enjoy", "Rosetta", "Code").map { x =>
Futures.future {
Thread.sleep((Math.random * 1000).toInt)
println(x)
}
}.foreach(_())
/*
* http://shootout.alioth.debian.org/
* contributed by Rex Kerr
* based on version by John Nilsson as modified by Geoff Reedy
* GMP wrapping based on Java version by Pall, Kraus, & Sassa
*/
object pidigits {
import Gmp._
class LFT(q:I, r:I, val t:I) {
def use(z: LFT) = { ~q; ~r; if (t ne z.t) ~t; z }
def compose(k: Int) = use(new LFT(q*k!, (q*(4*k+2))+*=(r,(2*k+1))!, t*(2*k+1)!))
def extract = {
val (y,rem) = (r + q*3) /% t !!
val x = if((rem + q) < t) Some(y.toInt) else None
~y; ~rem
x
}
def next(y: Int) = use(new LFT(q*10!, (r*10 -*= (t,10*y))!, t))
}
def pi_digits = {
def digits(z: LFT, k: Int): Stream[Int] = z extract match {
case Some(y) => Stream.cons(y,digits(z next y,k))
case None => digits(z compose k,k+1)
}
digits(new LFT(I(1),I(0),I(1)),1)
}
def by[T](s: Stream[T], n: Int): Stream[Stream[T]] =
if (s.isEmpty) Stream.empty
else Stream.cons(s take n, by(s drop n, n))
def main(args: Array[String]): Unit =
for ((d,n) <- by(pi_digits take args(0).toInt, 10).zipWithIndex)
printf("%-10s\t:%d\n",d.mkString,10*n+d.length)
}
/*
* Partial GMP wrapper for Scala.
* Write math like normal.
* Use ! to pull the result off the temporary stack
* Use ~ to return a value to the temporary stack
* Be careful with weird +*= GMP functions that destroy argument
*/
class GmpUtil {
System.loadLibrary("jpargmp")
@native def mpz_init(): Long
@native def mpz_clear(src: Long)
@native def mpz_set_si(lhs: Long, a: Int)
@native def mpz_get_si(a: Long): Int
@native def mpz_cmp(a: Long, b: Long): Int
@native def mpz_add(sum: Long, a: Long, b: Long)
@native def mpz_sub(sum: Long, a: Long, b: Long)
@native def mpz_mul_si(prod: Long, a: Long, b: Int)
@native def mpz_addmul_ui(lhs: Long, a: Long, b: Int)
@native def mpz_submul_ui(lhs: Long, a: Long, b: Int)
@native def mpz_tdiv_qr(quot: Long, rem: Long, n: Long, d: Long)
}
object Gmp {
val gmp = new GmpUtil
private var stack = Nil:List[I]
private var defunct = Nil:List[I]
class I {
private val z = gmp.mpz_init()
def !() = stack match {
case i :: rest if (i eq this) =>
stack = Nil
defunct = rest ::: defunct
i
case _ => I.die
}
def !!() = stack match {
case i :: j :: rest if (i eq this) =>
stack = Nil
defunct = rest ::: defunct
(i,j)
case _ => I.die
}
def toInt = gmp.mpz_get_si(z)
def <(i: I) = gmp.mpz_cmp(z, i.z) < 0
def +(i: I) = { gmp.mpz_add(I.ans.z, z, i.z); I.get }
def -(i: I) = { gmp.mpz_sub(I.ans.z, z, i.z); I.get }
def *(n: Int) = { gmp.mpz_mul_si(I.ans.z, z, n); I.get }
def +*=(i: I, n: Int) = { gmp.mpz_addmul_ui(z, i.z, n); this }
def -*=(i: I, n: Int) = { gmp.mpz_submul_ui(z, i.z, n); this }
def /%(i: I) = { val r = I.ans.z; gmp.mpz_tdiv_qr(I.ans.z, r, z, i.z); I.get }
def unary_~() = { defunct ::= this }
override def finalize() { gmp.mpz_clear(z); super.finalize }
}
object I {
def apply(n:Int) = defunct match {
case i :: rest =>
defunct = rest
gmp.mpz_set_si(i.z,n)
i
case _ =>
val i = new I
if (n != 0) gmp.mpz_set_si(i.z,n)
i
}
def ans() = { val i = I(0); stack ::= i; i }
def die: Nothing = throw new IndexOutOfBoundsException
def get() = stack match { case i :: rest => i ; case _ => die }
}
}