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 } } }