6 Replies - 8808 Views - Last Post: 26 July 2010 - 09:47 AM

#1 macosxnerd101  Icon User is offline

  • Self-Trained Economist
  • member icon




Reputation: 10596
  • View blog
  • Posts: 39,259
  • Joined: 27-December 08

Week #26- Erlang

Post icon  Posted 21 July 2010 - 07:01 PM

This week's challenge is Erlang, a functional, open-source, programming language released by Ericsson.
Posted Image

wikipedia said:

Erlang is a general-purpose concurrent programming language and runtime system. The sequential subset of Erlang is a functional language, with strict evaluation, single assignment, and dynamic typing. For concurrency it follows the Actor model. It was designed by Ericsson to support distributed, fault-tolerant, soft-real-time, non-stop applications. The first version was developed by Joe Armstrong in 1986.[1] It supports hot swapping, thus code can be changed without stopping a system.[2] Erlang was originally a proprietary language within Ericsson, but was released as open source in 1998.

While threads are considered a complicated and error-prone topic in most languages, Erlang provides language-level features for creating and managing processes with the aim of simplifying concurrent programming. Though all concurrency is explicit in Erlang, processes communicate using message passing instead of shared variables, which removes the need for locks.


Getting Started:
To get started, download the Erlang SDK, which comes with a shell, which is used for compiling Erlang files as well as running some basic commands, like adding numbers and invoking functions. Erlang files (.erl extension) are used to store functions, and are referred to as modules. In order for the functions to be accessed outside of the module they are declaried in, they must be exported, as well as the module declared the head of the file. Modules are declared as such: -module(name)., and functoins are exported with the following syntax: -export([funcName/numArgs]).. Note how the . symbol is the terminator for each line. Individual commands within functions are separated by a semi-colon, and the function is ended with a period.

Example (primality checker):
-module(prime).
-export([is_prime/1]).

%the entry function, starts at N mod 2
is_prime(N) -> check_prime(N,2).

%case 1: base case- nothing after is prime
check_prime(N,K) when K >= N/2 -> N rem K /= 0;

%case 2: If we can't disprove primality, go to the next number
check_prime(N,K) when N rem K > 0 -> check_prime(N,K+1);

%case 3: If we can disprove primality, stop.
check_prime(N,K) when N rem K == 0 -> false.



In the Shell, to compile and run:
%compile
c:("path:/name.erl"). 

%if the compilation is successful
%a {ok, module_name} should appear
%if this is the case, you can invoke functions

%invoke a function- module:function(params).
prime:is_prime(100). 



Resources:
Erlang Tutorial From Ericson

Ideas:
The Dining Philosophers Problem
Mergesort or Quicksort
Calculuate N!
Find the Nth Fibonacci Number

Is This A Good Question/Topic? 2
  • +

Replies To: Week #26- Erlang

#2 Raynes  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 611
  • View blog
  • Posts: 2,815
  • Joined: 05-January 09

Re: Week #26- Erlang

Posted 22 July 2010 - 08:16 AM

Awesome. This is one of the few high-profile functional languages I haven't tried yet. I'll get around to this sometime this week.
Was This Post Helpful? 0
  • +
  • -

#3 TheSoundOfTruth  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 88
  • Joined: 17-September 09

Re: Week #26- Erlang

Posted 22 July 2010 - 09:03 AM

Oooh looks like fun. I better get coding.
Was This Post Helpful? 0
  • +
  • -

#4 Motoma  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 452
  • View blog
  • Posts: 796
  • Joined: 08-June 10

Re: Week #26- Erlang

Posted 22 July 2010 - 01:33 PM

Oh Telco.

Absolutely trivial tinkering with Erlang to follow.

gcd.erl:
-module(gcd).
-export([gcd/2]).

gcd(A, B)/> when A > B -> gcd(B, A - B)/>;
gcd(A, B)/> when A < B -> gcd(A, B - A);
gcd(A, B)/> when A == B -> A.



Interactive shell:
Eshell V5.6.3  (abort with ^G)
1> c(gcd).
{ok,gcd}
2> gcd:gcd(700, 1234).
2
3> gcd:gcd(512, 768)
256



EDIT: I swear I edit every single post I make. Bad form.

This post has been edited by Motoma: 22 July 2010 - 01:35 PM

Was This Post Helpful? 0
  • +
  • -

#5 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5848
  • View blog
  • Posts: 12,707
  • Joined: 16-October 07

Re: Week #26- Erlang

Posted 25 July 2010 - 06:30 AM

Erlang is a strange language. I never really got in to functional languages. While I've learned to embrace dynamic typing, this is probably the loosest language I've seen. Function overloads to the Nth, with pattern matching, "guards", a build in stack op for lists that's used extensively... Odd, but fun.

I recently did a vigenere in C++. It's simple, short, but uses a number of operations. Substitution ciphers with variable look up sounded like a nice, terse language test. Also, I figured most Erlang examples would be very math oriented and Erlang has a bad rep for strings.

So, my very first Erlang program:
-module(cipher).
-export([ceasarEnc/2, ceasarDec/2, test/0, vigenere/1]).
 
shiftFun(Dir) when Dir=:=true -> fun(Ch, Offset, Min, Max) -> 
	( ((Ch - Min) + Offset) rem (Max-Min+1) ) + Min
end;
shiftFun(_) -> fun(Ch, Offset, Min, Max) -> 
	F = shiftFun(true),
	F(Ch, (Max-Min+1)-Offset, Min, Max) 
end.

ceasar(_, [], _) -> [];
ceasar(F, [H|T], Offset) when H >= hd("A") andalso H =< hd("Z") -> 
	[ F(H, Offset, hd("A"), hd("Z")) | ceasar(F, T, Offset) ];
ceasar(F, [H|T], Offset) when H >= hd("a") andalso H =< hd("z") -> 
	[ F(H, Offset, hd("a"), hd("z")) | ceasar(F, T, Offset) ];
ceasar(F, [H|T], Offset) -> [ H | ceasar(F, T, Offset) ].

ceasarEnc(L, Offset) -> ceasar(shiftFun(true), L, Offset).

ceasarDec(L, Offset) -> ceasar(shiftFun(false), L, Offset).

vigenere(_, [], _) -> [];
vigenere(F, [H|T], [Kh|Kt]) -> 
	Newkey = lists:append(Kt,[Kh]), %% [1|[2,3]] not same as [[1,2]|3] probably better way to do this
	[ F(H, Kh, 0, 255) | vigenere(F, T, Newkey) ].

vigenere({encode, Key, L}) -> vigenere(shiftFun(true), L, Key);
vigenere({decode, Key, L}) -> vigenere(shiftFun(false), L, Key).


testCeasar(S, Offset) -> T1 = ceasarEnc(S, Offset), [S, T1, ceasarDec(T1, Offset)].

testVigenere(S, Key) -> T1 = vigenere({encode, Key, S}), [S, T1, vigenere({decode, Key, T1})].

test({ceasar, Results}) -> io:fwrite("Name: Ceasar~nValue: ~s~nEncode: ~s~nDecode: ~s~n~n", Results);
test({vigenere, Results}) -> io:fwrite("Name: Vigenere~nValue: ~s~nEncode: ~w~nDecode: ~s~n~n", Results).

test() ->
	Phrase = "The quick brown fox jumps over the lazy dog.",
	test({ceasar, testCeasar(Phrase, 15)}),
	test({vigenere, testVigenere(Phrase, "DIC")}).



I probably did some really un-erlangy or un-functional things. I know I basically ignored tail end recursion.

To write this little snippet I read a lot of internet resources and even perused the Programming Erlang book by Joe Armstrong. I the site Learn you some Erlang ( for great good ) not just informative and helpful, but entertaining. I love Monty Python references. Give this one a look if you haven't.

I was dubious of this language at first, but it did kind of grow on me.

This post has been edited by baavgai: 25 July 2010 - 06:32 AM

Was This Post Helpful? 3
  • +
  • -

#6 macosxnerd101  Icon User is offline

  • Self-Trained Economist
  • member icon




Reputation: 10596
  • View blog
  • Posts: 39,259
  • Joined: 27-December 08

Re: Week #26- Erlang

Posted 26 July 2010 - 08:22 AM

Thanks for the link! *Bookmarked for future reference*
Was This Post Helpful? 0
  • +
  • -

#7 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5848
  • View blog
  • Posts: 12,707
  • Joined: 16-October 07

Re: Week #26- Erlang

Posted 26 July 2010 - 09:47 AM

After playing around with Erlang for several hours to get a good feel and ( hopefully ) decent example, I found myself unwilling to completely drop it.

So, here's anything example that's far more linear and thus probably easier to follow. It's the answer to a question we get on DIC with some frequency.

-module(mort).
-export([getPayment/3, showTable/3, test/0]).

roundCurrency(M) -> trunc((M * 100.0)+0.5) / 100.

printTableRow(PaymentNum, Balance, Payment, PrincipalPayment, InterestPayment, NewBalance) ->
	io:fwrite("~3b ~12.2f ~12.2f ~12.2f ~12.2f ~12.2f ~n", 
		[PaymentNum, Balance, Payment, PrincipalPayment, InterestPayment, NewBalance]
	).

getPayment(Principal, AnnualInterest, Years) ->
	MonthlyInterest = AnnualInterest / 12.0,
	TotalPayments = Years * 12,
	Payment = Principal * MonthlyInterest / ( 1.0 - math:pow( 1.0 + MonthlyInterest, -1 *  TotalPayments) ),
	{ payment, roundCurrency(Payment), MonthlyInterest }.

showTableRow(Balance, { payment, Payment, Interest }, PaymentNum) ->
	InterestPayment = roundCurrency(Balance * Interest),
	PrincipalPayment = Payment - InterestPayment,
	if PrincipalPayment >= Balance ->
		printTableRow(PaymentNum, Balance, Balance+InterestPayment, Balance, InterestPayment, 0.0);
	true ->
		NewBalance = Balance - PrincipalPayment,
		printTableRow(PaymentNum, Balance, Payment, PrincipalPayment, InterestPayment, NewBalance),
		showTableRow(NewBalance, { payment, Payment, Interest }, PaymentNum+1)
	end.
	 
showTable(Principal, AnnualInterest, Years) -> 
	io:fwrite("~3s ~12s ~12s ~12s ~12s ~12s ~n", 
		["#", "Balance", "Payment", "Principal", "Interest", "New Balance"]
	),
	showTableRow(Principal, getPayment(Principal, AnnualInterest, Years), 1).

test() -> showTable(20000.00, 0.075, 5).


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1