Llenguatge de programació

De Viquipèdia
(S'ha redirigit des de: Llenguatges de programació)
Dreceres ràpides: navegació, cerca
Codi font d'un programa escrit en llenguatge BASIC.

Un llenguatge de programació és un llenguatge informàtic utilitzat per controlar el comportament d'una màquina, normalment un ordinador. Cada llenguatge té una sèrie de regles sintàctiques i semàntiques estrictes que cal seguir per escriure un programa informàtic, i que en descriuen l'estructura i el significat respectivament. Aquestes regles permeten especificar tant la classe de dades amb què treballarà el programa com les accions que realitzarà. Mentre que alguns llenguatges es defineixen per una especificació formal (un document), altres són definits oficiosament per una implementació concreta (un compilador).

Actualment existeixen milers de llenguatges de programació, i se'n creen de nous contínuament.[1] Alguns dels més extensos són ASM, C, C++, C# i Java, tot i que els llenguatges de programació relacionats amb la web, com ara PHP i Javascript estan esdevenint més i més populars.

Classificació alt nivell-baix nivell[modifica | modifica el codi]

Els llenguatges se solen classificar principalment en llenguatges de baix nivell, que són molt propers al codi binari utilitzat internament per un tipus d'ordinador determinat, i llenguatges d'alt nivell, que són més propers al llenguatge humà i més independents del tipus d'ordinador.

La diferència entre llenguatges de baix i alt nivell es fa evident comparant dos programes que escriuen "Hola" en pantalla, el primer usant llenguatge d'assemblador per màquines x86 (baix nivell),

 MODEL SMALL
 IDEAL
 STACK 100H
 
 DATASEG
 HW DB 'Hola!$'
 
 CODESEG
 MOV AX, @data
 MOV DS, AX
 MOV DX, OFFSET HW
 MOV AH, 09H
 INT 21H
 MOV AX, 4C00H
 INT 21H
 END

i el segon utilitzant un llenguatge d'alt nivell (Python),

 print "Hola!"

Els llenguatges d'alt nivell es poden classificar també segons el tipus de model de programació que utilitzen (procedimentals, funcionals, orientats a objectes, etc.). També hi ha llenguatges de marcatge, que no són llenguatges de programació, sinó que s'utilitzen per estructurar o donar forma a un text. Avui en dia existeixen gran quantitat de llenguatges, més o menys especialitzats en diferents tasques.

Elements[modifica | modifica el codi]

Tots els llenguatges de programació tenen alguns elements de formació primitius per a la descripció de les dades i dels processos o transformacions aplicades a aquestes dades (tal com la suma de dos nombres o la selecció d'un element que forma parteix d'una col·lecció). Aquests elements primitius són definits per regles sintàctiques i semàntiques que descriuen la seva estructura i significat respectivament.

Sintaxi[modifica | modifica el codi]

Amb freqüència els elements de la sintaxi es fan que se'ls ressalta amb colors diferents per facilitar la seva lectura. Aquest exemple està escrit en Python.

A la forma visible d'un llenguatge de programació se la coneix com sintaxi. La majoria dels llenguatges de programació són purament textuals, és a dir, utilitzen seqüències de text que inclouen paraules, nombres i puntuació, de manera similar als llenguatges naturals escrits. D'altra banda, hi ha alguns llenguatges de programació que són més gràfics en la seva naturalesa, utilitzant relacions visuals entre símbols per especificar un programa.

La sintaxi d'un llenguatge de programació descriu les combinacions possibles dels símbols que formen un programa sintàcticament correcte. El significat que se li dóna a una combinació de símbols és manejat per la seva semàntica (ja sigui formal o com parteix del codi dur de la referència d'implementació). Ja que la majoria dels llenguatges són textuals, aquest article tracta de la sintaxi textual.

La sintaxi dels llenguatges de programació és definida generalment utilitzant una combinació d'expressions regulars (per a l'estructura lèxica) i la Notació De Backus-naur (per a l'estructura gramatical). Aquest és un exemple d'una gramàtica simple, obtinguda de Lisp:

expressió ::= àtom |llista
àtom      ::= nombre|símbol
nombre    ::= [+-]?['0'-'9']+
símbol    ::= ['A'-'Z'<nowiki>'</nowiki>a'-'z'].*
llista    ::= '(' expressió* ')'

Amb aquesta gramàtica s'especifica el següent:

  • una expressió pot ser un àtom o una llista;
  • un àtom pot ser un nombre o un símbol;
  • un nombre és una seqüència contínua d'un o més dígits decimals, precedit opcionalment per un signe més o un signe menys;
  • un símbol és una lletra seguida de zero o més caràcters (excloent espais);
  • una llista és un parell de parèntesi que obren i tanquen, amb zero o més expressions al mig.

Alguns exemples de seqüències ben formades d'acord a aquesta gramàtica:

'12345', '()', '(a b c232 (1))'

No tots els programes sintàcticament correctes són semànticament correctes. Molts programes sintàcticament correctes tenen inconsistències amb les regles del llenguatge; i poden (depenent de l'especificació del llenguatge i la solidesa de la implementació) resultar en un error de traducció o execució. En alguns casos, tals programes poden exhibir un comportament indefinit. A més, fins i tot quan un programa està ben definit dins d'un llenguatge, encara pot tenir un significat que no és el que la persona que ho va escriure estava tractant de construir.


Usant el llenguatge natural, per exemple, pot no ser possible assignar-li significat a una oració gramaticalment vàlida o l'oració pot ser falsa:

  • "Les idees verdes i descolorides dormen furiosament" és una oració ben formada gramaticalment però no té significat comunament acceptat.
  • "Pepet és un solter casat" també està ben formada gramaticalment però expressa un significat que no pot ser veritable.

El següent fragment en el llenguatge C és sintàcticament correcte, però executa una operació que no està definida semànticament (ja que p és un punter nul, les operacions p→real i p→im no tenen cap significat):

complex *p = NULL;
complex abs_p = sqrt (p→real * p→real + p→im * p→im);

Si la declaració de tipus de la primera línia fos omesa, el programa dispararia un error de compilació, doncs la variable "p" no estaria definida. Però el programa seria sintàcticament correcte encara, ja que les declaracions de tipus proveeixen informació semàntica només.

La gramàtica necessària per especificar un llenguatge de programació pot ser classificada per la seva posició en la Jerarquia de Chomsky. La sintaxi de la majoria dels llenguatges de programació pot ser especificada utilitzant una gramàtica Tipus-2, és a dir, són gramàtiques lliures de context. Alguns llenguatges, incloent Perl i a Lisp, contenen construccions que permeten l'execució durant la fase d'anàlisi. Els llenguatges que permeten construccions que permeten al programador alterar el comportament d'un analitzador fan de l'anàlisi de la sintaxi un problema sense decisió única, i generalment enfosqueixen la separació entre anàlisi i execució. En contrast amb el sistema de macros de Lisp i els blocs Begin de Perl, que poden tenir càlculs generals, les macros de C són mers reemplaçaments de cadenes, i no requereixen execució de codi.

Sistema de tipatge[modifica | modifica el codi]

El sistema de tipus defineix com un llenguatge de programació classifica els valors i expressions en tipus, com els manipula, i com hi interacciona. Generalment això inclou la descripció de les estructures de dades que el llenguatge pot construir. El disseny i estudi matemàtic d'aquests sistemes és conegut com la Teoria de tipus (type theory).

S'ha de recordar però que els computadors digitals moderns emmagatzemen internament totes les estructures simplement com a uns i zeros (binari)

Llenguatges tipats vers llenguatges no tipats[modifica | modifica el codi]

Un llenguatge és tipat si l'especificació de cada operació defineix a quins tipus de dades una operació és aplicable, amb la implicació que no és aplicable als altres tipus.[2] Per exemple, "aquest text entre cometes" és un string. En la majoria de llenguatges de programació, dividir un número per un string no té sentit. En conseqüència la majoria dels llenguatges de programació moderns rebutjaran qualsevol intent de dur a terme una operació com aquesta. En alguns llenguatges, l'operació sense sentit es detectarà en temps de compilació (comprovació de tipus "estàtica") i serà rebutjada pel compilador. Mentre que en d'altres, l'operació sense sentit es detectarà en temps d'execució (comprovació de tipus "dinàmica"), resultant en una excepció en temps d'execució (runtime exception).

Un cas especial de llenguatges tipats són els llenguatges mono-tipats. Normalment són llenguatges de script o de marcatge, com Rexx o SGML, i només tenen un tipus de dades - majoritàriament, cadenes de caràcters que són utilitzats tan per dades simbòliques com numèriques.

En contrast, un llenguatge no tipat, com la majoria de llenguatges assembladors, permet qualsevol operació sobre qualsevol tipus de dades, considerades com a seqüències de bits de mides vàries. Llenguatges d'alt nivell no tipats inclouen BCPL i algunes varietats de Forth.

A la pràctica, mentre que pocs llenguatges es consideren tipats des del punt de vista de la Teoria de tipus (verificar o rebutjar totes les operacions), la majoria del llenguatges moderns ofereixen un cert grau de tipatge. Molts llenguatges de producció ofereixen alguna manera de subvertir o fer un bypass al sistema de tipus.

Tipus estàtics versus dinàmics[modifica | modifica el codi]

En els sistemes de tipatge estàtics totes les expressions tenen els seus tipus determinats abans que el programa s'executi els (normalment al moment de compilar). Per exemple, 1 i (2+2) són expressions d'enters; no es poden passar a una funció que espera una cadena, o emmagatzemar-se en una variable definida per contenir dates.

Els llengües estàticament tipats poden ser o bé tipats de forma manifestada o bé tipats de forma inferida. En el primer cas, el programador ha d'escriure explícitament els tipus en certes posicions textuals (per exemple, en les declaracions de variables). En el segon cas, el compilador infereix els tipus de les expressions i les declaracions basant-se en el context.

El tipatge dinàmic, també anomenat tipat latent, determina el tipus de les operacions en temps d'execució; en altres paraules, els tipus estan associats amb valors de temps d'execució més que no pas a expressions textuals.

Tipus febles i tipus forts[modifica | modifica el codi]

Els llenguatges feblement tipats permeten que un valor d'un tipus pugui ser tractat com d'un altre tipus; per exemple una cadena pot ser operada com un nombre. Això pot ser útil a vegades, però també pot introduir certs tipus de fallades que no poden ser detectades durant la compilació o de vegades ni tan sols durant l'execució.

Els llenguatges fortament tipats eviten que passi l'anteriorment explicat: qualsevol intent de dur a terme una operació sobre el tipus equivocat dispara un error. Als llenguatges amb tipus forts se'ls sol anomenar de tipus segurs .

Llenguatges amb tipus febles com Perl i JavaScript permeten un gran nombre de conversions de tipus implícites. Per exemple en JavaScript l'expressió 2 * x converteix implícitament x a un nombre, i aquesta conversió és reeixida inclusivament quan x és null, undefined, un Array o una cadena de lletres. Aquestes conversions implícites són útils amb freqüència, però també poden ocultar errors de programació.

Les característiques d'estàtics i forts són ara generalment considerades conceptes ortogonals, però el seu tractament en textos de l'àmbit de la programació és divers. Alguns utilitzen el terme de tipus forts per referir-se a tipus fortament estàtics o, per augmentar la confusió, simplement com a equivalència de tipus estàtics. De tal manera que C ha estat considerat com a llenguatge tant de tipus forts, com de tipus estàtics febles.

Semàntica estàtica[modifica | modifica el codi]

La semàntica estàtica defineix les restriccions sobre l'estructura dels textos vàlids que resulta impossible o molt difícil expressar mitjançant formalismes sintàctics estàndard. Per als llenguatges compilats, la semàntica estàtica bàsicament inclou les regles semàntiques que es poden verificar en el moment de compilar. Per exemple la revisió que cada identificador sigui declarat abans de ser utilitzat (en llenguatges que requereixen tals declaracions) o que les etiquetes a cada braç d'una estructura casi siguin diferents. Moltes restriccions importants d'aquest tipus, com la validació que els identificadors siguin utilitzats en els contextos apropiats (per exemple no sumar un enter al nom d'una funció), o que les trucades a subrutines tinguin el nombre i tipus de paràmetres adequat, poden ser implementades definint-les com regles en una lògica coneguda com a sistema de tipus. Altres formes d'anàlisis estàtiques, com les anàlisis de flux de dades, també poden ser part de la semàntica estàtica. Nous llenguatges de programació com a Java i C# tenen una anàlisi definida d'assignacions, una forma d'anàlisi de flux de dades, com a part de la seva semàntica estàtica.

Implementació[modifica | modifica el codi]

Codi font d'un programa escrit en el llenguatge de programació java.

La implementació d'un llenguatge és la que proveeix una manera que s'executi un programa per a una determinada combinació de programari i maquinari. Existeixen bàsicament dues maneres d'implementar un llenguatge: compilació i interpretació.

  • Compilació: és el procés que tradueix un programa escrit en un llenguatge de programació a un altre llenguatge de programació, generant un programa equivalent que la màquina serà capaç interpretar. Els programes traductors que poden realitzar aquesta operació s'anomenen compiladors. Aquests, com els programes acobladors avançats, poden generar moltes línies de codi de màquina per cada proposició del programa font.

També es pot utilitzar una alternativa per traduir llenguatges d'alt nivell. En lloc de traduir el programa font i gravar de forma permanent el codi objecte que es produeix durant la compilació per utilitzar-lo en una execució futura, el programador només carrega el programa font a la computadora junt amb les dades que es processaran. A continuació, un programa intèrpret, emmagatzemat al sistema operatiu del disc, o inclòs de manera permanent dins de la màquina, converteix cada proposició del programa font en llenguatge de màquina així que vagi sent necessari durant el processament de les dades. El codi objecte no es grava per utilitzar-lo posteriorment.

La següent vegada que s'utilitzi una instrucció, se l'haurà d'interpretar una altra vegada i traduir a llenguatge màquina. Per exemple, durant el processament repetitiu dels passos d'un cicle o bucle, cada instrucció del bucle haurà de tornar a ser interpretada en cada execució repetida del cicle, el que fa que el programa sigui més lent en temps d'execució (perquè es va revisant el codi en temps d'execució) però més ràpid en temps de disseny (perquè no s'ha d'estar compilant a cada moment el codi complet). L'intèrpret elimina la necessitat de realitzar una compilació després de cada modificació del programa quan es vol agregar funcions o corregir errors; però és obvi que un programa objecte compilat amb antelació s'haurà d'executar amb molta major rapidesa que un que s'ha d'interpretar a cada pas durant una execució del codi.

La majoria de llenguatges d'alt nivell permeten la programació multipropòsit, tanmateix, molts d'ells van ser dissenyats per permetre programació dedicada, com ho va ser el Pascal amb les matemàtiques al seu començament. També s'han implementat llenguatges educatius infantils com a Logo que mitjançant una sèrie de simples instruccions. En l'àmbit d'infraestructura d'Internet, es pot destacar Perl amb un poderós sistema de processament de text i una enorme col·lecció de mòduls.

Tècnica[modifica | modifica el codi]

Llibres sobre diversos llenguatges de programació.

Per escriure programes que proporcionin els millors resultats, es pot tenir en compte una sèrie de detalls:

  • Correcció: un programa és correcte si fa el que ha de fer tal com es va establir en les fases prèvies al seu desenvolupament. Per determinar si un programa fa el que deu, és molt important especificar clarament què ha de fer el programa abans de desenvolupar-lo i, una vegada acabat, comparar-ho amb el que realment fa.
  • Claredat: és molt important que el programa sigui el més clar i llegible possible, per facilitar així el seu desenvolupament i posterior manteniment. En elaborar un programa s'ha d'intentar que la seva estructura sigui senzilla i coherent, així com cuidar l'estil en l'edició; d'aquesta forma es veu facilitat el treball del programador, tant en la fase de creació com en les fases posteriors de correcció d'errors, ampliacions, modificacions, etc. Fases que poden ser realitzades fins i tot per un altre programador, amb el qual la claredat és encara més necessària perquè altres programadors puguin continuar el treball fàcilment. Alguns programadors arriben fins i tot a utilitzar Art ASCII per delimitar seccions de codi. D'altres, per diversió o per impedir una anàlisi còmoda a altres programadors, recorren a l'ús de codi ofuscat.
  • Eficiència: es tracta que el programa, a més de realitzar allò per a la qual cosa va ser creat (és a dir, que sigui correcte), ho faci gestionant de la millor forma possible els recursos que utilitza. Normalment, en parlar d'eficiència d'un programa, se sol fer referència mentre tarda a realitzar la tasca per a la que ha estat creat i a la quantitat de memòria que necessita, però hi ha altres recursos que també poden ser de consideració en obtenir l'eficiència d'un programa, depenent de la seva naturalesa (espai en disc que utilitza, trànsit de xarxa que genera, etc.).
  • Portabilitat: un programa és portable quan té la capacitat de poder executar-se en una plataforma, ja sigui maquinari o programari, diferent d'aquella en la qual es va elaborar. La portabilitat és una característica molt desitjable per a un programa, ja que permet, per exemple, a un programa que s'ha desenvolupat per a sistemes GNU/Linux executar-se també en la família de sistemes operatius Windows. Això permet que el programa pugui arribar a més usuaris més fàcilment.

Paradigmes[modifica | modifica el codi]

Els programes es poden classificar pel paradigma del llenguatge que s'usi per produir-los. Els principals paradigmes són: imperatius, declaratius i orientació a objectes.

Els programes que usen un llenguatge imperatiu especifiquen un algorisme, usen declaracions, expressions i sentències.[3] Una declaració associa un nom de variable amb un tipus de dada, per exemple: var x: integer;. Una expressió conté un valor, per exemple: 2 + 2 conté el valor 4. Finalment, una sentència ha d'assignar una expressió a una variable o usar el valor d'una variable per alterar el fluix d'un programa, per exemple: x := 2 + 2; if x == 4 then fes_quelcom();. Una crítica comuna en els llenguatges imperatius és l'efecte de les sentències d'assignació sobre una classe de variables dites "no locals".[4]

Els programes que usen un llenguatge declaratiu especifiquen les propietats que la sortida ha de conèixer i no especifica qualsevol detall d'implementació. Dues àmplies categories de llenguatges declaratius són els llenguatges funcionals i els llenguatges lògics. Els llenguatges funcionals no permeten assignacions de variables no locals, així, es fan més fàcil, per exemple, programes com funcions matemàtiques.[4] El principi darrere els llenguatges lògics és definir el problema que es vol resoldre (l'objectiu) i deixar els detalls de la solució al sistema.[5] L'objectiu és definit donant una llista de subobjectius. Cada subobjectiu també es defineix donant una llista dels seus subobjectius, etc. Si en tractar de buscar una solució, una ruta de subobjectius falla, llavors tal subobjectiu es descarta i sistemàticament es prova una altra ruta.

La forma en la qual es programa pot ser per mitjà de text o de forma visual. En la programació visual els elements són manipulats gràficament en comptes d'especificar-se per mitjà de text.

Classificació dels principals llenguatges de programació[modifica | modifica el codi]

Codi font d'un programa en el llenguatge de programació orientat a objectes Ruby.
Vegeu classificació dels llenguatges de programació

Història[modifica | modifica el codi]

Desenvolupament inicial[modifica | modifica el codi]

Els primers llenguatges de programació són anteriors a l'aparició de l'ordinador modern. Al segle XIX hi havia telers programables i rotlles per a pianola que van aplicar el que avui es considera com a exemples de llenguatges de domini específic. A principis del segle XX van aparèixer les targetes perforades com a mitjà per a codificar i emmagatzemar dades que eren tractades mecànicament. A la dècada del 1930 i 1940, els formalismes d'Alonzo Church amb el seu càlcul lambda i d'Alan Turing amb la màquina de Turing van aportar una abstracció matemàtica per expressar algorismes; el càlcul lambda segueix tenint influència sobre el disseny del llenguatges.[6]

Als anys 40, es van crear els ordinadors digitals elèctrics. El primer llenguatge de programació d'alt nivell dissenyat va ser el Plankalkül, desenvolupat per Konrad Zuse entre el 1943 i 1945. Tanmateix, no es va implementar fins al 1998 i 2000.[7]

Els programadors dels ordinadors de principis dels anys 50 utilitzaven llenguatge màquina, és a dir, la primera generació de llenguatges (1GL). Ràpidament va ser substituïda pels llenguatges de segona generació coneguts com a llenguatges assembladors. Més endavant, encara als anys 40, el desenvolupament de llenguatge d'assemblador va ser reemplaçat pels llenguatges de "tercera generació" (3GL), com el FORTRAN, el Lisp i COBOL.[8] Els 3GLs són més abstractes i són "portables", o almenys es poden implementar de forma similar als ordinadors amb un codi màquina natiu diferent. Algunes versions actualitzades de 3GLs encara s'utilitzen, i han influenciat el desenvolupament posterior.[9] A finals dels anys 50 es va introduir l'ALGOL 60, del que la major part dels llenguatges posteriors en són descendents en molts aspectes.[9]

Referències[modifica | modifica el codi]

  1. «HOPL: an interactive Roster of Programming Languages». Australia: Murdoch University. [Consulta: 01-06-2009]. «Aquest web llista 8512 llenguatges.»
  2. Andrew Cooke. «An Introduction to Programming Languages». [Consulta: 30 de juny de 2006].
  3. Wilson, Leslie B. Comparative Programming Languages, Second Edition (en anglès). Addison-Wesley, 1993, p. 75. ISBN 0-201-56885-3. 
  4. 4,0 4,1 Wilson, Leslie B. Comparative Programming Languages, Second Edition (en anglès). Addison-Wesley, 1993, p. 213. ISBN 0-201-56885-3. 
  5. Wilson, Leslie B. Comparative Programming Languages, Second Edition (en anglès). Addison-Wesley, 1993, p. 244. ISBN 0-201-56885-3. 
  6. Benjamin C. Pierce va escriure:
    "... the lambda calculus has seen widespread use in the specification of programming language features, in language design and implementation, and in the study of type systems."
    Pierce, Benjamin C. Types and Programming Languages. MIT Press, 2002, p. 52. ISBN 0-262-16209-1. 
  7. Rojas, Raúl, et al. (2000). "Plankalkül: The First High-Level Programming Language and its Implementation". Institut für Informatik, Freie Universität Berlin, Technical Report B-3/2000. (full text)
  8. Linda Null, Julia Lobur, The essentials of computer organization and architecture, Edition 2, Jones & Bartlett Publishers, 2006, ISBN 0763737690, p. 435
  9. 9,0 9,1 O'Reilly Media. «History of programming languages» (PDF). [Consulta: 5 d'octubre de 2006].

Bibliografia[modifica | modifica el codi]

  • Bauer, F. L. & Wössner, H.. Algorithmische Sprache und Programmentwicklung. Berlín: Springer, 11981, 21984. 3-540-12962-6. 
  • Henning, P. A. & Vogelsang, H.. Handbuch Programmiersprachen. Softwareentwicklung zum Lernen und Nachschlagen. Munic: Hanser, 2007. 3-446-40558-5, 978-3-446-40558-5. 
  • Organick, E. I.; Forsythe, A. I.; Plummer, R. P.. Programming Language Structures. Nova York: Academic Press, 1978, p. 659. ISBN 0-12-528260-5. 
  • Wexelblat, Richard L.. History of Programming Languages. Nova York: Academic Press, 1981, p. 758. ISBN 0-12-745040-8. 

Vegeu també[modifica | modifica el codi]

Enllaços externs[modifica | modifica el codi]

A Wikimedia Commons hi ha contingut multimèdia relatiu a: Llenguatge de programació Modifica l'enllaç a Wikidata