Voi siete qui: Inizio Programmare in Scala

Glossario

$tag

Un metodo dichiarato dal tratto ScalaObject che non accetta argomenti e restituisce un intero. È usato internamente da Scala per ottimizzare il pattern matching, ma potrebbe venire rimosso in una futura versione del linguaggio. Pur essendo invisibile nel codice Scala (in quanto generato automaticamente dal compilatore), potrebbe essere necessario definirlo nelle classi Java che estendono certi tratti o certe classi Scala.

Ambito

Un determinato confine di visibilità che limita l’insieme di tipi e membri accessibili al proprio interno.

Annotazione

Un meccanismo per allegare “metadati” a una dichiarazione in modo che il compilatore (o altri strumenti) sia in grado di sfruttarli per generare codice, verificarlo, convalidarlo, &c. In Scala (come in Java) le annotazioni sono classi e, quando vengono usate, sono precedute dal carattere @.

Qualsiasi dichiarazione di tipo esplicita viene anche chiamata annotazione di tipo.

Inoltre si definiscono annotazioni le specifiche che integrano una dichiarazione di tipo indicandone il comportamento della varianza in caso di ereditarietà, i limiti e le viste.

Annotazione di tipo

Una dichiarazione esplicita del tipo di un valore, come in count: Int, dove Int è l’annotazione di tipo. È necessaria nei casi in cui l’inferenza di tipo non può essere usata, come per i parametri e talvolta il tipo di ritorno di una funzione.

Annotazione di varianza di tipo

Applicato a un parametro di tipo in un tipo parametrico, il simbolo + davanti al simbolo del tipo viene usato per indicare la covarianza, il simbolo - per indicare la controvarianza. L’assenza di qualsiasi simbolo a precedere il tipo indica l’invarianza, che è il comportamento predefinito.

Annotazione self-type

Una dichiarazione contenuta in un tratto o in una classe che modifica il tipo del tratto o della classe, a volte definendo un alias per this (chiamato self per convenzione). Un tipo esplicito per la classe corrente può essere sfruttato per indicare quali sono i tratti da cui dipende, che dovranno essere mescolati in un’istanza concreta per risolvere tali dipendenze. In alcuni casi le annotazioni self-type vengono usate per garantire che un’istanza del tipo corrente possa essere usata come istanza di uno dei tipi da cui dipende (si veda come sono state impiegate per implementare il pattern Observer nella sezione Annotazioni self-type e membri tipo astratti del capitolo 13).

Applicazione

In Scala, qualsiasi object dotato di un metodo main che viene invocato dalla JVM o dal CLR di .NET all’avvio di un nuovo processo.

Applicazione parziale

Associata al currying, è l’applicazione di una funzione curry a un sottoinsieme dei suoi argomenti, risultante in una nuova funzione che accetta i restanti argomenti.

Argomento con nome

Indica la possibilità di usare un nome per fare riferimento a un argomento quando si invoca un metodo, utile in combinazione con i valori predefiniti degli argomenti per minimizzare il numero di argomenti che devono essere specificati dal chiamante.

Argomento implicito

Un argomento che l’utente può scegliere di non specificare quando invoca un metodo. Il parametro che riceve un argomento implicito viene indicato con la parola chiave implicit. Se l’utente non specifica un valore per l’argomento, si usa un valore predefinito dello stesso tipo, oppure un metodo senza argomenti la cui invocazione restituisce un valore dello stesso tipo, entrambi ottenuti cercando nell’ambito di visibilità corrente. Si veda anche la voce Valore predefinito di un argomento.

Arità

Il numero di argomenti accettati da una funzione.

AspectJ

Una estensione di Java che supporta la programmazione orientata agli aspetti. AspectJ supporta sia una sintassi estesa basata su quella di Java sia una sintassi Java “pura” che usa le annotazioni per indicare i punti di taglio e i consigli di un aspetto. Il comportamento di un aspetto (definito nei consigli) può essere incorporato nel codice bersaglio a tempo di compilazione, o in un passo di “introduzione” successivo alla compilazione, o ancora nel momento in cui le classi vengono caricate dalla macchina virtuale sottostante.

Astrazione

Lo stato esternamente visibile di un tipo, insieme alle trasformazioni di stato e alle altre operazioni che il tipo supporta. Questi elementi sono separati rispetto all’implementazione incapsulata dell’astrazione, in termini di campi e metodi. In Scala, i tratti e le classi astratte vengono spesso usati per definire astrazioni e a volte per implementarle parzialmente; i tipi concreti forniscono implementazioni complete.

Attore

Nel modello di concorrenza ad attori, un’entità autonoma capace di inviare e ricevere messaggi.

Attributo

Un altro nome per indicare un campo, usato per convenzione in molti linguaggi di programmazione orientati agli oggetti. Scala segue invece la convenzione Java, preferendo il termine campo al termine attributo.

Campo

In un tipo, una dichiarazione val o var che rappresenta, tutto o in parte, lo stato di un’istanza di quel tipo.

Cancellazione di tipo

Una proprietà del modello dei tipi generici adottato per la JVM. Quando si crea un tipo a partire da un tipo generico, l’informazione sui tipi specifici sostituiti ai parametri di tipo non viene memorizzata nel bytecode e quindi non è disponibile a tempo di esecuzione. Scala deve seguire lo stesso modello, perciò non è in grado di distinguere le istanze di List[String] da quelle di List[Int], per esempio. Si confronti con la voce Tipi reificati.

Caratteri operatore

Caratteri come <, *, &c. che non sono lettere, né cifre, né caratteri riservati come le parentesi tonde, le parentesi graffe, le parentesi quadre, il punto e virgola, i due punti, o la virgola. Questi caratteri possono essere usati nei nomi dei metodi per implementare una forma di sovraccarico degli operatori.

case

La parola chiave usata nelle espressioni di pattern matching per elaborare un oggetto attraverso un estrattore, un controllo di tipo, &c.

Chiusura

In Scala, si definisce chiusura un’istanza, creata a partire da un letterale funzione, in cui tutte le variabili libere presenti sono state legate a variabili con lo stesso nome visibili nell’ambito di definizione del letterale. In altre parole, l’istanza si “chiude” nel senso che le variabili libere vengono legate. Essendo istanze, le chiusure sono valori di prima classe, perciò possono essere passate ad altre funzioni per personalizzare il loro comportamento. Per esempio, List.foreach accetta una chiusura che viene applicata a ogni elemento della lista. Si vedano anche le voci Variabile legata e Letterale funzione.

Classe

Un modello per istanze che saranno dotate degli stessi campi, usati per rappresentare valori di stato, e degli stessi metodi. Le classi Scala supportano l’ereditarietà singola e zero o più mixin sotto forma di tratti. Si confronti con la voce Tipo.

Classe associata

Una classe dichiarata con lo stesso nome di un object e definita nello stesso file sorgente. Si veda anche la voce Oggetto associato.

Classe case

Una classe dichiarata con la parola chiave case, per la quale il compilatore Scala definisce automaticamente i metodi equals, hashCode e toString e crea un oggetto associato con un metodo factory apply e un metodo estrattore unapply. Le classi case sono particolarmente convenienti da usare nelle clausole delle espressioni di pattern matching.

Cliente

Un termine informale usato in tutto il libro per indicare una parte di codice che ne usa un’altra come API, &c.

Commenti

Per i commenti, Scala segue le stesse convenzioni di Java, C#, C++, &c. Un // commento prosegue fino al termine della riga, mentre un /* commento */ può essere distribuito su più righe.

Componente

Per i nostri scopi, un aggregato di tipi coesivi che espone servizi attraverso astrazioni ben definite, allo stesso tempo incapsulando i dettagli di implementazione e minimizzando le dipendenze nei confronti di altri componenti. Si noti che esiste un ampio spettro di definizioni per il termine componente sia in campo scientifico sia in campo industriale.

Concorrenza basata su eventi

Una forma di concorrenza ad alte prestazioni che prevede di segnalare i cambiamenti di stato significativi tramite eventi a cui si risponde usando un gestore (chiamato handler in inglese) appropriato.

Contratto

Il protocollo che regola l’interazione tra un modulo (per esempio, una classe, un tratto, un oggetto, o persino una funzione o un metodo) e i clienti del modulo. Per maggiori dettagli, si veda la voce Progettazione per contratto.

Controfigura

Quando si collauda il comportamento di un oggetto, una controfigura è un altro oggetto che soddisfa una dipendenza dell’oggetto sottoposto al collaudo. La controfigura può essere d’aiuto nel processo di collaudo, offrendo dati e comportamenti cablati e modificando la propria interazione con l’oggetto in maniera controllata. Tipi specifici di controfigura includono i “simulatori” (in inglese, fake), gli oggetti “finti” (in inglese, mock) e i “fantocci” (in inglese, stub).

Controvarianza o controvariante

Nel contesto del comportamento di varianza per i tipi parametrici in caso di ereditarietà, se un parametro A in un tipo parametrico T[-A] è controvariante, allora - è l’annotazione di varianza e il tipo T[B] è un supertipo di T[A] se B è un sottotipo di A. Si vedano anche le voci Covarianza e Invarianza.

Conversione di tipo implicita

Un metodo o un valore funzione contrassegnato dalla parola chiave implicit che lo identifica come idoneo a essere usato per convertire implicitamente un tipo in un altro ogni volta che è necessaria una conversione nell’ambito di visibilità che lo contiene (per esempio, si veda il pattern Pimp my library).

Costruttore ausiliario

Un costruttore secondario di una classe, dichiarato come un metodo di nome this senza tipo di ritorno. Come prima (o unica) istruzione, un costruttore ausiliario deve invocare il costruttore principale o un costruttore ausiliario precedentemente definito.

Costruttore di tipo

Informalmente, un tipo parametrico viene talvolta chiamato costruttore di tipo, sebbene anche i tipi “non parametrici” siano in realtà costruttori di tipo, ma privi di parametri. La creazione di un nuovo tipo concreto, che avviene specificando tipi concreti particolari per i parametri di tipo, è analoga alla creazione di una nuova istanza, che avviene specificando gli argomenti per i parametri del costruttore.

Costruttore principale

Il costruttore principale di una classe: il suo corpo è il corpo della classe, e la sua lista di parametri viene specificata dopo il nome della classe. Si veda anche la voce Costruttore ausiliario.

Covarianza o covariante

Nel contesto del comportamento di varianza dei tipi parametrici in caso di ereditarietà, se un parametro A in un tipo parametrico T[+A] è covariante, allora + è l’annotazione di varianza e un tipo T[B] è un sottotipo di T[A] se B è un sottotipo di A. Si vedano anche le voci Controvarianza e Invarianza.

Currying

La trasformazione di una funzione a N argomenti in una sequenza di N funzioni a un argomento ognuna delle quali (tranne l’ultima) restituisce una nuova funzione che accetta un singolo argomento e restituisce una nuova funzione, e così via, fino all’ultima funzione che accetta un singolo argomento e restituisce un valore.

Descrizione for

Un altro nome per le espressioni for di Scala.

Designatori di tipo

Gli identificatori convenzionali di tipo usati comunemente, come class Person, object O { type t }, &c. Rappresentano a tutti gli effetti una notazione abbreviata per le proiezioni di tipo.

Duck typing

Un termine usato per indicare il funzionamento della risoluzione dei metodi in un linguaggio dinamicamente tipato. Per soddisfare l’interprete, è sufficiente che un oggetto accetti l’invocazione di un metodo (l’invio di un messaggio). “Se cammina come un’anatra e fa il verso dell’anatra, allora è un’anatra!” Lo si confronti con l’uso dei tipi strutturali in alcuni linguaggi staticamente tipati come Scala.

Entità di prima classe

Una “entità” è di prima classe in un linguaggio quando potete usarne le istanze per assegnarle alle variabili, passarle come parametri e restituirle come valore di ritorno da una funzione. L’espressione viene spesso usata per fare riferimento alle funzioni, che sono valori di prima classe in Scala e nella programmazione funzionale in generale.

Ereditarietà

Una forte relazione tra una classe o un tratto e un’altra classe o un altro tratto. La classe o il tratto derivato incorpora i membri della classe o del tratto genitore come se fossero stati definiti nel derivato. Nella maggior parte dei casi, il derivato può ridefinire i membri ereditati. Le istanze del derivato sono sostituibili alle istanze del genitore.

Ereditarietà multipla

In alcuni linguaggi, escluso Scala, un tipo può estendere più di una classe genitore. Si confronti con la voce Ereditarietà singola.

Ereditarietà singola

Una classe, oggetto, o tratto può estendere solo una classe genitore. Si confronti con la voce Ereditarietà multipla.

Estrattore

Un metodo unapply, definito in un oggetto associato, usato per estrarre i valori dei campi di un oggetto. Di solito viene usato nelle espressioni di pattern matching.

Evento

Nella concorrenza basata su eventi, la notifica di un cambiamento di stato.

final

Parola chiave usata nelle dichiarazioni: per i tipi, final ne impedisce l’estensione; per i membri di tipo, final ne impedisce la ridefinizione.

Firma

Per una funzione, comprende il nome, i tipi dei parametri e il tipo di ritorno. Per un metodo, la firma include anche il tipo in cui è definito.

Funzione

In Scala, il termine funzione viene usato per indicare la definizione di una operazione che non è legata a un oggetto o a una classe particolare. Si confronti con la voce Metodo. Le funzioni sono istanze dei tipi FunctionN, dove N è l’arità della funzione.

Funzione parziale

Una funzione che non è valida per l’intero insieme di valori dei suoi argomenti. A seconda del contesto, il compilatore può convertire le espressioni di pattern matching in funzioni parziali.

Funzioni di ordine superiore

Funzioni che accettano altre funzioni come argomenti o restituiscono un valore funzione.

Funzioni sovraccaricate

Due o più funzioni, definite nello stesso ambito (per esempio, come metodi in un tipo o come funzioni “pure”), che hanno lo stesso nome ma firme diverse.

Generatore

Espressioni come i <- listaDiInt nelle descrizioni for. In questo esempio, ogni passaggio attraverso il ciclo genera un nuovo valore i preso dalla listaDiInt.

Generici

Un altro termine per indicare i tipi parametrici, usato più spesso in Java che in Scala.

Grammatica libera dal contesto

Nei linguaggi di programmazione, un tipo di grammatica in cui ogni simbolo non terminale può essere specificato tramite una produzione priva di riferimenti a informazioni di contesto aggiuntive. In altre parole, un simbolo non terminale può apparire da solo nella parte sinistra della produzione che lo specifica.

Grammatiche di espressioni analitiche

Chiamate parsing expression grammars (PEG) in inglese, rappresentano un’alternativa alle grammatiche libere da contesto che offre la garanzia di un tempo di riconoscimento lineare sfruttando la memoizzazione e l’assenza di ambiguità nelle espressioni [PEG].

implicit

Una parola chiave di Scala usata per segnalare l’idoneità di un metodo o di una funzione al ruolo di conversione di tipo implicita. La parola chiave viene anche usata per indicare un argomento implicito.

Incapsulamento

La restrizione della visibilità dei membri di un tipo al fine di renderli invisibili ai clienti del tipo quando dovrebbero essere tali. Così facendo, il tipo espone solo l’astrazione che supporta, nascondendo i dettagli di implementazione in modo da evitare accessi indesiderati da parte dei clienti, e preservando la coerenza e la minimalità dell’astrazione esposta.

Inferenza di tipo

Desumere il tipo di un valore sulla base del contesto in cui viene usato anziché affidarsi ad annotazioni di tipo esplicite. A volte viene chiamata tipizzazione implicita.

Iniezione di dipendenza

Una forma di inversione del controllo nella quale un oggetto riceve le proprie dipendenze esterne in maniera programmatica o attraverso un framework guidato da informazioni di configurazione. Perciò, l’oggetto rimane “passivo” piuttosto che assumere un ruolo attivo nel risolvere le dipendenze. Il meccanismo di iniezione usa gli argomenti del costruttore o i metodi forniti dall’oggetto per impostare il valore dei campi. L’iniezione di dipendenza riduce al minimo l’accoppiamento tra gli oggetti, obbligati a conoscere solo le astrazioni da cui dipendono anziché le loro implementazioni concrete.

Interessi trasversali

“Interessi” (certi tipi di requisiti e di questioni progettuali o implementative) che non rientrano nei confini della decomposizione modulare principale, pur rappresentando comportamenti che devono essere invocati coerentemente su un insieme di oggetti e funzioni in momenti specifici nel corso dell’esecuzione. Per esempio, la stessa strategia di persistenza basata su un ORM (acronimo dell’inglese Object-Relational Mapping) deve essere applicata in maniera sistematica a un insieme di classi, non solo a una singola classe. Perciò, tali “interessi” vengono chiamati “trasversali”. Dovrebbero essere gestiti senza ricorrere a espedienti come duplicazione di codice, &c. Si veda anche la voce Programmazione orientata agli aspetti.

Invarianza e invariante

Nel contesto del comportamento di varianza per i tipi parametrici in caso di ereditarietà, se un parametro A in un tipo parametrico T[A] è invariante allora non è presente alcuna annotazione di varianza e un tipo T[B] è un sottotipo di T[A] se e solo se B è uguale ad A. Questo significa che i tipi non possono essere cambiati. Si vedano anche le voci Covarianza e Controvarianza.

Nel contesto della progettazione per contratto, viene chiamata invariante un’asserzione che dovrebbe essere vera prima e dopo l’esecuzione di un metodo.

Inversione del controllo

L’idea che un oggetto non dovrebbe istanziare una copia delle proprie dipendenze esterne, ma piuttosto ottenerle affidandosi ad altri meccanismi. L’inversione del controllo promuove un disaccoppiamento migliore e favorisce la testabilità, poiché gli oggetti conoscono solo le astrazioni da cui dipendono anziché le specifiche implementazioni concrete delle dipendenze. L’inversione del controllo si presenta in forma debole quando un oggetto, invocando una factory, un localizzatore di servizio, &c. per ottenere le dipendenze, assume ancora un ruolo attivo e rimane accoppiato al “fornitore”. La forma più forte di inversione del controllo è l’iniezione di dipendenza, dove l’oggetto resta “passivo”.

Invocazione per nome

Si veda la voce Parametro per nome.

Invocazione per valore

Si veda la voce Parametro per valore.

Istanza o istanziare

Un oggetto creato invocando il costruttore di una classe. La parola oggetto è sinonimo di istanza nella maggior parte dei linguaggi orientati agli oggetti, ma in Scala il termine oggetto viene usato per fare riferimento a un object dichiarato esplicitamente, mentre il termine istanza (insieme al verbo istanziare) viene riservato per il caso più generale.

L’istanziazione può anche riferirsi alla creazione di un tipo concreto a partire da un tipo parametrico, effettuata specificando i tipi concreti per i parametri di tipo.

lazy

Le variabili immutabili (val) possono essere dichiarate lazy per segnalare che verranno valutate solo al momento di leggerle. Questa funzionalità è utile per differire elaborazioni costose che potrebbero non essere necessarie.

Le strutture dati ritardate, cioè dichiarate come lazy, si possono anche usare per definire strutture dati infinite in grado di evitare l’esaurimento delle risorse di sistema fino a quando viene valutato solo un sottoinsieme finito della struttura. Le classi Stream e Range sono entrambe a valutazione ritardata. Si confronti con la voce Rigoroso.

Letterale

Usato per fare riferimento a espressioni di valori “letterali”, come numeri (per esempio 1, 3.14), stringhe (per esempio "Ciao Scala"), tuple (per esempio, (1, 2, 3)) e letterali funzione (per esempio, (x) => x + x).

Letterale funzione

Il termine usato in Scala per indicare un’espressione di funzione anonima da cui vengono create le chiusure.

Limiti di tipo

Vincoli sull’insieme di tipi permessi che è possibile usare per un parametro in un tipo parametrico o assegnare a un tipo astratto. In Scala, l’espressione A <: B definisce un limite superiore su A, vincolandolo a essere un sottotipo di B o uguale a B. L’espressione A >: B definisce un limite inferiore su A, vincolandolo a essere un supertipo di B o uguale a B.

Limiti di vista

Una specifica di tipo della forma A <% B, che consente di usare qualsiasi tipo per A a condizione che nell’ambito di visibilità sia presente una vista in grado di convertire un’istanza di A in un’istanza di B.

Limiti inferiori di tipo

Si veda la voce Limiti di tipo.

Limiti superiori di tipo

Si veda la voce Limiti di tipo.

Linearizzazione

L’algoritmo usato per risolvere le priorità nella ricerca di un membro in un tipo, come nel caso della ridefinizione dei metodi, incluse le invocazioni a super.

Linguaggio domain-specific

Un linguaggio di programmazione personalizzato che assomiglia ai termini, agli idiomi e alle espressioni di un particolare dominio. Un DSL interno è una forma idiomatica di un linguaggio di programmazione generico: non è necessario creare un riconoscitore particolare per il DSL poiché il codice viene scritto nel linguaggio generico e riconosciuto come tale. Un DSL esterno è un linguaggio con una propria grammatica e un proprio riconoscitore.

Mailbox

Nel modello di concorrenza ad attori, la coda in cui un attore memorizza i propri messaggi fino a quando non decide di elaborarli.

main

Il punto di entrata di un’applicazione invocato dall’interprete viene chiamato main, secondo una convenzione nominale che risale al linguaggio C. In Scala, il metodo main deve essere definito in un object. Java, al contrario, richiede che il metodo main sia definito come un metodo statico in una classe.

MapReduce

Una strategia dividi-e-conquista per elaborare in parallelo insiemi di dati di grandi dimensioni. Nella fase di “mappatura” i dati vengono suddivisi in sottoinsiemi su cui effettuare i calcoli desiderati. Nella fase di “riduzione” i risultati dei calcoli sui sottoinsiemi vengono combinati nel risultato finale. I framework MapReduce si occupano dei dettagli riguardanti la gestione delle operazioni e dei nodi su cui vengono eseguite, compreso il riavvio delle operazioni che falliscono per qualche ragione. L’utente del framework deve solo scrivere gli algoritmi per mappare e ridurre gli insiemi di dati ed effettuare i calcoli sui sottoinsiemi.

Membro

Un termine generico per un tipo, campo, o metodo dichiarato in una classe o in un tratto.

Memoizzazione

Una tecnica per ottimizzare l’invocazione delle funzioni tramite l’uso di una cache. I risultati delle invocazioni di una funzione vengono memorizzati in modo che, al ripetersi di un’invocazione con gli stessi ingressi, sia possibile restituire il risultato salvato anziché invocare nuovamente la funzione.

Messaggio

Nel modello di concorrenza ad attori, lo scambio di messaggi è il meccanismo usato dagli attori per coordinarsi tra loro.

Nella programmazione orientata agli oggetti, l’invocazione di un metodo viene talvolta chiamata “invio di un messaggio a un oggetto”, specialmente in certi linguaggi come Smalltalk e, in una certa misura, Ruby.

Metodo

Una funzione, definita in una classe, in un tratto, o in un oggetto, che viene associata esclusivamente a un’istanza. I metodi possono essere invocati solo tramite la sintassi oggetto.metodo.

Mixin

Un’astrazione estremamente specializzata che incapsula stato e comportamento più adatti a completare quelli di un altro oggetto piuttosto che a esistere in isolamento. In Scala i mixin vengono implementati usando i tratti.

Modello di concorrenza ad attori

Un modello di concorrenza in cui attori autonomi si coordinano tra loro scambiando messaggi. Un attore memorizza i propri messaggi in una mailbox fino a quando non decide di elaborarli.

Notazione infissa

Una sintassi supportata dal compilatore per invocare metodi con un solo argomento senza inserire il punto tra l’oggetto e il nome del metodo e senza aggiungere le parentesi attorno all’argomento. Quando viene usata con metodi il cui nome è composto esclusivamente da caratteri operatore, la sintassi offre una forma di sovraccarico degli operatori. A volte viene chiamata notazione operazionale. Si veda anche la voce Notazione postfissa.

Notazione operazionale

Si veda la voce Notazione infissa.

Notazione postfissa

Una sintassi supportata dal compilatore per i metodi senza argomenti, a volte chiamati metodi ad arità zero. Il metodo può essere invocato omettendo il punto tra il suo nome e l’oggetto. Si veda anche la voce Notazione infissa.

Oggetti package

Un genere speciale di oggetti contenenti dichiarazioni di membri che dovrebbero esere visibili nell’ambito del package definito. Per esempio, grazie alla dichiarazione package object math { type Complex = … }, è possibile fare riferimento al tipo Complex usando il nome math.Complex. Disponibili solo in Scala 2.8.

Oggetto

Un’unità coesiva con un particolare stato, possibili transizioni di stato, e specifici comportamenti. In Scala la parola chiave object viene usata per dichiarare esplicitamente un oggetto singleton tramite la stessa sintassi delle dichiarazioni di classe, eccetto che per l’assenza di parametri nel costruttore e di costruttori ausiliari (in quanto gli object vengono istanziati dalla macchina virtuale sottostante, non dal programmatore nel proprio codice). Per evitare di confondere i significati di oggetto, si usa il termine istanza per fare riferimento in modo generico sia alle istanze di classi sia agli object.

Oggetto associato

Un object dichiarato con lo stesso nome di una classe (che viene considerata la sua classe associata) e definito nello stesso file sorgente. Gli oggetti associati sono il luogo deputato alla definizione di metodi e campi che sarebbero statici nelle classi Java, come i metodi factory, i metodi apply e unapply sfruttati dal pattern matching, &c.

Oggetto valore

Un oggetto o istanza immutabile.

Paradigma dichiarativo

Lo stile proprio di molti linguaggi funzionali e domain-specific dove i programmi sono formati da istruzioni che esprimono relazioni tra valori e tipi piuttosto che da una particolare sequenza di azioni attraverso la quale guidare il sistema. Si confronti con la voce Paradigma imperativo.

Paradigma imperativo

Lo stile di molti linguaggi orientati agli oggetti e “procedurali” dove i programmi consistono di istruzioni che guidano il sistema attraverso una particolare sequenza di azioni. Si confronti con la voce Paradigma dichiarativo.

Parametro formale

Un altro nome per indicare un argomento di una funzione, usato nella descrizione dei legami per le variabili libere contenute nella funzione.

Parametro per nome

Un parametro per nome somiglia a un valore funzione che non accetta argomenti, ma anziché essere dichiarato con la firma p: () => R, dove R è il tipo di ritorno, è dichiarato con la firma p: => R. I parametri per nome vengono valutati ogni volta che la funzione vi fa riferimento, anziché essere valutati una sola volta appena prima di invocare la funzione, come accade ai parametri per valore. Più che nelle dichiarazioni di funzione con argomenti espliciti per i parametri, si rivelano utili per progettare funzioni le cui invocazioni assomiglino a un costrutto di controllo che accetta un “blocco” (si pensi all’aspetto di un ciclo while, per esempio): in questo caso, l’argomento con il comportamento simile a un blocco verrebbe ricevuto da un parametro per nome.

Parametro per valore

Un parametro per valore è il tipico genere di parametro di un metodo il cui argomento corrispondente viene valutato prima di essere ricevuto. Si confronti con la voce Parametro per nome.

Pattern di progettazione

Una soluzione a un problema immerso nel suo contesto. Un idioma o una struttura di codice che soddisfa i requisiti di un problema, di un vincolo, di una condizione, &c. che ricorre di frequente in un certo ambito.

Pattern matching

Espressioni case, di solito racchiuse in una espressione match, che elaborano un oggetto attraverso confronti di tipo, estrattori, espressioni regolari, &c. per determinare come gestirlo in modo opportuno.

Pimp my library

Il nome di un pattern di progettazione usato per dare l’illusione che siano stati aggiunti nuovi metodi a un tipo. Sfrutta una conversione di tipo implicita per racchiudere automaticamente il tipo in un tipo avvolgente nel caso in cui il tipo avvolgente disponga dei metodi desiderati.

Postcondizione

Un’asserzione che dovrebbe essere vera nel momento in cui si esce da un metodo o da un’altra entità computazionale. Si veda la voce Progettazione per contratto.

Precondizione

Un’asserzione che dovrebbe essere vera nel momento in cui si entra in un metodo o in un’altra entità computazionale. Si veda la voce Progettazione per contratto.

Prive di effetti collaterali

Funzioni o espressioni che non hanno effetti collaterali, nel senso che non modificano né lo stato globale né quello di alcun oggetto.

Produzione

Un termine usato per ogni parte di una grammatica che decompone uno specifico simbolo non terminale in altri simboli non terminali (tra cui è possibile includere un riferimento ricorsivo al simbolo originale) e simboli terminali.

Progettazione per contratto

Una metodologia di progettazione per classi e moduli inventata da Bertrand Meyer per il linguaggio Eiffel. Per ogni entità computazionale si specifica in modo programmatico l’insieme degli ingressi validi, in modo che sia possibile effettuare la verifica di queste precondizioni durante il collaudo. Similmente, supponendo che le precondizioni siano rispettate, è possibile garantire che i risultati rispettino certe specifiche espresse in modo eseguibile, chiamate postcondizioni. Si possono anche specificare invarianti che dovrebbero essere vere sia prima che l’entità esegua le sue operazioni sia dopo.

Programmazione funzionale

Una forma di programmazione che imita la natura di variabili e funzioni matematiche: le prime vengono assegnate una sola volta; le seconde sono prive di effetti collaterali, si possono comporre a partire da altre funzioni, possono essere assegnate a variabili e restituite da altre funzioni.

Programmazione orientata agli aspetti (AOP)

Una metodologia di sviluppo per progettare e implementare gli interessi trasversali in modo “modulare” (incapsulandoli correttamente, senza duplicazione di codice, &c.) e poi integrarli in tutti i punti di esecuzione rilevanti in modo robusto e conciso, attraverso meccanismi di tipo dichiarativo o imperativo. Nella terminologia AOP i punti di esecuzione vengono chiamati punti di unione, un insieme di punti di unione viene chiamato punto di taglio e il nuovo comportamento che viene invocato prima, dopo, o “durante” l’esecuzione di un punto di unione viene chiamato consiglio. AspectJ [AspectJ] è lo strumento AOP più noto. I tratti di Scala possono essere usati per implementare funzionalità simili agli aspetti.

Programmazione orientata agli oggetti (OOP)

Una forma di programmazione in cui i valori di stato e le operazioni su quello stato vengono incapsulati in un’entità chiamata oggetto che espone un’astrazione coerente ai propri clienti e allo stesso tempo nasconde i dettagli interni della propria implementazione. La OOP supporta anche la nozione di ereditarietà per definire specializzazioni e relazioni “familiari” tra i tipi.

Proiezioni di tipo

Riferimenti a un tipo annidato all’interno di un altro tipo: per esempio, se un tipo t è dichiarato in una classe C, allora la proiezione di tipo per t è C#t.

Punto di dichiarazione

Indica una possibile posizione in cui specificare il comportamento di varianza dei tipi parametrici. In Scala tale comportamento si indica quando i tipi vengono dichiarati, cioè nel punto di dichiarazione, mentre in Java va fatto quando i tipi vengono invocati (cioè usati), quindi nel punto di invocazione.

Punto di invocazione

Si veda la voce Punto di dichiarazione.

Pura

Usata nel contesto delle funzioni per denotare che sono prive di effetti collaterali. Si veda anche la voce Trasparenza referenziale.

Raffinamento

Il termine usato per indicare l’aggiunta o la ridefinizione dei membri nel corpo di un tipo per un tipo composto.

REPL

Un nome dato agli ambienti interattivi di un linguaggio, come il comando scala in modalità interattiva. REPL è l’acronimo di Read-Evaluate-Print Loop (ciclo di lettura-valutazione-stampa).

Riconoscitori spazzino

Automi in grado di riconoscere le grammatiche di espressioni analitiche [Ford], caratterizzati da mancanza di ambiguità e buone prestazioni. La libreria di riconoscimento combinatorio inclusa in Scala 2.8 aggiungerà il supporto per la creazione di riconoscitori spazzino (chiamati packrat parsers in inglese).

Ricorsione

L’atto, compiuto da una funzione, di invocare se stessa come parte della propria computazione. È necessario specificare una condizione di terminazione per evitare una ricorsione infinita. Si veda anche la voce Ricorsione in coda.

Ricorsione in coda

Una forma di ricorsione in cui una funzione invoca se stessa come ultima istruzione, cioè senza effettuare ulteriori operazioni sul risultato della invocazione ricorsiva. Il compilatore Scala ottimizzerà le funzioni ricorsive in coda trasformandole in un ciclo.

Rigoroso

Termine che si riferisce a strutture dati non ritardate, cioè definite compiutamente dalle espressioni usate per costruirle.

Scaladoc

La documentazione delle API generata a partire dal codice sorgente Scala tramite lo strumento scaladoc, analoga alla documentazione Javadoc di Java.

sealed

Parola chiave da usare su una classe genitore che desidera vincolare tutte le definizioni di sottoclassi dirette a trovarsi nello stesso file sorgente che la contiene.

Simbolo

Una stringa internata. I letterali simbolo vengono scritti usando un singolo apice, come in 'nome.

Simbolo non terminale

Un elemento di una grammatica che richiede una ulteriore decomposizione in uno o più simboli non terminali (inclusa la possibilità di un riferimento ricorsivo a se stesso) e simboli terminali.

Simbolo terminale

Un lessema di una grammatica, per esempio una parola chiave, che non richiede decomposizioni ulteriori. Si veda anche la voce Simbolo non terminale.

Singleton

Una classe di cui esiste una sola istanza. In Scala, le classi singleton vengono dichiarate usando la parola chiave object anziché class.

Sottotipo

Un sinonimo di tipo derivato.

Sovraccarico degli operatori

La caratteristica di alcuni linguaggi in cui gli operatori matematici classici come *, /, <, &c. possono essere ridefiniti dai programmatori per i propri tipi personalizzati. Scala supporta una forma di sovraccarico degli operatori ammettendo la presenza di caratteri operatore nei nomi dei metodi e l’uso della notazione infissa per invocare i metodi con un solo argomento. La “precedenza tra gli operatori” per questi metodi è determinata dal primo carattere: per esempio, il metodo *< avrà precedenza più alta rispetto al metodo +<.

Stato

Termine usato in espressioni come “lo stato di un oggetto”, dove informalmente indica l’insieme di tutti i valori correnti dei campi di un oggetto.

Struttura dati infinita

Una struttura dati che rappresenta una collezione di valori senza termine, in grado di farlo senza esaurire le risorse di sistema. I singoli valori vengono calcolati solo su richiesta. Fino a quando si richiedono sottoinsiemi finiti di valori, è possibile evitare l’esaurimento delle risorse di sistema.

Supertipo

Un sinonimo di tipo genitore.

Sviluppo guidato dal collaudo

Una disciplina di sviluppo in cui non si implementa nessuna nuova funzionalità fino a quando non viene scritto un test che avrà successo una volta che la funzionalità sia stata implementata. Si veda anche la voce Sviluppo guidato dal comportamento.

Sviluppo guidato dal comportamento

Uno stile di sviluppo guidato dal collaudo (TDD) che enfatizza il ruolo dei test come guida per la comprensione dei requisiti di un programma. Segue lo stesso processo del TDD, nel senso che i “test” vengono scritti prima del codice. La differenza risiede nel formato in cui vengono scritti i test, che li rende più simili a specifiche dei requisiti (o del comportamento) che a verifiche di conformità del codice ai requisiti, pur rimanendo eseguibile. Le specifiche vengono utilizzate per le attività di verifica, valutazione e regressione che nel TDD coinvolgono i test.

Tipi esistenziali

Espressioni che segnalano la presenza di un tipo senza indicarne il valore concreto, a volte perché non può essere noto. Vengono usati principalmente per supportare alcuni aspetti del sistema di tipi di Java all’interno di quello di Scala, compresi la cancellazione di tipo, i tipi “grezzi” (per esempio, le collezioni precedenti a Java 5) e la varianza di tipo nel punto di invocazione.

Tipi parametrici

L’analogo Scala dei generici Java. I tipi parametrici vengono definiti usando nomi segnaposto per i parametri di tipo. Per creare un’istanza di un tipo parametrico è necessario indicare i tipi specifici che sostituiranno i segnaposto come parametri di tipo. Si veda anche la voce Costruttore di tipo.

Tipi reificati

Tipi generici che conservano nel bytecode l’informazione sui tipi specifici usati per istanziarli, in modo che sia disponibile a tempo di esecuzione. Questa è una caratteristica esclusiva del bytecode .NET, poiché la JVM usa la cancellazione di tipo, costringendo così anche la versione .NET di Scala ad adottarla per minimizzare le incompatibilità con la versione Java.

Tipi singleton

Il designatore di tipo unico che omette le dipendenze dal percorso. Se p1 e p2 sono due tipi dipendenti dal percorso differenti, i loro tipi singleton p1.type e p2.type potrebbero essere uguali. Si confronti con la voce Singleton relativa agli oggetti. In particolare, si noti che i tipi singleton non sono i tipi degli oggetti singleton, ma gli oggetti singleton sono dotati di un tipo singleton.

Tipi stabili

Nel contesto dei tipi dipendenti dal percorso, tutti gli elementi di un percorso tranne l’ultimo devono essere stabili: a grandi linee, ciò significa che devono essere package oppure oggetti singleton, o dichiarazioni di tipo usate come alias di queste due entità.

Tipizzazione dinamica

Parlando per sommi capi, la proprietà di un linguaggio in cui le informazioni di tipo vengono associate durante l’esecuzione. Si dice anche che il tipo viene legato al valore assegnato a un riferimento piuttosto che al riferimento stesso. Si confronti con la voce Tipizzazione statica.

Tipizzazione statica

Parlando per sommi capi, la proprietà di un linguaggio in cui le informazioni di tipo vengono associate durante la compilazione. Si dice anche che il tipo viene legato a un riferimento piuttosto che al valore assegnato al riferimento.

Tipo

Una categorizzazione di stati permessi e operazioni su quegli stati, incluse transizioni da uno stato all’altro. Il tipo di un’istanza è la combinazione delle sua classe dichiarata (nominata esplicitamente oppure anonima), dei tratti mescolati e dei tipi specifici usati per sostituire qualsiasi parametro di tipo se la classe o i tratti sono tipi parametrici. In Scala, type è anche una parola chiave. Dove indicato nel testo, a volte abbiamo usato il termine tipo per fare riferimento in modo generico a una classe, a un oggetto, o a un tratto.

Tipo annotato

Qualsiasi tipo a cui siano state applicate una o più annotazioni (precedute dal carattere @).

Tipo astratto

Una classe o un tratto con uno o più metodi, campi, o tipi dichiarati ma indefiniti. I tipi astratti non possono essere istanziati. Si confronti con la voce Tipo concreto.

Una dichiarazione type all’interno di una classe o di un tratto astratti.

Tipo base

Un sinonimo di tipo genitore.

Tipo composto

Il tipo reale di una dichiarazione della forma T1 extends T2 with T3 with … TN { R }, dove R è il raffinamento (corpo). Le definizioni contenute in R influenzano il tipo.

Tipo concreto

Una classe, un tratto, o un oggetto i cui metodi, campi e tipi siano tutti definiti. Dai tipi concreti è possibile creare istanze. Si confronti con la voce Tipo astratto.

Tipo derivato

Un sinonimo per tipo figlio

Tipo dipendente dal percorso

Un tipo annidato T è unico sulla base del proprio “percorso”, l’elenco gerarchico e intervallato da punti formato dal package e dai tipi che racchiudono il tipo T e infine dal tipo T stesso. Le istanze di T possono avere tipi diversi e incompatibili tra loro: per esempio, se T è annidato in un tratto e il tratto compare nella linearizzazione di tipi differenti, allora le istanze di quei tipi T saranno di tipo diverso.

Tipo figlio

Una classe o un tratto che estende una classe o un tratto genitore. A volte viene chiamato sottotipo o tipo derivato. Si veda la voce Ereditarietà.

Tipo funzione

In Scala, tutte le funzioni sono istanze dei tipi FunctionN[-T1, -T2, …, -TN, +R], dove N è il numero di parametri (ne sono supportati da 0 fino a 22). La sintassi (T1, T2, …, TN) => R per la firma del tipo viene usata per dichiarare istanze concrete, cioè letterali funzione.

Tipo genitore

Una classe o un tratto da cui è derivata un’altra classe o un altro tratto. Viene anche chiamato supertipo o tipo base. Si veda la voce Ereditarietà.

Tipo infisso

Quando un tipo parametrico della forma Op[A,B] viene usato per istanziare un tipo, può anche essere scritto come A Op B. Per esempio, Or[Throwable,Boolean] può essere scritto come Throwable Or Boolean.

Tipo primitivo

Un tipo che non è un oggetto per la macchina virtuale sottostante (JVM o CLR). Scala non ha tipi primitivi a livello del codice sorgente, ma usa i tipi valore, che sono sottoclassi di AnyVal, per avvolgere i tipi primitivi della macchina virtuale, offrendo loro una semantica da oggetto a livello del codice e sfruttando le operazioni di trasformazione tra tipi primitivi e tipi oggetto a livello di bytecode per ottimizzare le prestazioni.

Tipo riferimento

Un tipo le cui istanze sono implementate come oggetti dalla macchina virtuale sottostante. Tutti i tipi riferimento estendono AnyRef.

Tipo strutturale

Un tipo strutturale è come un tipo anonimo: specifica solo la “struttura” che un tipo candidato deve supportare, per esempio i membri che devono essere presenti. I tipi strutturali non nominano i tipi candidati a cui portrebbero corrispondere, né i tipi candidati devono condividere un tratto o una classe genitore comune con il tipo strutturale. Perciò, i tipi strutturali si possono considerare l’analogo type-safe del duck typing presente nei linguaggi dinamicamente tipati come Ruby.

Tipo valore

Una sottoclasse di AnyVal che avvolge il corrispondente tipo “primitivo” della macchina virtuale sottostante (JVM o CLR). I tipi valore sono Boolean, Char, Byte, Double, Float, Long, Int e Short. (Anche Unit è un tipo valore.) Tutti sono dichiarati abstract final in modo da non poter essere usati in espressioni come new V. Invece, i programmatori devono specificarne i valori letterali, come 3.14 per un’istanza di Double, o ricorrere ai metodi che restituiscono nuovi valori, ed è l’interprete Scala a gestire l’istanziazione di queste sottoclassi. Tutte le istanze di tipi valore sono oggetti valore immutabili.

Il termine tipo valore viene anche usato per indicare le diverse categorie a cui il tipo di ogni istanza deve appartenere: tipi annotati, tipi composti, tipi funzione, tipi infissi, tipi parametrici, tuple, designatori di tipo, proiezioni di tipo, tipi singleton.

Trampolino

Un ciclo che scorre una lista di funzioni, invocandole tutte una per una. Il nome deriva dalla metafora di lanciare le funzioni da un trampolino. Può essere usato per riscrivere una forma di ricorsione in cui una funzione non invoca se stessa ma una funzione diversa che richiama quella originale, e così via, avanti e indietro. Esiste una proposta per includere un’implementazione del trampolino nel compilatore di Scala 2.8.

Trasparenza referenziale

La proprietà di un’espressione, come una funzione, che può essere sostituita con il suo valore senza modificare il comportamento del codice. La sostituzione può avvenire quando le funzioni sono prive di effetti collaterali e gli argomenti con cui vengono invocate sono gli stessi. Il vantaggio principale della trasparenza referenziale consiste nel semplificare il ragionamento sul comportamento di una funzione, rendendo superflua la comprensione del contesto in cui viene invocata. In questo modo, le funzioni sono anche più facili da collaudare, riorganizzare e riutilizzare.

Tratto

Un’entità che incapsula stato (campi) e comportamento (metodi) in modo simile a una classe, ma usata per la composizione dei mixin. È possibile mescolare zero o più tratti nelle dichiarazioni di classe o direttamente nelle istanze, determinando la creazione, in quest’ultimo caso, di una classe anonima.

Tupla

Un raggruppamento di due o più elementi di tipi arbitrari, simile a un “prodotto cartesiano”, da usare senza l’obbligo di definire prima la classe che li contiene. I valori tupla letterali vengono scritti tra parentesi e separati da virgole, come in (x1, x2, … xN). Sono valori di prima classe, quindi potete assegnarli a variabili e usarli come argomenti o valori di ritorno di una funzione. Le tuple sono rappresentate dalle classi TupleN, per N che va da 2 a 22, estremi inclusi.

Valore

Lo stato effettivo di un’istanza. Il termine di solito viene usato quando si parla di una variabile che fa riferimento all’istanza. Si veda anche la voce Tipo valore.

Valore immutabile

Un valore che non può essere modificato dopo essere stato inizializzato. Si confronti con la voce Valore mutabile.

Valore mutabile

Un valore che può essere modificato dopo essere stato inizializzato. Si confronti con la voce Valore immutabile.

Valore predefinito di un argomento

Un valore che verrà usato per un argomento di un metodo se il chiamante non ne specifica uno. Disponibile solo in Scala 2.8. Si vedano anche le voci Argomento implicito e Argomento con nome.

Variabile

Un riferimento con nome a un valore. Se la variabile viene dichiarata con la parola chiave val non è possibile assegnarvi un nuovo valore, se la dichiarazione viene effettuata con la parola chiave var è possibile assegnare un nuovo valore alla variabile. Il valore a cui una variabile fa riferimento deve essere di tipo compatibile con il tipo dichiarato o inferito per la variabile.

Variabile legata

Una variabile dichiarata come argomento di un letterale funzione che viene “legata” a un valore quando la chiusura creata a partire dal letterale funzione viene invocata.

Variabile libera

Una variabile a cui il corpo di un letterale funzione fa riferimento, ma che non è stata passata come argomento. Di conseguenza, deve essere “legata” a una variabile con lo stesso nome definita nell’ambito in cui il letterale funzione è stato definito, in modo da formare una chiusura.

Varianza di tipo

Quando si dichiara un tipo parametrico, il comportamento della varianza in caso di ereditarietà per ogni parametro di tipo può essere specificato usando una annotazione di varianza di tipo sul simbolo del tipo.

Visibilità

L’ambito in cui un tipo o un membro dichiarato è visibile ad altri tipi e membri.

Vista

Un valore implicito di tipo funzione che converte un tipo A in un tipo B. La funzione è di tipo A => B o (=> A) => B (in quest’ultimo caso, (=> A) è un parametro per nome). È anche possibile usare come vista un metodo per la conversione di tipo implicita dotato della stessa firma e visibile nell’ambito corrente.

© 2008–9 O’Reilly Media
© 2009–10 Giulio Piancastelli per la traduzione italiana