Articol pe blog.alexn.org

February 2nd, 2009 Alex

Celălalt blog al meu nu primeşte prea multă dragoste. Azi am spart gheaţa :)

Enjoy ~

Posted in programming, technology | 2 Comments »

Perl, primele impresii

September 21st, 2008 Alex

Perl CamelM-am jucat un pic cu Perl.

Aveam o impresie destul de proastă despre limbaj din motive evidente:

  • sintaxa este concisă și sunt folosite caractere despre al căror sens nu-ți dai seama decât după ce citești un tutorial
  • în ultimul timp Perl primește multe critici de la programatori Python/Ruby

Încă nu am ajuns departe, limbajul fiind un pic mai greu de învățat, dar momentan sunt plăcut surprins.

Scopul lexical al variabilelor este așa cum te-ai aștepta: o variabilă este privată blocului în care este declarată și variabilele din blocurile exterioare sunt ascunse atunci când este conflict de nume. Iar bloc de cod chiar se referă la orice bloc de cod, adică poți declara variabile vizibile doar în ciclul „while” curent.

În 5.10 metodele pot folosi conceptul de variabilă “statică” din C … adică o variabilă globală ce poate fi accesată numai din interiorul metodei unde este declarată. Sună a moft, dar chiar este util pentru încapsulare, și în anumite situații chiar nu ai nevoie de oop.

Perl este loosly-typed, și experiența cu PHP mi-a lăsat un gust amar, dar cu directivele „use strict” și „use warnings” compilatorul generează o grămadă de erori și avertismente, și fiți pe fază … de la compilare, nu de la runtime. Exemplu:

use strict;
use warnings;
#use diagnostics;
 
sub add_to_list {
    my ($number, @list) = @_; # parametru
 
    sub add {
	return $_ + $number;
    }
 
    map add, @list;
}
 
my @x = add_to_list 0, (1..5);
my @y = add_to_list 5, (1..5);
print "@x\n";
print "@y\n";

Output-ul scriptului este:

Variable "$number" will not stay shared at ./learn line 11.
1 2 3 4 5
1 2 3 4 5

Avertismentul este dat o singură dată, la început, înainte de execuția efectivă a codului. Nu se înțeleg multe, dar dacă folosim directiva „use diagnostics” ni se explică mesajul: funția add nu este anonimă și deci este construită o singură dată, la primul apel al funcției „add_to_list”. Pentru construcția unei funcții ce capturează contextul curent de fiecare dată avem nevoie de un bloc de cod anonim:

sub add_to_list {
    my ($number, @list) = @_; # parametru
 
    my $add = sub {
	return $_ + $number;
    };
 
    map &$add, @list;
}

Cu output:

1 2 3 4 5
6 7 8 9 10

O chestie ce nu mi-a plăcut este noțiunea de referință. Lisp este primul limbaj unde toate variabilele reprezintă referințe la obiecte și nu obiecte propriu-zise. În Perl se face însă distincția. Pe de o parte este bine, deoarece se lucrează mai mult cu clone și se minimizează efectele secundare, dar se înmulțesc lucrurile pe care trebuie să le reți pentru a lucra cu limbajul. De exemplu listele, tip de dată fundamental, nu pot reține decât scalari (i.e. nu pot reține alte liste). Pentru a include liste în liste poți include referințe la liste, referințe care sunt considerate a fi scalari. E ok, dar e cam complicat.

Caracterul loosely-typed mă deranjează un pic, deoarece am coșmaruri de la PHP. Nu este la fel de rău când folosești „use strict”, dar încă apar chestii ciudate, cum ar fi că șirul de caractere “0″ este evaluat ca fals dacă este întâlnit într-un context în care se cere valoare booleană (if, while, etc..).

Are closures și sunt pe bune:

my @func;
 
foreach my $i (0..10) {
    push @func, sub{ 
	my($arg)=@_; 
	$arg * $i;
    };
}
 
print &{$func[$_]}(2),"\n"
    foreach (0..10);

În exemplu se crează un vector, în care fiecărui index $i i se asociază o funcție ce ia un parametru și-l înmulțește cu $i. La fel ca în Javascript, variabilele din context sunt capturate prin referință, nu prin valoare. Același exemplu formulat altfel poate da rezultate neașteptate:

my @func;
 
for (my $i=0; $i<=10; $i++) {
    push @func, sub{ 
	my($arg)=@_; 
	$arg * $i;
    };
}
 
print &{$func[$_]}(2),"\n"
    foreach (0..10);

Documentația oficială este bestială. Credeam că Python are cea mai bună documentație. Vezi learn.perl.org și perldoc.perl.org.

OOP-ul nu este chiar inclus în limbaj. Nu ar fi o problemă, din punctul meu de vedere oop-ul este supra-apreciat. Cu structuri de date suficient de flexibile, și dacă limbajul permite ceva „syntactic-sugar”, poți lucra OO fără probleme. Problema ar fi de standardizare. Common Lisp are CLOS. Se pare că există un add-on pentru Perl care a devenit standard pentru bibliotecile de cod moderne (e.g. Catalyst): Moose. Dar până să-mi dau cu părerea despre Moose, mai am de experimentat.

Posted in programming, technology | No Comments »

Despre unelte și alte nebunii

August 30th, 2008 Alex

Când eram mai mic și se vroia să fiu redus la tăcere, aveam o glumă preferată … „acum tac, gata am tăcut, nu mai zic nimic, am aruncat cheia, sunt silențios …” :) Nu prea mă pot abține.

M-am jucat în ultimul timp cu .NET și sunt chiar incitat de posibilitățile platformei, care este compusă practic dintr-o mașină virtuală, câteva compilatoare și o colecție de biblioteci de cod. Pentru un obsedat de limbaje ca mine, îmi plac următoarele:

  • F# - un dialect ML în mare parte compatibil cu Ocaml, cu plugin de VS 2008, iar odată cu ultima versiune a apărut și F# Developer Center
  • IronPython și IronRuby sunt 2 interpretoare funcționale ce pot fi folosite în Silverlight (exemplu)
  • C# 3.0 care a devenit un limbaj interesant (vezi tutorial programare funcțională)
  • DLR - o colecție de optimizări pentru interpretarea eficientă a limbajelor dinamice + un metaobject protocol ce ar putea permite comunicarea între 2 limbaje dinamice … cum ar fi apelul de metode scrise în IronPython din cadrul IronRuby.

Îmi plac limbajele de programare, și cred că este un fetiș, dar nu prea-mi pasă :) Momentan mă joc cu F# și mi se pare extrem de cool, și cu un design mai curat decât Scala, care pare a fi o struțo-cămilă deloc reușită.

Dar oricum, după cum spunea Steve Jobs: „real artists ship”. Și „code talks, bullshit walks”, sau cum era? :) Degeaba folosești limbajul zeilor dacă ești incompetent.

Posted in compilers, programming | No Comments »

Project Euler (în C# și Python)

July 13th, 2008 Alex

Mi-am reamintit de Project Euler, o colecție de probleme de matematică/informatică, perfecte pentru exerciții în timpul liber. Așa că m-am apucat de prima problemă, și este banală, dar rezolvarea reprezintă un exercițiu interesant pentru învățarea unui limbaj de programare.

Algoritmul brut ar arăta așa:

def calculateSum(max):
    sum = 0
    for i in range(0,max):
        if i%3==0 or i%5==0:
            sum += i
    return sum

Python idiomatic ar arăta așa:

def calculateSum(max):
    return sum([x 
                for x in range(0,max) 
                if x%3==0 or x%5==0])

În C# 3.0 am avea următorul cod echivalent:

long calculateSum(int max) {
    return
        (from i in Enumerable.Range(0,max)
         where i%3==0 || i%5==0
         select (long) i).Sum();
}

Nu arată deloc rău, dar este stupid să parcurgi toate numerele și să le aduni manual, problema putând fi optimizată matematic:

def calculateSum(max):
    def calculateFor(N):
        elements_nr = (max - 1) / N
        return int(N * elements_nr * (elements_nr + 1) / 2.0)
 
    return (calculateFor(3) + 
            calculateFor(5) - 
            calculateFor(15))

Exemplul este destul de evident ce face, cu mențiunea că metoda “calculateFor” este definită în cadrul metodei “calculateSum” deoarece are sens numai în cadrul acestei metode.

Echivalentul în C# 3.0:

long calculateSum(int max) {
 
    Func<int,long> calculateFor = (N) => {
        var elementsNr = (max - 1) / N;
        return N * 
            (long)(elementsNr / 2.0 * (elementsNr + 1));
    };
 
    return calculateFor(3) +
           calculateFor(5) -
           calculateFor(15);
}

Exceptând casturile de tip pe care le faci la fiecare pas, C# 3.0 chiar este decent.

Posted in programming | 4 Comments »