diff options
Diffstat (limited to 'it-it')
-rw-r--r-- | it-it/bash-it.html.markdown | 91 | ||||
-rw-r--r-- | it-it/bf-it.html.markdown (renamed from it-it/brainfuck-it.html.markdown) | 2 | ||||
-rw-r--r-- | it-it/c++-it.html.markdown | 289 | ||||
-rw-r--r-- | it-it/coffeescript-it.html.markdown | 2 | ||||
-rw-r--r-- | it-it/git-it.html.markdown | 498 | ||||
-rw-r--r-- | it-it/go-it.html.markdown | 453 | ||||
-rw-r--r-- | it-it/logtalk-it.html.markdown | 550 | ||||
-rw-r--r-- | it-it/markdown.html.markdown | 244 | ||||
-rw-r--r-- | it-it/matlab-it.html.markdown | 526 | ||||
-rw-r--r-- | it-it/python-it.html.markdown | 199 | ||||
-rw-r--r-- | it-it/ruby-ecosystem-it.html.markdown | 145 | ||||
-rw-r--r-- | it-it/rust-it.html.markdown | 322 |
12 files changed, 3266 insertions, 55 deletions
diff --git a/it-it/bash-it.html.markdown b/it-it/bash-it.html.markdown index af8823c4..efc47969 100644 --- a/it-it/bash-it.html.markdown +++ b/it-it/bash-it.html.markdown @@ -10,7 +10,12 @@ contributors: - ["Anton Strömkvist", "http://lutic.org/"] - ["Rahil Momin", "https://github.com/iamrahil"] - ["Gregrory Kielian", "https://github.com/gskielian"] -filename: LearnBash.sh + - ["Etan Reisner", "https://github.com/deryni"] + - ["Jonathan Wang", "https://github.com/Jonathansw"] + - ["Leo Rudberg", "https://github.com/LOZORD"] + - ["Betsy Lorton", "https://github.com/schbetsy"] + - ["John Detter", "https://github.com/jdetter"] +filename: LearnBash-it.sh translators: - ["Robert Margelli", "http://github.com/sinkswim/"] - ["Tommaso Pifferi", "http://github.com/neslinesli93/"] @@ -50,6 +55,13 @@ echo '$Variabile' # il suo nome senza $. Se vuoi usare il valore della variabile, devi usare $. # Nota che ' (singolo apice) non espande le variabili! +# Espansione dei parametri ${ }: +echo ${Variabile} +# Questo è un esempio semplice dell'espansione dei parametri. +# L'espansione dei parametri prende il valore di una variabile, ed appunto lo "espande" o lo stampa. +# Durante l'espansione il valore o il parametro passato possono essere modificati. +# Sotto ci sono altri esempi che analizzano l'uso dell'espansione dei parametri. + # Sostituzione di stringhe nelle variabili echo ${Variabile/Una/A} # Questo sostituirà la prima occorrenza di "Una" con "La" @@ -64,6 +76,12 @@ echo ${Foo:-"ValoreDiDefaultSeFooMancaOppureÈVuoto"} # Questo funziona per null (Foo=), stringa vuota (Foo=""), zero (Foo=0) ritorna 0 # Nota: viene ritornato il valore di default, il contenuto della variabile pero' non cambia. +# Espansione delle graffe { } +# Viene usata per generare stringe in modo arbitrario +echo {1..10} +echo {a..z} +# Con questi comandi viene stampato l'intervallo dal valore iniziale al valore finale (i numeri da 1 a 10, le lettere dell'alfabeto) + # Variabili builtin: # Ci sono delle variabili builtin molto utili, come echo "Valore di ritorno dell'ultimo programma eseguito: $?" @@ -72,6 +90,18 @@ echo "Numero di argomenti: $#" echo "Argomenti dello script: $@" echo "Argomenti dello script separati in variabili distinte: $1 $2..." +# Adesso che sappiamo come stampare a schermo, e come usare le variabili, possiamo andare avanti con le basi di bash! +# Per conoscere la directory su cui siamo posizionati, è sufficiente usare `pwd`. +# `pwd` è l'acronimo di "print working directory", ovvero "stampa la directory corrente". +# Possiamo anche usare la variabile builtin `$PWD`. +# Prova questi due esempi, e vedi che il risultato è lo stesso: +echo "Sono dentro $(pwd)" # esegue `pwd` ed interpola l'output +echo "Sono dentro $PWD" # interpola direttamente la variabile builtin + +# Se c'è troppo testo nel terminale, ottenuto scrivendo comandi oppure eseguendo uno script, il comando `clear` pulisce lo schermo +clear +# Puoi utilizzare anche Ctrl-L al posto di clear + # Leggere un valore di input: echo "Come ti chiami?" read Nome # Nota che non abbiamo dovuto dichiarare una nuova variabile @@ -120,12 +150,52 @@ ls # Questi comandi hanno opzioni che controllano la loro esecuzione: ls -l # Elenca tutti i file e le cartelle su una riga separata +ls -t # Ordina i contenuti della cartella in base all'ultima data di modifica (ordine decrescente) +ls -R # Esegue `ls` in modo ricorsivo all'interno di questa cartella e tutte le sottocartelle # I risultati del comando precedente possono essere passati al comando successivo come input. # Il comando grep filtra l'input con il pattern passato. Ecco come possiamo elencare i # file .txt nella cartella corrente: ls -l | grep "\.txt" +# Usa `cat` per stampare il contenuto dei file a schermo: +cat file.txt + +# Possiamo leggere il contenuto di un file e memorizzarlo in una variabile, sempre usando `cat`: +Contenuti=$(cat file.txt) +echo "INIZIO DEL FILE\n$Contenuti\nFINE DEL FILE" + +# Usa `cp` per copiare file o cartelle da un punto all'altro del sistema. +# `cp` crea NUOVE versioni dei file, quindi le modifiche della copia non hanno effetto sull'originale, e viceversa. +# Nota che il file (o la cartella) di destinazione vengono sovrascritte se già esistono! +cp fileSorgente.txt copia.txt +cp -r cartellaSorgente/ destinazione/ # copia ricorsiva + +# Se hai bisogno di trasferire file tra computer, puoi usare `scp` o `sftp`. +# `scp` ha una sintassi simile a `cp`. +# `sftp` invece è più interattivo. + +# Usa `mv` per spostare file o cartella da un punto all'altro del sistema. +# `mv` è simile a `cp`, ma cancella il file(o la cartella) sorgente. +# `mv` è molto utile anche per rinominare i file! +mv s0rg3nt3.txt dst.txt # mi spiace anonymous... + +# Dal momento che bash lavora nel contesto della cartella corrente, potresti voler eseguire il comando dentro a qualche altra cartella. Per fare questo si usa `cd`: +cd ~ # va nella cartella Home +cd .. # va nella cartella "padre" + # (ad esempio da /home/user/Download a /home/user) +cd /home/user/Documenti # entra nella cartella specificata +cd ~/Documenti/.. # siamo sempre nella cartella home... vero? + +# Usa le subshell per lavorare in cartelle diverse contemporaneamente +(echo "All'inizio sono qua: $PWD") && (cd cartella; echo "Adesso invece sono qua: $PWD") +pwd # siamo sempre nella prima cartella + +# Usa `mkdir` per creare nuove cartelle +mkdir nuovaCartella +# Il flag `-p` indica la creazione delle cartelle intermedie, se non esistono. +mkdir nuovaCartella/con/tante/cartelle/intermedie + # Puoi redirezionare l'input e l'output del comando (stdin, stdout, e stderr). # Leggi da stdin finchè ^EOF$ e sovrascrivi hello.py con le righe # comprese tra "EOF": @@ -164,7 +234,9 @@ echo "#helloworld" | cat > output.out echo "#helloworld" | tee output.out >/dev/null # Pulisci i file temporanei verbosamente (aggiungi '-i' per la modalità interattiva) +# Attenzione: il comando `rm` non può essere annullato! rm -v output.out error.err output-and-error.log +rm -r cartellaTemporanea/ # cancella ricorsivamente # I comandi possono essere sostituiti con altri comandi usando $( ): # Il comando seguente mostra il numero di file e cartelle nella @@ -255,10 +327,25 @@ sed -i 's/okay/great/g' file.txt grep "^foo.*bar$" file.txt # passa l'opzione "-c" per stampare invece il numero delle righe che soddisfano la regex grep -c "^foo.*bar$" file.txt +# Altre opzioni utili possono essere: +grep -r "^foo.*bar$" someDir/ # esegue `grep` ricorsivamente nella cartella +grep -n "^foo.*bar$" file.txt # stampa il numero delle righe del file +grep -rI "^foo.*bar$" someDir/ # esegue `grep` ricorsivamente nella cartella, ignorando i file non testuali +# Esegue la stessa ricerca iniziale, ma filtrando solo le righe che contengono la stringa "baz" +grep "^foo.*bar$" file.txt | grep -v "baz" + # se vuoi letteralmente cercare la stringa, # e non la regex, usa fgrep (o grep -F) -fgrep "^foo.*bar$" file.txt +fgrep "foobar" file.txt + +# Il comando trap permette di eseguire un comando quando un segnale viene ricevuto dal tuo script. +# In questo esempio, trap eseguirà rm se uno dei tre segnali (SIGHUP, SIGINT o SIGTERM) viene ricevuto. +trap "rm $TEMP_FILE; exit" SIGHUP SIGINT SIGTERM +# `sudo` viene usato per eseguire comandi come superuser, ovvero come utente che ha maggiori privilegi all'interno del sistema +$NOME1=$(whoami) +$NOME2=$(sudo whoami) +echo "Ero $NOME1, poi sono diventato più potente: $NOME2" # Leggi la documentazione dei builtin di bash con il builtin 'help' di bash: help diff --git a/it-it/brainfuck-it.html.markdown b/it-it/bf-it.html.markdown index 08d2ede9..a79710d0 100644 --- a/it-it/brainfuck-it.html.markdown +++ b/it-it/bf-it.html.markdown @@ -1,5 +1,5 @@ --- -language: brainfuck +language: bf contributors: - ["Prajit Ramachandran", "http://prajitr.github.io/"] - ["Mathias Bynens", "http://mathiasbynens.be/"] diff --git a/it-it/c++-it.html.markdown b/it-it/c++-it.html.markdown index 92ebc165..b4f9c50e 100644 --- a/it-it/c++-it.html.markdown +++ b/it-it/c++-it.html.markdown @@ -8,6 +8,7 @@ contributors: - ["Connor Waters", "http://github.com/connorwaters"] translators: - ["Robert Margelli", "http://github.com/sinkswim/"] + - ["Tommaso Pifferi", "http://github.com/neslinesli93/"] lang: it-it --- @@ -151,7 +152,7 @@ namespace Primo { namespace Secondo { void foo() { - printf("Questa è Secondo::foo\n") + printf("Questa è Secondo::foo\n"); } } @@ -460,7 +461,7 @@ void Cane::print() const Cane::~Cane() { - cout << "Ciao ciao " << nome << "\n"; + std::cout << "Ciao ciao " << nome << "\n"; } int main() { @@ -646,7 +647,7 @@ void stampaMessaggio<10>() { printMessage<20>(); // Stampa "impara il C++ in 20 minuti!" printMessage<10>(); // Stampa "Impara il C++ più velocemente in soli 10 minuti!" - + //////////////////////////// // Gestione delle eccezioni /////////////////////////// @@ -657,7 +658,7 @@ printMessage<10>(); // Stampa "Impara il C++ più velocemente in soli 10 minuti #include <exception> #include <stdexcept> -// Tutte le eccezioni lanciate all'interno del blocco _try_ possono essere catturate dai successivi +// Tutte le eccezioni lanciate all'interno del blocco _try_ possono essere catturate dai successivi // handlers _catch_. try { // Non allocare eccezioni nello heap usando _new_. @@ -805,6 +806,94 @@ void faiQualcosaConUnFile(const std::string& nomefile) // sono tutti automaticamente distrutti con i loro contenuti quando escono dalla visibilità. // - I mutex usano lock_guard e unique_lock +// I contenitori che utilizzano chiavi non-primitive (classi personalizzate) +// richiedono la funzione di confronto nell'oggetto stesso, o tramite un puntatore a funzione. +// Le chiavi primitive hanno funzioni di confronto già definite, ma puoi sovrascriverle. +class Foo { +public: + int j; + Foo(int a) : j(a) {} +}; +struct funzioneDiConfronto { + bool operator()(const Foo& a, const Foo& b) const { + return a.j < b.j; + } +}; +// Questo non è permesso, anche se qualche compilatore potrebbe non dare problemi +//std::map<Foo, int> fooMap; +std::map<Foo, int, funzioneDiConfronto> fooMap; +fooMap[Foo(1)] = 1; +fooMap.find(Foo(1)); -- vero + +/////////////////////////////////////// +// Espressioni Lambda (C++11 e superiori) +/////////////////////////////////////// + +// Le espressioni lambda (più semplicemente "lambda") sono utilizzate +// per definire una funzione anonima nel punto in cui viene invocata, o +// dove viene passata come argomento ad una funzione + +// Ad esempio, consideriamo l'ordinamento di un vettore costituito da una +// coppia di interi, utilizzando il secondo elemento per confrontare +vector<pair<int, int> > tester; +tester.push_back(make_pair(3, 6)); +tester.push_back(make_pair(1, 9)); +tester.push_back(make_pair(5, 0)); + +// Passiamo una lambda come terzo argomento alla funzione di ordinamento +// `sort` è contenuta nell'header <algorithm> +sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs) { + return lhs.second < rhs.second; +}); + +// Nota bene la sintassi utilizzata nelle lambda: +// [] serve per "catturare" le variabili. +// La "Lista di Cattura" definisce tutte le variabili esterne che devono essere disponibili +// all'interno della funzione, e in che modo. +// La lista può contenere: +// 1. un valore: [x] +// 2. un riferimento: [&x] +// 3. qualunque variabile nello scope corrente, per riferimento [&] +// 4. qualunque variabile nello scope corrente, per valore [=] +// Esempio: + +vector<int> id_cani; +// numero_cani = 3; +for(int i = 0; i < 3; i++) { + id_cani.push_back(i); +} + +int pesi[3] = {30, 50, 10}; + +// Mettiamo che vuoi ordinare id_cani in base al peso dei cani +// Alla fine, id_cani sarà: [2, 0, 1] + +// Le lambda vengono in aiuto + +sort(id_cani.begin(), id_cani.end(), [&pesi](const int &lhs, const int &rhs) { + return pesi[lhs] < pesi[rhs]; +}); +// Nota come abbiamo catturato "pesi" per riferimento nell'esempio. +// Altre informazioni sulle lambda in C++: http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11 + +/////////////////////////////// +// Ciclo For semplificato(C++11 e superiori) +/////////////////////////////// + +// Puoi usare un ciclo for per iterare su un tipo di dato contenitore +int arr[] = {1, 10, 3}; + +for(int elem: arr) { + cout << elem << endl; +} + +// Puoi usare "auto" senza preoccuparti del tipo degli elementi nel contenitore +// Ad esempio: + +for(auto elem: arr) { + // Fai qualcosa con `elem` +} + /////////////////////// // Roba divertente ////////////////////// @@ -855,20 +944,188 @@ Foo f1; f1 = f2; -// Come deallocare realmente le risorse all'interno di un vettore: -class Foo { ... }; -vector<Foo> v; -for (int i = 0; i < 10; ++i) - v.push_back(Foo()); +/////////////////////////////////////// +// Tuple (C++11 e superiori) +/////////////////////////////////////// + +#include<tuple> + +// Concettualmente le tuple sono simili alle strutture del C, ma invece di avere +// i membri rappresentati con dei nomi, l'accesso agli elementi avviene tramite +// il loro ordine all'interno della tupla. + +// Cominciamo costruendo una tupla. +// Inserire i valori in una tupla +auto prima = make_tuple(10, 'A'); +const int maxN = 1e9; +const int maxL = 15; +auto seconda = make_tuple(maxN, maxL); + +// Vediamo gli elementi contenuti nella tupla "prima" +cout << get<0>(prima) << " " << get<1>(prima) << "\n"; // stampa : 10 A + +// Vediamo gli elementi contenuti nella tupla "seconda" +cout << get<0>(seconda) << " " << get<1>(seconda) << "\n"; // stampa: 1000000000 15 + +// Estrarre i valori dalla tupla, salvandoli nelle variabili +int primo_intero; +char primo_char; +tie(primo_intero, primo_char) = prima; +cout << primo_intero << " " << primo_char << "\n"; // stampa : 10 A + +// E' possibile creare tuple anche in questo modo +tuple<int, char, double> terza(11, 'A', 3.14141); + +// tuple_size ritorna il numero di elementi in una tupla (come constexpr) +cout << tuple_size<decltype(terza)>::value << "\n"; // stampa: 3 + +// tuple_cat concatena gli elementi di tutte le tuple, nell'esatto ordine +// in cui sono posizionati all'interno delle tuple stesse +auto tupla_concatenata = tuple_cat(prima, seconda, terza); +// tupla_concatenata diventa = (10, 'A', 1e9, 15, 11, 'A' ,3.14141) + +cout << get<0>(tupla_concatenata) << "\n"; // stampa: 10 +cout << get<3>(tupla_concatenata) << "\n"; // stampa: 15 +cout << get<5>(tupla_concatenata) << "\n"; // stampa: 'A' + + +///////////////////// +// Contenitori +///////////////////// + +// I Contenitori della "Standard Template Library", ovvero la libreria standard +// dei template contenuti nel C++, sono template predefiniti. +// I Contenitori si occupano di come allocare lo spazio per gli elementi contenuti, +// e forniscono funzioni per accedervi e manipolarli + +// Vediamo alcuni tipi di contenitori: + +// Vector (array dinamici/vettori) +// Permettono di definire un vettore, o una lista di oggetti, a runtime +#include<vector> +vector<Tipo_Dato> nome_vettore; // usato per inizializzare un vettore +cin >> val; +nome_vettore.push_back(val); // inserisce il valore di "val" nel vettore + +// Per iterare in un vettore, abbiamo due possibilità: +// Ciclo normale +for(int i=0; i<nome_vettore.size(); i++) +// Cicla dall'indice zero fino all'ultimo + +// Iteratore +vector<Tipo_Dato>::iterator it; // inizializza l'iteratore per il vettore +for(it=nome_vettore.begin(); it!=nome_vettore.end();++it) +// Nota che adesso non cicla più sugli indici, ma direttamente sugli elementi! + +// Per accedere agli elementi del vettore +// Operatore [] +var = nome_vettore[indice]; // Assegna a "var" il valore del vettore all'indice dato + + +// Set (insiemi) +// Gli insiemi sono contenitori che memorizzano elementi secondo uno specifico ordine. +// Gli insiemi vengono per lo più utilizzati per memorizzare valori unici, secondo +// un ordine, senza scrivere ulteriore codice. + +#include<set> +set<int> insieme; // Inizializza un insieme di interi +insieme.insert(30); // Inserisce il valore 30 nell'insieme +insieme.insert(10); // Inserisce il valore 10 nell'insieme +insieme.insert(20); // Inserisce il valore 20 nell'insieme +insieme.insert(30); // Inserisce il valore 30 nell'insieme +// Gli elementi dell'insieme sono: +// 10 20 30 + +// Per cancellare un elemento +insieme.erase(20); // Cancella l'elemento con valore 20 +// L'insieme contiene adesso: 10 30 + +// Per iterare su un insieme, usiamo gli iteratori +set<int>::iterator it; +for(it=insieme.begin();it<insieme.end();it++) { + cout << *it << endl; +} +// Stampa: +// 10 +// 30 + +// Per svuotare il contenitore usiamo il metodo "clear" +insieme.clear(); +cout << insieme.size(); +// Stampa: 0 + +// Nota: per permettere elementi duplicati, possiamo usare "multiset" + +// Map (mappa/tabella di hash) +// Le mappe servono per memorizzare un elemento, detto chiave, a cui viene +// associato un valore, il tutto secondo uno specifico ordine. + +#include<map> +map<char, int> mia_mappa; // Inizializza una mappa che usa i char come chiave, e gli interi come valore + +mia_mappa.insert(pair<char,int>('A',1)); +// Inserisce il valore 1 per la chiave A +mia_mappa.insert(pair<char,int>('Z',26)); +// Inserisce il valore 26 per la chiave Z + +// Per iterare +map<char,int>::iterator it; +for (it=mia_mappa.begin(); it!=mia_mappa.end(); ++it) + std::cout << it->first << "->" << it->second << '\n'; +// Stampa: +// A->1 +// Z->26 + +// Per trovare il valore corrispondente ad una data chiave +it = mia_mappa.find('Z'); +cout << it->second; +// Stampa: 26 + + +/////////////////////////////////// +// Operatori logici e bitwise(bit-a-bit) +////////////////////////////////// + +// La maggior parte di questi operatori in C++ sono gli stessi degli altri linguaggi + +// Operatori logici + +// Il C++ usa la "Short-circuit evaluation" per le espressioni booleane. Cosa significa? +// In pratica, in una condizione con due argomenti, il secondo viene considerato solo se +// il primo non basta a determinate il valore finale dell'espresione. + +true && false // Effettua il **and logico** e ritorna falso +true || false // Effettua il **or logico** e ritorna vero +! true // Effettua il **not logico** e ritorna falso + +// Invece di usare i simboli, si possono usare le keyword equivalenti +true and false // Effettua il **and logico** e ritorna falso +true or false // Effettua il **or logico** e ritorna vero +not true // Effettua il **not logico** e ritorna falso + +// Operatori bitwise(bit-a-bit) + +// **<<** Operatore di Shift a Sinistra +// << sposta i bit a sinistra +4 << 1 // Sposta a sinistra di 1 i bit di 4, ottenendo 8 +// x << n in pratica realizza x * 2^n + + +// **>>** Operatore di Shift a Destra +// >> sposta i bit a destra +4 >> 1 // Sposta a destra di 1 i bit di 4, ottenendo 2 +// x >> n in pratica realizza x / 2^n -// La riga seguente riduce la dimensione di v a 0, ma il distruttore non -// viene chiamato e dunque le risorse non sono deallocate! -v.empty(); -v.push_back(Foo()); // Il nuovo valore viene copiato nel primo Foo che abbiamo inserito +~4 // Effettua il NOT bit-a-bit +4 | 3 // Effettua il OR bit-a-bit +4 & 3 // Effettua il AND bit-a-bit +4 ^ 3 // Effettua il XOR bit-a-bit -// Distrugge realmente tutti i valori dentro v. Vedi la sezione riguardante gli -// oggetti temporanei per capire come mai funziona così. -v.swap(vector<Foo>()); +// Le keyword equivalenti sono +compl 4 // Effettua il NOT bit-a-bit +4 bitor 3 // Effettua il OR bit-a-bit +4 bitand 3 // Effettua il AND bit-a-bit +4 xor 3 // Effettua il XOR bit-a-bit ``` Letture consigliate: diff --git a/it-it/coffeescript-it.html.markdown b/it-it/coffeescript-it.html.markdown index 31973369..d30ba819 100644 --- a/it-it/coffeescript-it.html.markdown +++ b/it-it/coffeescript-it.html.markdown @@ -4,8 +4,6 @@ contributors: - ["Luca 'Kino' Maroni", "http://github.com/kino90"] - ["Tenor Biel", "http://github.com/L8D"] - ["Xavier Yao", "http://github.com/xavieryao"] -translators: - - ["Tommaso Pifferi","http://github.com/neslinesli93"] filename: coffeescript-it.coffee lang: it-it --- diff --git a/it-it/git-it.html.markdown b/it-it/git-it.html.markdown new file mode 100644 index 00000000..521538a1 --- /dev/null +++ b/it-it/git-it.html.markdown @@ -0,0 +1,498 @@ +--- +category: tool +tool: git +contributors: + - ["Jake Prather", "http://github.com/JakeHP"] + - ["Leo Rudberg" , "http://github.com/LOZORD"] + - ["Betsy Lorton" , "http://github.com/schbetsy"] + - ["Bruno Volcov", "http://github.com/volcov"] +translators: + - ["Christian Grasso", "http://chris54721.net"] +filename: LearnGit-it.txt +lang: it-it +--- + +Git è un sistema di +[controllo versione distribuito](https://it.wikipedia.org/wiki/Controllo_versione_distribuito) +e di gestione del codice sorgente. + +Git esegue una serie di _snapshot_ per salvare lo stato di un progetto, così +facendo può fornirti la possibilità di gestire il tuo codice e di salvarne lo +stato assegnando delle versioni. + +## Basi del controllo versione + +### Cos'è il controllo versione? + +Il controllo versione (_Version Control_ o _Versioning_) è un sistema che +registra le modifiche apportate a uno o più file nel tempo. + +### Controllo versione centralizzato e distribuito + +* Il controllo versione centralizzato si concentra sulla sincronizzazione, il + monitoraggio e il backup dei file. +* Il controllo versione distribuito si concentra sulla condivisione delle + modifiche. Ogni modifica ha un identificatore univoco. +* I sistemi distribuiti non hanno una struttura definita. Si potrebbe creare + ad esempio un sistema centralizzato simile a SVN utilizzando Git. + +[Ulteriori informazioni](http://git-scm.com/book/it/v1/Per-Iniziare-Il-Controllo-di-Versione) + +### Perchè usare Git? + +* Consente di lavorare offline. +* Collaborare con altre persone è semplice! +* Utilizzare i branch (rami di sviluppo) è semplice! +* Git è veloce. +* Git è flessibile. + +## Architettura di Git + +### Repository + +Un insieme di file, cartelle, registrazioni della cronologia e versioni. +Immaginalo come una struttura dati del codice, con la caratteristica che ogni +"elemento" del codice ti fornisce accesso alla sua cronologia delle revisioni, +insieme ad altre cose. + +Un repository comprende la cartella .git e il working tree. + +### Cartella .git (componente del repository) + +La cartella .git contiene tutte le configurazioni, i log, i rami e altro. +[Lista dettagliata](http://gitready.com/advanced/2009/03/23/whats-inside-your-git-directory.html) + +### Working Tree (componente del repository) + +Si tratta semplicemente delle cartelle e dei file presenti nel repository. +Spesso viene indicato come "directory di lavoro" ("working directory"). + +### Index (componente della cartella .git) + +L'Index è l'area di staging di Git. Si tratta di un livello che separa il +working tree dal repository. Ciò fornisce agli sviluppatori più controllo su +cosa viene inviato al repository. + +### Commit + +Un commit è uno snapshot di una serie di modifiche apportate al working tree. +Ad esempio, se hai aggiunto 5 file e ne hai rimossi 2, ciò sarà registrato in +un commit. Il commit può essere pushato (inviato) o meno ad altri repository. + +### Branch (ramo) + +Un branch (ramo) è essenzialmente un puntatore all'ultimo commit che hai +effettuato. Effettuando altri commit, il puntatore verrà automaticamente +aggiornato per puntare all'ultimo commit. + +### Tag + +Un tag è un contrassegno applicato a un punto specifico nella cronologia dei +commit. Di solito i tag vengono utilizzati per contrassegnare le versioni +rilasciate (v1.0, v1.1, etc.). + +### HEAD e head (componenti della cartella .git) + +HEAD (in maiuscolo) è un puntatore che punta al branch corrente. Un repository +può avere solo 1 puntatore HEAD *attivo*. + +head (in minuscolo) è un puntatore che può puntare a qualsiasi commit. Un +repository può avere un numero qualsiasi di puntatori head. + +### Stadi di Git +* _Modified_ - Un file è stato modificato, ma non è ancora stato effettuato + un commit per registrare le modifiche nel database di Git +* _Staged_ - Un file modificato è stato contrassegnato per essere incluso nel + prossimo commit +* _Committed_ - È stato effettuato un commit e le modifiche sono state + registrate nel database di Git + +## Comandi + +### init + +Crea un repository Git vuoto. Le impostazioni e le informazioni del repository +sono salvate nella cartella ".git". + +```bash +$ git init +``` + +### config + +Utilizzato per configurare le impostazioni, sia specifiche del repository, sia +a livello globale. Le impostazioni globali sono salvate in `~/.gitconfig`. + +```bash +$ git config --global user.email "email@example.com" +$ git config --global user.name "Nome utente" +``` + +[Ulteriori informazioni su git config](http://git-scm.com/docs/git-config) + +### help + +Fornisce una documentazione molto dettagliata di ogni comando. + +```bash +# Mostra i comandi più comuni +$ git help + +# Mostra tutti i comandi disponibili +$ git help -a + +# Documentazione di un comando specifico +# git help <nome_comando> +$ git help add +$ git help commit +$ git help init +# oppure git <nome_comando> --help +$ git add --help +$ git commit --help +$ git init --help +``` + +### Ignorare file + +Per impedire intenzionalmente che file privati o temporanei vengano inviati +al repository Git. + +```bash +$ echo "temp/" >> .gitignore +$ echo "privato.txt" >> .gitignore +``` + + +### status + +Mostra le differenza tra lo stato attuale del working tree e l'attuale commit +HEAD. + +```bash +$ git status +``` + +### add + +Aggiunge file alla staging area, ovvero li contrassegna per essere inclusi nel +prossimo commit. Ricorda di aggiungere i nuovi file, altrimenti non saranno +inclusi nei commit! + +```bash +# Aggiunge un file nella directory attuale +$ git add HelloWorld.java + +# Aggiunge un file in una sottocartella +$ git add /path/to/file/HelloWorld.c + +# Il comando supporta le espressioni regolari +$ git add ./*.java + +# Aggiunge tutti i file non ancora contrassegnati +$ git add --all +``` + +Questo comando contrassegna soltanto i file, senza effettuare un commit. + +### branch + +Utilizzato per gestire i branch (rami). Puoi visualizzare, modificare, creare o +eliminare branch utilizzando questo comando. + +```bash +# Visualizza i branch e i remote +$ git branch -a + +# Crea un nuovo branch +$ git branch nuovoBranch + +# Elimina un branch +$ git branch -d nomeBranch + +# Rinomina un branch +$ git branch -m nomeBranch nuovoNomeBranch + +# Permette di modificare la descrizione di un branch +$ git branch nomeBranch --edit-description +``` + +### tag + +Utilizzato per gestire i tag. + +```bash +# Visualizza i tag esistenti +$ git tag +# Crea un nuovo tag +# L'opzione -m consente di specificare una descrizione per il tag. +# Se l'opzione -m non viene aggiunta, Git aprirà un editor per consentire +# l'inserimento del messaggio. +$ git tag -a v2.0 -m 'Versione 2.0' +# Mostra informazioni relative a un tag +# Include informazioni sul creatore del tag, la data di creazione, e il +# messaggio assegnato al tag oltre alle informazioni sul commit. +$ git show v2.0 +``` + +### checkout + +Consente di cambiare branch o ripristinare i file a una revisione specifica. +Tutti i file nel working tree vengono aggiornati per corrispondere alla versione +presente nel branch o nel commit specificato. + +```bash +# Effettua il checkout di un repository - il branch predefinito è 'master' +$ git checkout +# Effettua il checkout di un branch specifico +$ git checkout nomeBranch +# Crea un nuovo branch e ne effettua il checkout +# Equivalente a "git branch <nomeBranch>; git checkout <nomeBranch>" +$ git checkout -b nuovoBranch +``` + +### clone + +Clona, o copia, un repository esistente in una nuova directory. Inoltre, +aggiunge dei branch _remote-tracking_, utilizzati per monitorare i branch +remoti corrispondenti a quelli locali, e consentendo così di inviare le +modifiche al repository remoto. + +```bash +# Clona learnxinyminutes-docs +$ git clone https://github.com/adambard/learnxinyminutes-docs.git +# Clona solo l'ultima revisione di un repository +$ git clone --depth 1 https://github.com/adambard/learnxinyminutes-docs.git +# Clona solo un branch specifico +$ git clone -b master-cn https://github.com/adambard/learnxinyminutes-docs.git --single-branch +``` + +### commit + +Effettua uno _snapshot_ dello stato attuale del working tree e registra le +modifiche in un nuovo commit. Il commit contiene, oltre alle modifiche apportate, +anche l'autore e una descrizione. + +```bash +# Crea un nuovo commit con un messaggio +$ git commit -m "Aggiunta la funzione multiplyNumbers() in HelloWorld.c" + +# Aggiunge (git add) automaticamente i file modificati o eliminati (ESCLUSI +# i nuovi file) e quindi effettua il commit +$ git commit -a -m "Modificato foo.php e rimosso bar.php" + +# Modifica l'ultimo commit (il comando elimina il commit precedente e lo +# sostituisce con uno nuovo) +$ git commit --amend -m "Messaggio corretto" +``` + +### diff + +Mostra la differenza tra un file nel working tree e la sua versione nell'index, +in un branch o ad un commit specifico. + +```bash +# Mostra la differenza tra il working tree e l'index +$ git diff + +# Mostra la differenza tra l'index e il commit più recente +$ git diff --cached + +# Mostra la differenza tra il working tree e un commit specifico +$ git diff <commit> + +# Mostra la differenza tra due commit +$ git diff <commit1> <commit2> +``` + +### grep + +Consente di effettuare una ricerca veloce nel repository. + +```bash +# Cerca "variableName" nei file Java +$ git grep 'variableName' -- '*.java' + +# Cerca una riga contenente "arrayListName" E "add" oppure "remove" +$ git grep -e 'arrayListName' --and \( -e add -e remove \) +``` + +Impostazioni relative a `git grep`: + +```bash +# Mostra il numero delle righe +$ git config --global grep.lineNumber true + +# Rende i risultati più leggibili +$ git config --global alias.g "grep --break --heading --line-number" +``` + +### log + +Mostra la cronologia dei commit inviati al repository. + +```bash +# Mostra tutti i commit +$ git log + +# Mostra ogni commit su una sola riga +$ git log --oneline + +# Mostra solo i commit legati ai merge +$ git log --merges +``` + +### merge + +Effettua un "merge", ovvero unisce le modifiche di un branch in quello attuale. + +```bash +# Unisce il branch specificato a quello attuale +$ git merge nomeBranch + +# Genera un commit in ogni caso dopo aver eseguito il merge +$ git merge --no-ff nomeBranch +``` + +### mv + +Rinomina o sposta un file. + +```bash +# Rinomina un file +$ git mv HelloWorld.c HelloNewWorld.c + +# Sposta un file +$ git mv HelloWorld.c ./new/path/HelloWorld.c + +# Forza l'esecuzione del comando +# Se un file "nuovoNomeFile" esiste già nella directory, verrà sovrascritto +$ git mv -f nomeFile nuovoNomeFile +``` + +### pull + +Aggiorna il repository effettuando il merge delle nuove modifiche. + +```bash +# Aggiorna il branch attuale dal remote "origin" +$ git pull + +# Di default, git pull aggiorna il branch attuale effettuando il merge +# delle nuove modifiche presenti nel branch remote-tracking corrispondente +$ git pull + +# Aggiorna le modifiche dal branch remoto, quindi effettua il rebase dei commit +# nel branch locale +# Equivalente a: "git pull <remote> <branch>; git rebase <branch>" +$ git pull origin master --rebase +``` + +### push + +Invia ed effettua il merge delle modifiche da un branch locale ad uno remoto. + +```bash +# Invia ed effettua il merge delle modifiche dal branch "master" +# al remote "origin". +# git push <remote> <branch> +$ git push origin master + +# Di default, git push invia ed effettua il merge delle modifiche +# dal branch attuale al branch remote-tracking corrispondente +$ git push + +# Per collegare il branch attuale ad uno remoto, basta aggiungere l'opzione -u +$ git push -u origin master +``` + +### stash + +Salva lo stato attuale del working tree in una lista di modifiche non ancora +inviate al repository con un commit che possono essere applicate nuovamente +in seguito. + +Questo comando può essere utile se, ad esempio, mentre stai effettuando delle +modifiche non ancora completate, hai bisogno di aggiornare il repository locale +con `git pull`. Poichè non hai ancora effettuato il commit di tutte le modifiche, +non sarà possibile effettuare il pull. Tuttavia, puoi utilizzare `git stash` per +salvare temporaneamente le modifiche e applicarle in seguito. + +```bash +$ git stash +``` + +Ora puoi effettuare il pull: + +```bash +$ git pull +``` + +A questo punto, come già suggerito dall'output del comando `git stash`, puoi +applicare le modifiche: + +```bash +$ git stash apply +``` + +Infine puoi controllare che tutto sia andato bene: + +```bash +$ git status +``` + +Puoi visualizzare gli accantonamenti che hai effettuato finora utilizzando: + +```bash +$ git stash list +``` + +### rebase (attenzione) + +Applica le modifiche effettuate su un branch su un altro branch. +*Non effettuare il rebase di commit che hai già inviato a un repository pubblico!* + +```bash +# Effettua il rebase di experimentBranch in master +$ git rebase master experimentBranch +``` + +[Ulteriori informazioni](https://git-scm.com/book/it/v1/Diramazioni-in-Git-Rifondazione) + +### reset (attenzione) + +Effettua il reset del commit HEAD attuale ad uno stato specifico. +Questo comando consente di annullare `merge`, `pull`, `commit`, `add` e altro. +Tuttavia, può essere pericoloso se non si sa cosa si sta facendo. + +```bash +# Effettua il reset della staging area (annullando le aggiunte e le rimozioni +# di file dal repository, senza modificare il working tree) +$ git reset + +# Effettua il reset completo della staging area, ovvero annulla qualsiasi +# modifica al repository eliminando definitivamente anche tutte le modifiche +# ai file non inviate e ripristinando il working tree +$ git reset --hard + +# Effettua il reset del branch attuale al commit specificato (lasciando il +# working tree intatto) +$ git reset 31f2bb1 + +# Effettua il reset completo del branch attuale al commit specificato, +# eliminando qualsiasi modifica non inviata +$ git reset --hard 31f2bb1 +``` + +### rm + +Consente di rimuovere un file dal working tree e dal repository. +Per eliminare un file solo dal working tree ma non dal repository, è invece +necessario utilizzare `/bin/rm`. + +```bash +# Elimina un file nella directory attuale +$ git rm HelloWorld.c + +# Elimina un file da una sottocartella +$ git rm /pather/to/the/file/HelloWorld.c +``` diff --git a/it-it/go-it.html.markdown b/it-it/go-it.html.markdown new file mode 100644 index 00000000..e005f2dc --- /dev/null +++ b/it-it/go-it.html.markdown @@ -0,0 +1,453 @@ +--- +name: Go +language: Go +filename: learngo-it.go +contributors: + - ["Sonia Keys", "https://github.com/soniakeys"] + - ["Christopher Bess", "https://github.com/cbess"] + - ["Jesse Johnson", "https://github.com/holocronweaver"] + - ["Quint Guvernator", "https://github.com/qguv"] + - ["Jose Donizetti", "https://github.com/josedonizetti"] + - ["Alexej Friesen", "https://github.com/heyalexej"] + - ["Clayton Walker", "https://github.com/cwalk"] +translators: + - ["Tommaso Pifferi","http://github.com/neslinesli93"] +lang: it-it +--- + +Go è stato creato per avere tra le mani uno strumento in grado di arrivare +al punto, nel modo più veloce ed efficiente possibile. Non è all'ultima +moda tra i linguaggi di programmazione, ma è una delle migliori soluzioni +per risolvere in maniera efficace i problemi di tutti i giorni. + +Go presenta alcuni concetti già presenti nei linguaggi imperativi con +tipizzazione statica. Compila velocemente ed esegue altrettanto veloce. +Aggiunge la concorrenza in maniera diretta e semplice da capire, per far +forza sulle CPU multi-core di oggigiorno. Presenta caratteristiche utili +per la programmazione in larga scala. + +Go comes with a great standard library and an enthusiastic community. + +```go +// Commento su riga singola +/* Commento + su riga multipla */ + +// In cima a ogni file è necessario specificare il package. +// Main è un package speciale che identifica un eseguibile anziché una libreria. +package main + +// Con import sono dichiarate tutte le librerie a cui si fa riferimento +// all'interno del file. +import ( + "fmt" // Un package nella libreria standard di Go. + "io/ioutil" // Implementa alcune funzioni di utility per l'I/O. + m "math" // Libreria matematica, con alias locale m + "net/http" // Sì, un web server! + "strconv" // Package per la conversione di stringhe. +) + +// Una definizione di funzione. Il main è speciale: è il punto di ingresso +// per il programma. Amalo o odialo, ma Go usa le parentesi graffe. +func main() { + // Println stampa una riga a schermo. + // Questa funzione è all'interno del package fmt. + fmt.Println("Ciao mondo!") + + // Chiama un'altra funzione all'interno di questo package. + oltreIlCiaoMondo() +} + +// Le funzioni ricevono i parametri all'interno di parentesi tonde. +// Se la funzione non riceve parametri, vanno comunque messe le parentesi (vuote). +func oltreIlCiaoMondo() { + var x int // Dichiarazione di una variabile. Ricordati di dichiarare sempre le variabili prima di usarle! + x = 3 // Assegnazione di una variabile. + // E' possibile la dichiarazione "rapida" := per inferire il tipo, dichiarare e assegnare contemporaneamente. + y := 4 + // Una funzione che ritorna due valori. + somma, prod := imparaMoltepliciValoriDiRitorno(x, y) + fmt.Println("somma:", somma, "prodotto:", prod) // Semplice output. + imparaTipi() // < y minuti, devi imparare ancora! +} + +/* <- commento su righe multiple +Le funzioni possono avere parametri e ritornare (molteplici!) valori. +Qua, x e y sono gli argomenti, mentre somma e prod sono i valori ritornati. +Da notare il fatto che x e somma vengono dichiarati come interi. +*/ +func imparaMoltepliciValoriDiRitorno(x, y int) (somma, prod int) { + return x + y, x * y // Ritorna due valori. +} + +// Ecco alcuni tipi presenti in Go +func imparaTipi() { + // La dichiarazione rapida di solito fa il suo lavoro. + str := "Impara il Go!" // Tipo stringa. + + s2 := `Una stringa letterale +puo' includere andata a capo.` // Sempre di tipo stringa. + + // Stringa letterale non ASCII. I sorgenti Go sono in UTF-8. + g := 'Σ' // Il tipo runa, alias per int32, è costituito da un code point unicode. + + f := 3.14195 // float64, un numero in virgola mobile a 64-bit (IEEE-754) + + c := 3 + 4i // complex128, rappresentato internamente con due float64. + + // Inizializzare le variabili con var. + var u uint = 7 // Senza segno, ma la dimensione dipende dall'implementazione (come l'int) + var pi float32 = 22. / 7 + + // Sintassi per la conversione. + n := byte('\n') // Il tipo byte è un alias per uint8. + + // I vettori hanno dimensione fissa, stabilita durante la compilazione. + var a4 [4]int // Un vettore di 4 interi, tutti inizializzati a 0. + a3 := [...]int{3, 1, 5} // Un vettore inizializzato con una dimensione fissa pari a 3, i cui elementi sono 3, 1 e 5. + + // Gli slice hanno dimensione variabile. Vettori e slice hanno pro e contro, + // ma generalmente si tende a usare più spesso gli slice. + s3 := []int{4, 5, 9} // La differenza con a3 è che qua non ci sono i 3 punti all'interno delle parentesi quadre. + s4 := make([]int, 4) // Alloca uno slice di 4 interi, tutti inizializzati a 0. + var d2 [][]float64 // Semplice dichiarazione, non vengono fatte allocazioni. + bs := []byte("uno slice") // Sintassi per la conversione. + + // Poiché gli slice sono dinamici, è possibile aggiungere elementi + // quando è necessario. Per farlo, si usa la funzione append(). Il primo + // argomento è lo slice a cui stiamo aggiungendo elementi. Di solito + // lo slice viene aggiornato, senza fare una copia, come nell'esempio: + s := []int{1, 2, 3} // Il risultato è uno slice di dimensione 3. + s = append(s, 4, 5, 6) // Aggiunge 3 elementi: lo slice ha dimensione 6. + fmt.Println(s) // Lo slice aggiornato è [1 2 3 4 5 6] + // Per aggiungere un altro slice, invece che elencare gli elementi uno ad + // uno, è possibile passare alla funzione append un riferimento ad uno + // slice, oppure uno slice letterale: in questo caso si usano i tre punti, + // dopo lo slice, a significare "prendi ciascun elemento dello slice": + s = append(s, []int{7, 8, 9}...) // Il secondo argomento è uno slice letterale. + fmt.Println(s) // Lo slice aggiornato è [1 2 3 4 5 6 7 8 9] + + p, q := imparaLaMemoria() // Dichiara due puntatori a intero: p e q. + fmt.Println(*p, *q) // * dereferenzia un puntatore. Questo stampa due interi. + + // Una variabile di tipo map è un vettore associativo di dimensione variabile, + // e funzionano come le tabelle di hash o i dizionari in altri linguaggi. + m := map[string]int{"tre": 3, "quattro": 4} + m["uno"] = 1 + + // Le variabili dichiarate e non usate sono un errore in Go. + // L'underscore permette di "usare" una variabile, scartandone il valore. + _, _, _, _, _, _, _, _, _, _ = str, s2, g, f, u, pi, n, a3, s4, bs + // Stampare a schermo ovviamente significa usare una variabile. + fmt.Println(s, c, a4, s3, d2, m) + + imparaControlloDiFlusso() // Torniamo in carreggiata. +} + +// In Go è possibile associare dei nomi ai valori di ritorno di una funzione. +// Assegnare un nome al tipo di dato ritornato permette di fare return in vari +// punti all'interno del corpo della funzione, ma anche di usare return senza +// specificare in modo esplicito che cosa ritornare. +func imparaValoriDiRitornoConNome(x, y int) (z int) { + z = x * y + return // z è implicito, perchè compare nella definizione di funzione. +} + +// Go è dotato di garbage collection. Ha i puntatori, ma non l'aritmetica dei +// puntatori. Puoi fare errori coi puntatori a nil, ma non puoi direttamente +// incrementare un puntatore. +func imparaLaMemoria() (p, q *int) { + // I valori di ritorno (con nome) p e q sono puntatori a int. + p = new(int) // La funzione new si occupa di allocare memoria. + // L'int allocato viene inizializzato a 0, dunque p non è più nil. + s := make([]int, 20) // Alloca 20 int come un singolo blocco di memoria. + s[3] = 7 // Ne assegna uno. + r := -2 // Dichiara un'altra variabile locale + return &s[3], &r // & "prende" l'indirizzo di un oggetto. +} + +func calcoloCostoso() float64 { + return m.Exp(10) +} + +func imparaControlloDiFlusso() { + // L'istruzione if richiede parentesi graffe per il corpo, mentre non ha + // bisogno di parentesi tonde per la condizione. + if true { + fmt.Println("te l'ho detto") + } + // Eseguendo "go fmt" da riga di comando, il codice viene formattato + // in maniera standard. + if false { + // :( + } else { + // :D + } + // L'istruzione switch serve ad evitare tanti if messi in cascata. + x := 42.0 + switch x { + case 0: + case 1: + case 42: + // Quando è soddisfatta la condizione all'interno di un case, il + // programma esce dal switch senza che siano specificate istruzioni + // di tipo "break". In Go infatti di default non è presente il + // cosiddetto "fall through" all'interno dell'istruzione switch. + // Tuttavia, il linguaggio mette a disposizione la parola chiave + // fallthrough per permettere, in casi particolari, questo comportamento. + case 43: + // Non si arriva qua. + default: + // Il caso di default è opzionale. + } + // Come l'if, anche il for non usa parentesi tonde per la condizione. + // Le variabili dichiarate all'interno di if/for sono locali al loro scope. + for x := 0; x < 3; x++ { // ++ è un'istruzione! + fmt.Println("ciclo numero", x) + } + // x == 42 qua. + + // Il for è l'unica istruzione per ciclare in Go, ma ha varie forme. + for { // Ciclo infinito. + break // Scherzavo. + continue // Non si arriva qua. + } + + // Puoi usare range per ciclare su un vettore, slice, stringa, mappa o canale. + // range ritorna uno (per i canali) o due valori (vettore, slice, stringa, mappa). + for chiave, valore := range map[string]int{"uno": 1, "due": 2, "tre": 3} { + // per ogni coppia dentro la mappa, stampa chiave e valore + fmt.Printf("chiave=%s, valore=%d\n", chiave, valore) + } + + // Come nel for, := dentro la condizione dell'if è usato per dichiarare + // e assegnare y, poi testare se y > x. + if y := calcoloCostoso(); y > x { + x = y + } + // Le funzioni letterali sono closure. + xGrande := func() bool { + return x > 10000 // Si riferisce a x dichiarata sopra al switch (vedi sopra). + } + fmt.Println("xGrande:", xGrande()) // true (abbiamo assegnato e^10 a x). + x = 1.3e3 // Adesso x == 1300 + fmt.Println("xGrande:", xGrande()) // false ora. + + // Inoltre le funzioni letterali possono essere definite e chiamate + // inline, col ruolo di parametri di funzione, a patto che: + // a) la funzione letterale venga chiamata subito (), + // b) il valore ritornato è in accordo con il tipo dell'argomento. + fmt.Println("Somma e raddoppia due numeri: ", + func(a, b int) int { + return (a + b) * 2 + }(10, 2)) // Chiamata con argomenti 10 e 2 + // => Somma e raddoppia due numeri: 24 + + // Quando ti servirà, lo amerai. + goto amore +amore: + + imparaFabbricaDiFunzioni() // Una funzione che ritorna un'altra funzione è divertente! + imparaDefer() // Un tour veloce di una parola chiave importante. + imparaInterfacce() // Arriva la roba buona! +} + +func imparaFabbricaDiFunzioni() { + // Questi due blocchi di istruzioni sono equivalenti, ma il secondo è più semplice da capire. + fmt.Println(fabbricaDiFrasi("estate")("Una bella giornata", "giornata!")) + + d := fabbricaDiFrasi("estate") + fmt.Println(d("Una bella", "giornata!")) + fmt.Println(d("Un pigro", "pomeriggio!")) +} + +// I decoratori sono comuni in alcuni linguaggi. Si può fare lo stesso in Go +// con le funzioni letterali che accettano argomenti. +func fabbricaDiFrasi(miaStringa string) func(prima, dopo string) string { + return func(prima, dopo string) string { + return fmt.Sprintf("%s %s %s", prima, miaStringa, dopo) // Nuova stringa + } +} + +func imparaDefer() (ok bool) { + // Le istruzioni dette "deferred" (rinviate) sono eseguite + // appena prima che la funzione ritorni. + defer fmt.Println("le istruzioni 'deferred' sono eseguite in ordine inverso (LIFO).") + defer fmt.Println("\nQuesta riga viene stampata per prima perché") + // defer viene usato di solito per chiudere un file, così la funzione che + // chiude il file viene messa vicino a quella che lo apre. + return true +} + +// Definisce Stringer come un'interfaccia con un metodo, String. +type Stringer interface { + String() string +} + +// Definisce coppia come una struct con due campi interi, chiamati x e y. +type coppia struct { + x, y int +} + +// Definisce un metodo sul tipo coppia, che adesso implementa Stringer. +func (p coppia) String() string { // p viene definito "ricevente" + // Sprintf è un'altra funzione del package ftm. + // La notazione con il punto serve per richiamare i campi di p. + return fmt.Sprintf("(%d, %d)", p.x, p.y) +} + +func imparaInterfacce() { + // Brace syntax is a "struct literal". It evaluates to an initialized + // struct. The := syntax declares and initializes p to this struct. + // Le parentesi graffe sono usate per le cosiddette "struct letterali". + // Con :=, p viene dichiarata e inizializzata a questa struct. + p := coppia{3, 4} + fmt.Println(p.String()) // Chiama il metodo String di p, che è di tipo coppia. + var i Stringer // Dichiara i come interfaccia Stringer. + i = p // Valido perchè coppia implementa Stringer. + // Chiama il metodo String di i, che è di tipo Stringer. Output uguale a sopra. + fmt.Println(i.String()) + + // Functions in the fmt package call the String method to ask an object + // for a printable representation of itself. + // Le funzioni dentro al package fmt chiamano il metodo String per + // chiedere ad un oggetto una rappresentazione in stringhe di sé stesso. + fmt.Println(p) // Output uguale a sopra. Println chiama il metodo String. + fmt.Println(i) // Output uguale a sopra. + + imparaParametriVariadici("grande", "imparando", "qua!") +} + +// Le funzioni possono avere parametri variadici (ovvero di lunghezza variabile). +func imparaParametriVariadici(mieStringhe ...interface{}) { + // Cicla su ogni valore variadico. + // L'underscore serve a ignorare l'indice del vettore. + for _, param := range mieStringhe { + fmt.Println("parametro:", param) + } + + // Passa un valore variadico come parametro variadico. + fmt.Println("parametri:", fmt.Sprintln(mieStringhe...)) + + imparaGestioneErrori() +} + +func imparaGestioneErrori() { + // La sintassi ", ok" è usata per indicare se qualcosa ha funzionato o no. + m := map[int]string{3: "tre", 4: "quattro"} + if x, ok := m[1]; !ok { // ok sarà false perchè 1 non è dentro la mappa. + fmt.Println("qua non c'è nessuno!") + } else { + fmt.Print(x) // x sarebbe il valore che corrisponde alla chiave 1, se fosse nella mappa. + } + // Un errore non riporta soltanto "ok" ma è più specifico riguardo al problema. + if _, err := strconv.Atoi("non_intero"); err != nil { // _ scarta il valore + // stampa 'strconv.ParseInt: parsing "non_intero": invalid syntax' + fmt.Println(err) + } + // Approfondiremo le interfacce un'altra volta. Nel frattempo, + imparaConcorrenza() +} + +// c è un canale, un oggetto per comunicare in modo concorrente e sicuro. +func inc(i int, c chan int) { + c <- i + 1 // <- è l'operatore di "invio" quando un canale sta a sinistra. +} + +// Useremo inc per incrementare alcuni numeri in modo concorrente. +func imparaConcorrenza() { + // Stessa funzione usata prima per creare uno slice. Make alloca e + // inizializza slice, mappe e canali. + c := make(chan int) + // Lancia tre goroutine. I numeri saranno incrementati in modo concorrente, + // forse in parallelo se la macchina lo supporta. Tutti e tre inviano dati + // sullo stesso canale. + go inc(0, c) // go è un'istruzione che avvia una goroutine. + go inc(10, c) + go inc(-805, c) + // Legge tre risultati dal canale e li stampa a schermo. + // Non si conosce a priori l'ordine in cui i risultati arriveranno! + fmt.Println(<-c, <-c, <-c) // <- è l'operatore di "ricevuta" quando + // un canale sta a destra. + + cs := make(chan string) // Un altro canale, gestisce le stringhe. + ccs := make(chan chan string) // Un canale che gestisce canali di stringhe. + go func() { c <- 84 }() // Lancia una goroutine, solo per inviare un valore. + go func() { cs <- "parolina" }() // Stessa cosa ma per cs. + // select è simile a switch, ma ogni case riguarda un'operazione su un + // canale. Seleziona, in modo random, uno tra i canali che sono pronti + // a comunicare. + select { + case i := <-c: // Il valore ricevuto può essere assegnato a una variabile, + fmt.Printf("E' un %T", i) + case <-cs: // oppure il valore ricevuto può essere scartato. + fmt.Println("E' una stringa.") + case <-ccs: // Canale vuoto, non pronto per comunicare. + fmt.Println("Non succede niente.") + } + // A questo punto un valore è stato preso da c o cs. Una delle tue goroutine + // cominciate sopra ha completato l'esecuzione, l'altra rimarrà bloccata. + + imparaProgrammazioneWeb() // Se lo fa Go, lo puoi fare anche tu. +} + +// Una funzione all'interno del package http avvia un webserver. +func imparaProgrammazioneWeb() { + + // Il primo parametro di ListenAndServe è l'indirizzo TCP su cui ascoltare. + // Il secondo parametro è un'interfaccia, precisamente http.Handler. + go func() { + err := http.ListenAndServe(":8080", coppia{}) + fmt.Println(err) // Non ignorare gli errori. + }() + + richiediServer() +} + +// Per rendere coppia un http.Handler basta implementare il metodo ServeHTTP. +func (p coppia) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Il server fornisce dati con un metodo di http.ResponseWriter. + w.Write([]byte("Hai imparato Go in Y minuti!")) +} + +func richiediServer() { + risposta, err := http.Get("http://localhost:8080") + fmt.Println(err) + defer risposta.Body.Close() + corpo, err := ioutil.ReadAll(risposta.Body) + fmt.Printf("\nIl webserver dice: `%s`", string(corpo)) +} +``` + +## Letture consigliate + +La risorsa più importante per imparare il Go è il [sito ufficiale di Go](http://golang.org/). +Qui puoi seguire i tutorial, scrivere codice in modo interattivo, e leggere tutti i dettagli. +Oltre al tour, [la documentazione](https://golang.org/doc/) contiene informazioni su +come scrivere ottimo codice in Go, documentazione sui package e sui comandi, e +la cronologia delle release. + +Anche il documento che definisce il linguaggio è un'ottima lettura. E' semplice +da leggere e incredibilmente corto (rispetto ad altri documenti riguardanti +la creazione di linguaggi). + +Puoi giocare con il codice visto finora nel [Go playground](https://play.golang.org/p/Am120Xe7qf). +Prova a cambiarlo e ad eseguirlo dal browser! +Osserva che puoi usare [https://play.golang.org](https://play.golang.org) come +una [REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) per scrivere +codice all'interno del browser, senza neanche installare Go! + +Una lettura importante per capire Go in modo più profondo è il [codice +sorgente della libreria standard](http://golang.org/src/pkg/). Infatti è +molto ben documentato e costituisce quanto più chiaro e conciso ci sia riguardo +gli idiomi e le buone pratiche del Go. Inoltre, clickando sul nome di una +funzione [nella documentazione](http://golang.org/pkg/) compare il relativo +codice sorgente! + +Un'altra ottima risorsa per imparare è [Go by example](https://gobyexample.com/). + +Go Mobile aggiunge il supporto per lo sviluppo mobile (Android e iOS). +In questo modo è possibile scrivere un'app mobile nativa in Go, oppure +una libreria che contiene binding da un package scritto in Go, e che può +essere richiamata da Java(Android) e Objective-C(iOS). Visita la pagina di +[Go Mobile](https://github.com/golang/go/wiki/Mobile) per maggiori informazioni. diff --git a/it-it/logtalk-it.html.markdown b/it-it/logtalk-it.html.markdown new file mode 100644 index 00000000..7f1e9eeb --- /dev/null +++ b/it-it/logtalk-it.html.markdown @@ -0,0 +1,550 @@ +--- +language: Logtalk +filename: learnlogtalk-it.lgt +contributors: + - ["Paulo Moura", "http://github.com/pmoura"] +translators: + - ["Ugo Chirico", "https://github.com/ugochirico"] +lang: it-it +--- + +Logtalk è un linguaggio di programmazione logica orientata agli oggetti che estende il linguaggio Prolog con le moderne tecniche di Object-Oriented Programming quali incapsulamento, ereditarietà e riutilizzo del codice, senza compromettere le caratteristiche di programmazione dichiarativa del Prolog. Logtalk è implementato in codice altamente portabile e utilizza i più moderni standard di conformità del Prolog rispetto al compilatore backend. + +Per mantenere una dimensione ragionevole, questo tutorial presuppone necessariamente che il lettore abbia una conoscenza del linguaggio Prolog ed è inoltre focalizzato esclusivamente sulla descrizione delle caratteristiche object-oriented di Logtalk. + +# Sintassi + +Logtalk utilizza la sintassi standard del linguaggio Prolog con l'aggiunta di un paio di operatori e di alcune direttive per una curva di apprendimento morbida e per assicurare ampia portabilità. Una conseguenza importante è che il codice Prolog può essere facilmente incapsulato in oggetti con poche o nessuna modifica. Inoltre, Logtalk può interpretare come oggetti Logtalk, in modo trasparente, la maggior parte dei moduli Prolog già esistenti. + +I principali operatori sono: + +* `::/2` - per inviare un messaggio ad un oggetto +* `::/1` - per inviare un messaggio a se stesso _self_ (cioè all'oggetto che riceverà il messaggio) +* `^^/1` - _super_ per chiamare un predicato ereditato o importato + +Alcune delle più importanti entità e direttive saranno introdotte nelle sezioni successive. + +# Entità e Ruoli + +Logtalk tratta gli oggetti, i protocolli e le categorie come entità di prima classe. I rapporti tra le entità definiscono i _patterns of code reuse_ ossia i modelli di riutilizzo del codice e i _roles_ ossia i ruoli svolti da tali entità. Ad esempio, quando un oggetto istanzia un altro oggetto, il primo oggetto assume il ruolo di istanza e il secondo oggetto assume il ruolo di classe. Una relazione di tipo _extends_ tra due oggetti implica che entrambi gli oggetti svolgano il ruolo di prototipi, in cui uno di loro estende l'altro, che diventa quindi suo prototipo padre. + +# Definizione di un oggetto + +Un oggetto incapsula le dichiarazioni e le definizioni dei predicati. Gli oggetti possono essere creati in modo dinamico, ma di solito sono dichiarati come statici e definiti nel codice sorgente. Un singolo file sorgente può contenere un qualsiasi numero di definizioni di entità. Ecco un semplice oggetto `list` che definisce un membro pubblico `member/2`: + +```logtalk +:- object(list). + + :- public(member/2). + member(Head, [Head| _]). + member(Head, [_| Tail]) :- + member(Head, Tail). + +:- end_object. +``` + +# Compilazione dei file sorgenti + +Supponendo che il codice di cui sopra per l'oggetto `list` venga salvato in un file` list.lgt`, esso può essere compilato e caricato utilizzando il predicato predefiniti `logtalk_load/1` o la sua abbreviazione `{}/1`, con il percorso del file come argomento (l'estensione può essere omessa): + +```logtalk +?- {list}. +yes +``` + +# Inviare un messaggio ad un oggetto + +L'operatore infisso `::/2` è usato per inviare messaggi ad un oggetto. Analogamente al Prolog, è possibile fare backtracking per le soluzioni alternative: + +```logtalk +?- list::member(X, [1,2,3]). +X = 1 ; +X = 2 ; +X = 3 +yes +``` + +Analogamente alla programmazione object-oriented, logtalk consente anche l'Incapsulamento. +Un predicato può essere dichiarata pubblico, protetto o privato. Può anche essere _local_ quando non esiste una direttiva specifica per esso all'interno dello scope. Per esempio: + +```logtalk +:- object(scopes). + + :- private(bar/0). + bar. + + local. + +:- end_object. +``` + +Assumendo che l'oggetto è salvato nel file `scopes.lgt`: + +```logtalk +?- {scopes}. +yes + +?- catch(scopes::bar, Error, true). +Error = error( + permission_error(access, private_predicate, bar/0), + logtalk(scopes::bar, user) +) +yes + +?- catch(scopes::local, Error, true). +Error = error( + existence_error(predicate_declaration, local/0), + logtalk(scopes::local, user) +) +yes +``` + +Quando il predicato in un messaggio non è noto per l'oggetto (il ruolo dell'oggetto determina le procedure di ricerca), si ha un errore. +Per esempio: + +```logtalk +?- catch(scopes::unknown, Error, true). +Error = error( + existence_error(predicate_declaration, unknown/0), + logtalk(scopes::unknown, user) +) +yes +``` + +Un punto fondamentale da capire è che le direttive che specificano il predicato nello scope specificano la semantica di chiamata (_calling_) del predicato, e non la semantica di definizione (_definition_). Ad esempio, se un oggetto ha il ruolo di una classe e dichiara un predicato privato, tale predicato può essere definito nelle sue sottoclassi e nelle istanze * ma * può essere chiamato solo nelle sue istanza (_from_) dalla classe. + +# Definizione e implementazione di un protocollo + +Un Protocollo contiene le dichiarazioni dei predicati che possono essere implementati da un qualsivoglia numero di oggetti e categorie: + +```logtalk +:- protocol(listp). + + :- public(member/2). + +:- end_protocol. + +:- object(list, + implements(listp)). + + member(Head, [Head| _]). + member(Head, [_| Tail]) :- + member(Head, Tail). + +:- end_object. +``` + +Lo scope dei predicati di un protocollo può essere ristretto usando implementazioni protected e private. Ad esempio: + +```logtalk +:- object(stack, + implements(private::listp)). + +:- end_object. +``` + +Difatti, tutte le relazioni tra entità (nella direttiva di apertura di un entità) possono essere definite come public (default), protected, o private. + +# Prototipi + +Un oggetto senza una istanza o senza una relazione di specializzazione con un altro oggetto interpreta il ruolo di prototipo. Un prototipo può estendere un altro oggetto, il suo prototipo genitore. + +```logtalk +% clyde, our prototypical elephant +:- object(clyde). + + :- public(color/1). + color(grey). + + :- public(number_of_legs/1). + number_of_legs(4). + +:- end_object. + +% fred, another elephant, is like clyde, except that he's white +:- object(fred, + extends(clyde)). + + color(white). + +:- end_object. +``` + +Per rispondere ad un messaggio inviato ad un oggetto che ha il ruolo di prototipo, si cerca prima una risposta nel prototipo stesso e se il prototipo non sa rispondere si passa all'eventuale prototipo genitore (se esiste): + +```logtalk +?- fred::number_of_legs(N). +N = 4 +yes + +?- fred::color(C). +C = white +yes +``` + +Un messaggio è valido se il relativo predicato è dichiarato in un oggetto (e se il mittente è nel campo di applicazione), ma fallirà, piuttosto che lanciare un errore, se il predicato non è definito. Questa è chiamata la _closed-world assumption_. Ad esempio, si consideri il seguente oggetto, salvato in un file `foo.lgt`: + +```logtalk +:- object(foo). + + :- public(bar/0). + +:- end_object. +``` + +Caricando il file e cercando di chiamare il predicato `bar/0` questo fallisce come previsto. Si noti che ciò è diverso dal chiamare un predicato sconosciuto _unknown_, che invece genera un errore: + +```logtalk +?- {foo}. +yes + +?- foo::bar. +no + +?- catch(foo::baz, Error, true). +Error = error( + existence_error(predicate_declaration, baz/0), + logtalk(foo::baz, user) +) +yes +``` + +# Classi e istanze + +Per definire gli oggetti nei ruoli di classi e/o istanze, un oggetto deve avere almeno un istanziazione o una relazione di specializzazione con un altro oggetto. Gli oggetti che hanno il ruolo di meta-classi possono essere utilizzati quando abbiamo bisogno di usare una classe come se fosse un'istanza. Il seguente esempio mostra come creare dinamicamente nuovi oggetti in fase di esecuzione: + +```logtalk +% a simple, generic, metaclass defining a new/2 predicate for its instances +:- object(metaclass, + instantiates(metaclass)). + + :- public(new/2). + new(Instance, Clauses) :- + self(Class), + create_object(Instance, [instantiates(Class)], [], Clauses). + +:- end_object. + +% a simple class defining age/1 and name/1 predicate for its instances +:- object(person, + instantiates(metaclass)). + + :- public([ + age/1, name/1 + ]). + + % a default value for age/1 + age(42). + +:- end_object. + +% a static instance of the class person +:- object(john, + instantiates(person)). + + name(john). + age(12). + +:- end_object. +``` + +Nel rispondere ad un messaggio inviato ad un oggetto ha assunto il ruolo di istanza, tal messaggio viene convalidato partendo dalla sua classe e andando a ritroso nella gerarchia, se necessario, fino alle sue superclassi. Supponendo che il messaggio sia valido, allora si cerca una risposta a partire dall'istanza stessa: + +```logtalk +?- person::new(Instance, [name(paulo)]). +Instance = o1 +yes + +?- o1::name(Name). +Name = paulo +yes + +?- o1::age(Age). +Age = 42 +yes + +?- john::age(Age). +Age = 12 +yes +``` + +# Categorie + +Una categoria è un'unità atomica di codice riutilizzabile. Una categoria è usata per incapsulare una insieme coesivo (_cohesive_) di dichiarazioni e di definizioni di predicato ed è atta ad implementare una singola (_single_) funzionalità che può essere importata in qualsiasi oggetto. Una categoria può quindi essere concepita come il concetto duale di protocollo. Nel seguente esempio, si definiscono prima le categorie che rappresentano i motori di auto e poi si importano tali categorie negli oggetti auto: + +```logtalk +% a protocol describing engine characteristics +:- protocol(carenginep). + + :- public([ + reference/1, + capacity/1, + cylinders/1, + horsepower_rpm/2, + bore_stroke/2, + fuel/1 + ]). + +:- end_protocol. + +% a typical engine defined as a category +:- category(classic, + implements(carenginep)). + + reference('M180.940'). + capacity(2195). + cylinders(6). + horsepower_rpm(94, 4800). + bore_stroke(80, 72.8). + fuel(gasoline). + +:- end_category. + +% a souped up version of the previous engine +:- category(sport, + extends(classic)). + + reference('M180.941'). + horsepower_rpm(HP, RPM) :- + ^^horsepower_rpm(ClassicHP, ClassicRPM), % "super" call + HP is truncate(ClassicHP*1.23), + RPM is truncate(ClassicRPM*0.762). + +:- end_category. + +% with engines (and other components), we may start "assembling" some cars +:- object(sedan, + imports(classic)). + +:- end_object. + +:- object(coupe, + imports(sport)). + +:- end_object. +``` + +Le Categorie sono compilate in modo indipendente e, quindi, consentono l'importazione di oggetti da aggiornare mediante il semplice aggiornamento delle categorie importate, senza richiedere pertanto la ricompilazione dell'oggetto. Le Categorie forniscono anche la _runtime transparency_, cioè il protocollo della categoria si aggiunge al protocollo degli oggetti che importano tale categoria: + +```logtalk +?- sedan::current_predicate(Predicate). +Predicate = reference/1 ; +Predicate = capacity/1 ; +Predicate = cylinders/1 ; +Predicate = horsepower_rpm/2 ; +Predicate = bore_stroke/2 ; +Predicate = fuel/1 +yes +``` + +# Hot patching + +Le categorie possono essere anche usate per modificare gli oggetti al volo (_hot-patch_). Una categoria può aggiungere nuovi predicati ad un oggetto e/o sostituire le definizioni dei predicati dell'oggetto. Ad esempio, si consideri il seguente oggetto: + +```logtalk +:- object(buggy). + + :- public(p/0). + p :- write(foo). + +:- end_object. +``` + +Si supponga che l'oggetto stampi la stringa sbagliata quando riceve il messaggio `p/0`: + +```logtalk +?- {buggy}. +yes + +?- buggy::p. +foo +yes +``` + +Se il codice sorgente dell'oggetto non è disponibile e bisogna correggere l'applicazione che sta eseguendo il codice dell'oggetto, si può semplicemente definire una categoria che corregge il predicato non corretto: + +```logtalk +:- category(patch, + complements(buggy)). + + % fixed p/0 def + p :- write(bar). + +:- end_category. +``` + +Dopo la compilazione e il caricamento della categoria nell'applicazione in esecuzione si ottiene: + +```logtalk +?- {patch}. +yes + +?- buggy::p. +bar +yes +``` + +Poiché l'hot-patching pregiudica forzatamente l'incapsulamento, un apposito flag di compilazione `complementary` può essere impostato (a livello globale o per un singolo oggetto) per consentire, limitare o prevenire l'hot-patching. + +# Oggetti Parametrici e Categorie + +Gli oggetti e le categorie possono essere parametrizzati utilizzando come identificativo un compound-term al posto di un atomo. Oggetti e parametri di una categoria sono variabili logiche _logical variables_ condivise con tutti i predicati incapsulati. Ecco un esempio con cerchi geometrici: + +```logtalk +:- object(circle(_Radius, _Color)). + + :- public([ + area/1, perimeter/1 + ]). + + area(Area) :- + parameter(1, Radius), + Area is pi*Radius*Radius. + + perimeter(Perimeter) :- + parameter(1, Radius), + Perimeter is 2*pi*Radius. + +:- end_object. +``` + +Oggetti parametrici possono essere utilizzati come qualsiasi altro oggetto e di solito forniscono i valori da assegnare ai parametri quando si invia un messaggio: + +```logtalk +?- circle(1.23, blue)::area(Area). +Area = 4.75291 +yes +``` + +Gli oggetti parametrici forniscono anche un modo semplice per associare un insieme di predicati con un semplice predicato Prolog. Fatti Prolog possono essere interpretati come oggetti proxy parametrici ( _parametric object proxies_) quando hanno lo stesso funtore e arietà degli identificatori di oggetti parametrici. Per lavorare con i proxy viene fornita una sintassi maneggevole. Per esempio, si prendano le seguenti clausole per il predicato `circle/2`: + +```logtalk +circle(1.23, blue). +circle(3.71, yellow). +circle(0.39, green). +circle(5.74, black). +circle(8.32, cyan). +``` + +Con queste clausole, si può facilmente calcolare, ad esempio, un elenco con le aree di tutti i cerchi: + +```logtalk +?- findall(Area, {circle(_, _)}::area(Area), Areas). +Areas = [4.75291, 43.2412, 0.477836, 103.508, 217.468] +yes +``` + +In pratica, il costrutto `{Goal}::Message` prova il goal `Goal`, instanziando le variabili interne e inviando un messaggio `Message` al termine risultante. + +# Eventi and monitor + +Logtalk supporta l'_event-driven programming_ mediante la definizione di eventi e di monitor. Un evento è semplicemente l'invio di un messaggio ad un oggetto. Un monitor è un gestore di un evento. L'evento (con l'invio di un messaggio) è un'attività atomica, ed è preceduta da un evento _before_ e da un evento _after_. Il monitor gestisce tali eventi mediante i predicati, `before/3` e `after/3`, che sono chiamati rispettivamente prima e dopo il verificarsi dell'evento. Un monitor può inoltre interrogare, registrare e cancellare un evento nel registro eventi a livello di sistema il quale che associa gli eventi con i monitor. Ad esempio, un semplice tracer per ogni messaggio inviato utilizzando il costrutto `::/2` può essere definito come: + +```logtalk +:- object(tracer, + implements(monitoring)). % built-in protocol for event handlers + + :- initialization(define_events(_, _, _, _, tracer)). + + before(Object, Message, Sender) :- + write('call: '), writeq(Object), write(' <-- '), writeq(Message), + write(' from '), writeq(Sender), nl. + + after(Object, Message, Sender) :- + write('exit: '), writeq(Object), write(' <-- '), writeq(Message), + write(' from '), writeq(Sender), nl. + +:- end_object. +``` + +Supponendo che l'oggetto `tracer` e l'oggetto `list` definito in precedenza siano stati già compilati e caricati, si possono osservare i gestori di eventi in azione durante l'invio di un messaggio: + +```logtalk +?- list::member(X, [1,2,3]). + +call: list <-- member(X, [1,2,3]) from user +exit: list <-- member(1, [1,2,3]) from user +X = 1 ; +exit: list <-- member(2, [1,2,3]) from user +X = 2 ; +exit: list <-- member(3, [1,2,3]) from user +X = 3 +yes +``` + +Gli eventi possono essere impostati e cancellati dinamicamente in fase di esecuzione chiamando i predicati predefiniti `define_events/5` e` abolish_events/5` . + +La programmazione event-driven può essere vista come una forma di _computational reflection_. Si noti però che gli eventi sono generati solo quando si utilizza il costrutto di controllo per l'invio di messaggi `::/2`. + +# Espressioni lambda + +Logtalk supporta anche le espressioni lambda. I parametri della espressioni lambda sono rappresentati mediante una lista con l'operatore infisso `(>>)/2` che collega i parametri alla relativa lambda espressione. Ecco alcuni semplici esempi di che usano i meta-predicati. + + +```logtalk +?- {library(metapredicates_loader)}. +yes + +?- meta::map([X,Y]>>(Y is 2*X), [1,2,3], Ys). +Ys = [2,4,6] +yes +``` + +Logtalk supporta anche il _currying_: + +```logtalk +?- meta::map([X]>>([Y]>>(Y is 2*X)), [1,2,3], Ys). +Ys = [2,4,6] +yes +``` + +Infine, le variabili libere Lambda possono essere espresso usando la sintassi estesa `{Free1, ...}/[Parameter1, ...]>>Lambda`. + +# Macro + +I Termini e goal nel file sorgente possono essere _estesi_ al momento della compilazione specificando una hook ad un oggetto (_hook object_) che definisce le regole di riscrittura dei termini e riscrittura dei quesiti. Ad esempio, si consideri il seguente oggetto semplice, salvato nel file `source.lgt`: + +```logtalk +:- object(source). + + :- public(bar/1). + bar(X) :- foo(X). + + foo(a). foo(b). foo(c). + +:- end_object. +``` + +Si supponga il seguente hook all'oggetto, salvato nel file `my_macros.lgt`, che estende le clausole e chiama il predicato locale `foo/1`: + +```logtalk +:- object(my_macros, + implements(expanding)). % built-in protocol for expanding predicates + + term_expansion(foo(Char), baz(Code)) :- + char_code(Char, Code). % standard built-in predicate + + goal_expansion(foo(X), baz(X)). + +:- end_object. +``` + +Dopo aver caricato il file contenente la macro, si può espandere il nostro file sorgente usando il flag del compilatore `hook`: + +```logtalk +?- logtalk_load(my_macros), logtalk_load(source, [hook(my_macros)]). +yes + +?- source::bar(X). +X = 97 ; +X = 98 ; +X = 99 +true +``` + +La libreria Logtalk fornisce infine il supporto per combinare hook agli oggetti utilizzando diversi modi (ad esempio, definendo una pipeline di espansioni). + + +# Maggiori informazioni + +Visita il [Sito web di Logtalk (en)](http://logtalk.org) per maggiori informazioni. diff --git a/it-it/markdown.html.markdown b/it-it/markdown.html.markdown new file mode 100644 index 00000000..b006dbb4 --- /dev/null +++ b/it-it/markdown.html.markdown @@ -0,0 +1,244 @@ +--- +language: markdown +contributors: + - ["Dan Turkel", "http://danturkel.com/"] +translators: + - ["Jacopo Andrea Giola", "http://geekpanda.net"] +filename: markdown-it.md +lang: it-it +--- + +Markdown è stato creato da John Gruber nel 2004. Il suo scopo è quello di essere una sintassi facile da leggere e scrivere, e che può essere convertita in HTML (ad oggi anche in molti altri formati). + +Mandate tutto il feedback che volete! / Sentitevi liberi di forkare o di mandare pull request! + + +```markdown +<!-- Markdown è un superset di HTML, quindi ogni file HTML è a sua volta un file Markdown valido. Questo significa che possiamo usare elementi di HTML in Markdown, come per esempio i commenti, e questi non saranno modificati dal parser di Markdown. State attenti però, se inserite un elemento HTML nel vostro file Markdown, non potrete usare la sua sintassi all'interno del contenuto dell'elemento. --> + +<!-- L'implementazione di Markdown inoltre cambia da parser a parser. In questa guida cercheremo di indicare quando una feature è universale e quando sono specifiche ad un certo parser. --> + +<!-- Titoli --> +<!-- Potete creare gli elementi HTML da <h1> ad <h6> facilmente, basta che inseriate un egual numero di caratteri cancelletto (#) prima del testo che volete all'interno dell'elemento --> +# Questo è un <h1> +## Questo è un <h2> +### Questo è un <h3> +#### Questo è un <h4> +##### Questo è un <h5> +###### Questo è un <h6> + +<!-- Markdown inoltre fornisce due alternative per indicare gli elementi h1 e h2 --> +Questo è un h1 +============== + +Questo è un h2 +-------------- + +<!-- Stili di testo semplici --> +<!-- Il testo può essere stilizzato in corsivo o grassetto usando markdown --> + +*Questo testo è in corsivo.* +_Come pure questo._ + +**Questo testo è in grassetto.** +__Come pure questo.__ + +***Questo testo è stilizzato in entrabmi i modi.*** +**_Come questo!_** +*__E questo!__* + +<!-- In Github Flavored Markdown, che è utilizzato per renderizzare i file markdown su +Github, è presente anche lo stile barrato --> + +~~Questo testo è barrato.~~ + +<!-- I paragrafi sono uno o più linee di testo addiacenti separate da una o più righe vuote. --> + +Qeusto è un paragrafo. Sto scrivendo in un paragrafo, non è divertente? + +Ora sono nel paragrafo 2. +Anche questa linea è nel paragrafo 2! + + +Qui siamo nel paragrafo 3! + +<!-- Se volete inserire l'elemento HTML <br />, potete terminare la linea con due o più spazi e poi iniziare un nuovo paragrafo. --> + +Questa frase finisce con due spazi (evidenziatemi per vederli). + +C'è un <br /> sopra di me! + +<!-- Le citazioni sono semplici da inserire, basta usare il carattere >. --> + +> Questa è una citazione. Potete +> mandare a capo manualmente le linee e inserire un `>` prima di ognuna, oppure potete usare una sola linea e lasciare che vada a capo automaticamente. +> Non c'è alcuna differenza, basta che iniziate ogni riga con `>`. + +> Potete utilizzare anche più di un livello +>> di indentazione! +> Quanto è comodo? + +<!-- Liste --> +<!-- Le liste non ordinate possono essere inserite usando gli asterischi, il simbolo più o dei trattini --> + +* Oggetto +* Oggetto +* Altro oggetto + +oppure + ++ Oggetto ++ Oggetto ++ Un altro oggetto + +oppure + +- Oggetto +- Oggetto +- Un ultimo oggetto + +<!-- Le liste ordinate invece, sono inserite con un numero seguito da un punto. --> + +1. Primo oggetto +2. Secondo oggetto +3. Terzo oggetto + +<!-- Non dovete nemmeno mettere i numeri nell'ordine giusto, markdown li visualizzerà comunque nell'ordine corretto, anche se potrebbe non essere una buona idea. --> + +1. Primo oggetto +1. Secondo oggetto +1. Terzo oggetto +<!-- (Questa lista verrà visualizzata esattamente come quella dell'esempio prima) --> + +<!-- Potete inserire anche sotto liste --> + +1. Primo oggetto +2. Secondo oggetto +3. Terzo oggetto + * Sotto-oggetto + * Sotto-oggetto +4. Quarto oggetto + +<!-- Sono presenti anche le task list. In questo modo è possibile creare checkbox in HTML. --> + +I box senza la 'x' sono checkbox HTML ancora da completare. +- [ ] Primo task da completare. +- [ ] Secondo task che deve essere completato. +Il box subito sotto è una checkbox HTML spuntata. +- [x] Questo task è stato completato. + +<!-- Estratti di codice --> +<!-- Potete inserire un estratto di codice (che utilizza l'elemento <code>) indentando una linea con quattro spazi oppure con un carattere tab --> + + Questa è una linea di codice + Come questa + +<!-- Potete inoltre inserire un altro tab (o altri quattro spazi) per indentare il vostro codice --> + + my_array.each do |item| + puts item + end + +<!-- Codice inline può essere inserito usando il carattere backtick ` --> + +Giovanni non sapeva neppure a cosa servisse la funzione `go_to()`! + +<!-- In Github Flavored Markdown, potete inoltre usare una sintassi speciale per il codice --> + +\`\`\`ruby <!-- In realtà dovete rimuovere i backslash, usate solo ```ruby ! --> +def foobar + puts "Hello world!" +end +\`\`\` <!-- Anche qui, niente backslash, solamente ``` --> + +<!-- Se usate questa sintassi, il testo non richiederà di essere indentanto, inoltre Github userà la syntax highlighting del linguaggio specificato dopo i ``` iniziali --> + +<!-- Linea orizzontale (<hr />) --> +<!-- Le linee orizzontali sono inserite facilemtne usanto tre o più asterischi o trattini senza spazi consecutivi e senza spazi. --> + +*** +--- +- - - +**************** + +<!-- Link --> +<!-- Una delle funzionalità migliori di markdown è la facilità con cui si possono inserire i link. Mettete il testo da visualizzare fra parentesi quadre [] seguite dall'url messo fra parentesi tonde () --> + +[Cliccami!](http://test.com/) + +<!-- Potete inoltre aggiungere al link un titolo mettendolo fra doppie apici dopo il link --> + +[Cliccami!](http://test.com/ "Link a Test.com") + +<!-- La sintassi funziona anche i path relativi. --> + +[Vai a musica](/music/). + +<!-- Markdown supporta inoltre anche la possibilità di aggiungere i link facendo riferimento ad altri punti del testo --> + +[Apri questo link][link1] per più informazioni! +[Guarda anche questo link][foobar] se ti va. + +[link1]: http://test.com/ "Bello!" +[foobar]: http://foobar.biz/ "Va bene!" + +<!-- Il titolo può anche essere inserito in apici singoli o in parentesi, oppure omesso interamente. Il riferimento può essere inserito in un punto qualsiasi del vostro documento e l'identificativo del riferimento può essere lungo a piacere a patto che sia univoco. --> + +<!-- Esiste anche un "identificativo implicito" che vi permette di usare il testo del link come id --> + +[Questo][] è un link. + +[Questo]: http://thisisalink.com/ + +<!-- Ma non è comunemente usato. --> + +<!-- Immagini --> +<!-- Le immagini sono inserite come i link ma con un punto esclamativo inserito prima delle parentesi quadre! --> + +![Qeusto è il testo alternativo per l'immagine](http://imgur.com/myimage.jpg "Il titolo opzionale") + +<!-- E la modalità a riferimento funziona esattamente come ci si aspetta --> + +![Questo è il testo alternativo.][myimage] + +[myimage]: relative/urls/cool/image.jpg "Se vi serve un titolo, lo mettete qui" + +<!-- Miscellanea --> +<!-- Auto link --> + +<http://testwebsite.com/> è equivalente ad +[http://testwebsite.com/](http://testwebsite.com/) + +<!-- Auto link per le email --> + +<foo@bar.com> + +<!-- Caratteri di escaping --> + +Voglio inserire *questo testo circondato da asterischi* ma non voglio che venga renderizzato in corsivo, quindi lo inserirò così: \*questo testo è circondato da asterischi\*. + +<!-- Combinazioni di tasti --> +<!-- In Github Flavored Markdown, potete utilizzare il tag <kbd> per raffigurare i tasti della tastiera --> + +Il tuo computer è crashato? Prova a premere +<kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Canc</kbd> + +<!-- Tabelle --> +<!-- Le tabelle sono disponibili solo in Github Flavored Markdown e sono leggeremente complesse, ma se proprio volete inserirle fate come segue: --> + +| Col1 | Col2 | Col3 | +| :------------------- | :------: | -----------------: | +| Allineato a sinistra | Centrato | Allineato a destra | +| blah | blah | blah | + +<!-- oppure, per lo stesso risultato --> + +Col 1 | Col2 | Col3 +:-- | :-: | --: +È una cosa orrenda | fatela | finire in fretta + +<!-- Finito! --> + +``` + +Per altre informazioni, leggete il post ufficiale di John Gruber sulla sintassi [qui](http://daringfireball.net/projects/markdown/syntax) e il magnifico cheatsheet di Adam Pritchard [qui](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet). diff --git a/it-it/matlab-it.html.markdown b/it-it/matlab-it.html.markdown new file mode 100644 index 00000000..aeb42658 --- /dev/null +++ b/it-it/matlab-it.html.markdown @@ -0,0 +1,526 @@ +--- +language: Matlab +contributors: + - ["mendozao", "http://github.com/mendozao"] + - ["jamesscottbrown", "http://jamesscottbrown.com"] + - ["Colton Kohnke", "http://github.com/voltnor"] +translators: + - ["Samuele Gallerani", "http://github.com/fontealpina"] +lang: it-it +filename: matlab-it.md +--- + +MATLAB sta per MATrix LABoratory ed è un potente linguaggio per il calcolo numerico comunemente usato in ingegneria e matematica. + +```matlab +% I commenti iniziano con il segno percentuale. + +%{ +I commenti multilinea +assomigliano a +qualcosa +del genere +%} + +% i comandi possono essere spezzati su più linee, usando '...': + a = 1 + 2 + ... + + 4 + +% i comandi possono essere passati al sistema operativo +!ping google.com + +who % Mostra tutte le variabili in memoria +whos % Mostra tutte le variabili in memoria, con i loro tipi +clear % Cancella tutte le tue variabili dalla memoria +clear('A') % Cancella una particolare variabile +openvar('A') % Apre la variabile in un editor di variabile + +clc % Cancella il contenuto della Command Window +diary % Attiva il log della Command Window su file +ctrl-c % Interrompe il calcolo corrente + +edit('myfunction.m') % Apre la funzione/script nell'editor +type('myfunction.m') % Stampa il codice della funzione/script sulla Command Window + +profile on % Attiva la profilazione del codice +profile off % Disattiva la profilazione del codice +profile viewer % Apre il profilatore + +help comando % Mostra la documentazione di comando sulla Command Window +doc comando % Mostra la documentazione di comando sulla Help Window +lookfor comando % Cerca comando nella prima linea di commento di tutte le funzioni +lookfor comando -all % Cerca comando in tutte le funzioni + + +% Formattazione dell'output +format short % 4 decimali in un numero float +format long % 15 decimali +format bank % Solo due cifre decimali - per calcoli finaziari +fprintf('text') % Stampa "text" a terminale +disp('text') % Stampa "text" a terminale + +% Variabili ed espressioni +miaVariabile = 4 % Il pannello Workspace mostra la nuova variabile creata +miaVariabile = 4; % Il punto e virgola evita che l'output venga stampato sulla Command Window +4 + 6 % ans = 10 +8 * myVariable % ans = 32 +2 ^ 3 % ans = 8 +a = 2; b = 3; +c = exp(a)*sin(pi/2) % c = 7.3891 + +% La chiamata di funzioni può essere fatta in due modi differenti: +% Sintassi standard di una funzione: +load('myFile.mat', 'y') % argomenti tra parentesi, separati da virgole +% Sintassi di tipo comando: +load myFile.mat y % Non ci sono parentesi e gli argometi sono separati da spazi +% Notare la mancanza di apici nella sintassi di tipo comando: gli input sono sempre passati come +% testo letterale - non è possibile passare valori di variabili. Inoltre non può ricevere output: +[V,D] = eig(A); % Questa non ha una forma equivalente con una sintassi di tipo comando +[~,D] = eig(A); % Se si vuole solo D e non V + + + +% Operatori logici +1 > 5 % ans = 0 +10 >= 10 % ans = 1 +3 ~= 4 % Not equal to -> ans = 1 +3 == 3 % equal to -> ans = 1 +3 > 1 && 4 > 1 % AND -> ans = 1 +3 > 1 || 4 > 1 % OR -> ans = 1 +~1 % NOT -> ans = 0 + +% Gli operatori logici possono essere applicati alle matrici: +A > 5 +% Per ogni elemento, se la condizione è vera, quell'elemento vale 1 nella matrice risultante +A( A > 5 ) +% Restituisce un vettore contenente gli elementi in A per cui la condizione è vera + +% Stringhe +a = 'MyString' +length(a) % ans = 8 +a(2) % ans = y +[a,a] % ans = MyStringMyString + + +% Celle +a = {'one', 'two', 'three'} +a(1) % ans = 'one' - ritorna una cella +char(a(1)) % ans = one - ritorna una stringa + +% Strutture +A.b = {'one','two'}; +A.c = [1 2]; +A.d.e = false; + +% Vettori +x = [4 32 53 7 1] +x(2) % ans = 32, gli indici in Matlab iniziano da 1, non da 0 +x(2:3) % ans = 32 53 +x(2:end) % ans = 32 53 7 1 + +x = [4; 32; 53; 7; 1] % Vettore colonna + +x = [1:10] % x = 1 2 3 4 5 6 7 8 9 10 + +% Matrici +A = [1 2 3; 4 5 6; 7 8 9] +% Le righe sono separate da punto e virgola, mentre gli elementi sono separati da spazi +% A = + +% 1 2 3 +% 4 5 6 +% 7 8 9 + +A(2,3) % ans = 6, A(row, column) +A(6) % ans = 8 +% (implicitamente concatena le colonne in un vettore, e quindi gli indici sono riferiti al vettore) + + +A(2,3) = 42 % Aggiorna riga 2 colonna 3 con 42 +% A = + +% 1 2 3 +% 4 5 42 +% 7 8 9 + +A(2:3,2:3) % Crea una nuova matrice a partire da quella precedente +%ans = + +% 5 42 +% 8 9 + +A(:,1) % Tutte le righe nella colonna 1 +%ans = + +% 1 +% 4 +% 7 + +A(1,:) % Tutte le colonne in riga 1 +%ans = + +% 1 2 3 + +[A ; A] % Concatenazione di matrici (verticalmente) +%ans = + +% 1 2 3 +% 4 5 42 +% 7 8 9 +% 1 2 3 +% 4 5 42 +% 7 8 9 + +% è equivalente a +vertcat(A,A); + + +[A , A] % Concatenazione di matrici (orrizontalmente) + +%ans = + +% 1 2 3 1 2 3 +% 4 5 42 4 5 42 +% 7 8 9 7 8 9 + +% è equivalente a +horzcat(A,A); + + +A(:, [3 1 2]) % Ripristina le colonne della matrice originale +%ans = + +% 3 1 2 +% 42 4 5 +% 9 7 8 + +size(A) % ans = 3 3 + +A(1, :) =[] % Rimuove la prima riga della matrice +A(:, 1) =[] % Rimuove la prima colonna della matrice + +transpose(A) % Traspone la matrice, equivale a: +A one +ctranspose(A) % Trasposizione hermitiana della matrice +% (ovvero il complesso coniugato di ogni elemento della matrice trasposta) + + + + +% Aritmetica Elemento per Elemento vs. Artimetica Matriciale +% Gli operatori aritmetici da soli agliscono sull'intera matrice. Quando sono preceduti +% da un punto, allora agiscono su ogni elemento. Per esempio: +A * B % Moltiplicazione matriciale +A .* B % Moltiplica ogni elemento di A per il corrispondente elemento di B + +% Ci sono diverse coppie di funzioni, in cui una agisce su ogni elemento, e +% l'altra (il cui nome termina con m) agisce sull'intera matrice. +exp(A) % Calcola l'esponenziale di ogni elemento +expm(A) % Calcola la matrice esponenziale +sqrt(A) % Calcola la radice quadrata di ogni elementotake the square root of each element +sqrtm(A) % Trova la matrice di cui A nè è la matrice quadrata + + +% Plot di grafici +x = 0:.10:2*pi; % Crea un vettore che inizia a 0 e termina 2*pi con incrementi di .1 +y = sin(x); +plot(x,y) +xlabel('x axis') +ylabel('y axis') +title('Plot of y = sin(x)') +axis([0 2*pi -1 1]) % x range da 0 a 2*pi, y range da -1 a 1 + +plot(x,y1,'-',x,y2,'--',x,y3,':') % Per stampare più funzioni in unico plot +legend('Line 1 label', 'Line 2 label') % Aggiunge un etichetta con il nome delle curve + +% Metodo alternativo per stampare funzioni multiple in un unico plot. +% mentre 'hold' è on, i comandi sono aggiunti al grafico esistene invece di sostituirlo +plot(x, y) +hold on +plot(x, z) +hold off + +loglog(x, y) % Un plot di tipo log-log +semilogx(x, y) % Un plot con asse x logaritmico +semilogy(x, y) % Un plot con asse y logaritmico + +fplot (@(x) x^2, [2,5]) % Stampa la funzione x^2 da x=2 a x=5 + +grid on % Mostra la griglia, disattivare con 'grid off' +axis square % Rende quadrata la regione individuata dagli assi +axis equal % Iposta l'aspetto del grafico in modo che le unità degli assi siano le stesse + +scatter(x, y); % Scatter-plot +hist(x); % Istogramma + +z = sin(x); +plot3(x,y,z); % Stampa una linea 3D + +pcolor(A) % Heat-map di una matrice: stampa una griglia di rettangoli, colorati in base al valore +contour(A) % Contour plot di una matrice +mesh(A) % Stampa come una superfice di mesh + +h = figure % Crea un nuovo oggetto figura, con handle f +figure(h) % Rende la figura corrispondente al handle h la figura corrente +close(h) % Chiude la figura con handle h +close all % Chiude tutte le figure +close % Chiude la figura corrente + +shg % Riutilizza una finestra grafica già esistente, o se necessario ne crea una nuova +clf clear % Pulisce la figura corrente, e resetta le proprietà della figura + +% Le proprietà possono essere impostate e modificate attraverso l'handle della figura. +% Si può salvare l'handle della figura quando viene creata. +% La funzione gcf restituisce un handle alla figura attuale. +h = plot(x, y); % Si può salvare un handle della figura quando viene creata +set(h, 'Color', 'r') +% 'y' yellow; 'm' magenta, 'c' cyan, 'r' red, 'g' green, 'b' blue, 'w' white, 'k' black +set(h, 'LineStyle', '--') + % '--' linea continua, '---' tratteggiata, ':' puntini, '-.' trattino-punto, 'none' nessuna linea +get(h, 'LineStyle') + + +% La funzione gca restituisce un handle degli assi della figura corrente +set(gca, 'XDir', 'reverse'); % Inverte la direzione dell'asse x + +% Per creare una figura che contiene diverse sottofigure, usare subplot +subplot(2,3,1); % Seleziona la prima posizione in una griglia 2 per 3 di sottofigure +plot(x1); title('First Plot') % Stampa qualcosa in questa posizione +subplot(2,3,2); % Seleziona la seconda posizione nella griglia +plot(x2); title('Second Plot') % Stampa qualcosa in questa posizione + + +% Per usare funzioni o script, devono essere nel tuo path o nella directory corrente +path % Mostra il path corrente +addpath /path/to/dir % Aggiunge al path +rmpath /path/to/dir % Rimuove dal path +cd /path/to/move/into % Cambia directory + + +% Le variabili possono essere salvate in file .mat +save('myFileName.mat') % Salva le variabili nel tuo Workspace +load('myFileName.mat') % Carica variabili salvate nel tuo Workspace + +% M-file Scripts +% I file di script sono file esterni che contengono una sequenza di istruzioni. +% Permettono di evitare di scrivere ripetutamente lo stesso codice nella Command Window +% Hanno estensione .m + +% M-file Functions +% Come gli script, hanno la stessa estensione .m +% Ma possono accettare argomenti di input e restituire un output. +% Inoltre, hanno un proprio workspace (differente scope delle variabili). +% Il nome della funzione dovrebbe coincidere con il nome del file (quindi salva questo esempio come double_input.m). +% 'help double_input.m' restituisce i commenti sotto alla linea iniziale della funzione +function output = double_input(x) + %double_input(x) restituisce il doppio del valore di x + output = 2*x; +end +double_input(6) % ans = 12 + + +% Si possono anche avere sottofunzioni e funzioni annidate. +% Le sottofunzioni sono nello stesso file della funzione primaria, e possono solo essere +% chiamate da funzioni nello stesso file. Le funzioni annidate sono definite dentro ad altre +% funzioni, e hanno accesso ad entrambi i workspace. + +% Se si vuole creare una funzione senza creare un nuovo file si può usare una +% funzione anonima. Utile quando si vuole definire rapidamente una funzione da passare ad +% un'altra funzione (es. stampa con fplot, valutare un integrale indefinito +% con quad, trovare le radici con fzenzro, o trovare il minimo con fminsearch). +% Esempio che restituisce il quadrato del proprio input, assegnato all'handle sqr: +sqr = @(x) x.^2; +sqr(10) % ans = 100 +doc function_handle % scopri di più + +% Input dell'utente +a = input('Enter the value: ') + +% Ferma l'esecuzione del file e cede il controllo alla tastiera: l'utente può esaminare +% o cambiare variabili. Digita 'return' per continuare l'esecuzione, o 'dbquit' per uscire +keyboard + +% Importarare dati (anche xlsread/importdata/imread per excel/CSV/image file) +fopen(filename) + +% Output +disp(a) % Stampa il valore della variabile a +disp('Hello World') % Stampa una stringa +fprintf % Stampa sulla Command Window con più controllo + +% Istruzioni condizionali (le parentesi sono opzionali, ma un buon stile) +if (a > 15) + disp('Maggiore di 15') +elseif (a == 23) + disp('a è 23') +else + disp('nessuna condizione verificata') +end + +% Cicli +% NB. Ciclare su elementi di vettori/matrici è lento! +% Dove possibile, usa funzioni che agiscono sull'intero vettore/matrice +for k = 1:5 + disp(k) +end + +k = 0; +while (k < 5) + k = k + 1; +end + +% Misurare la durata dell'esecuzione del codice: 'toc' stampa il tempo trascorso da quando 'tic' è stato chiamato +tic +A = rand(1000); +A*A*A*A*A*A*A; +toc + +% Connessione a un Database MySQL +dbname = 'database_name'; +username = 'root'; +password = 'root'; +driver = 'com.mysql.jdbc.Driver'; +dburl = ['jdbc:mysql://localhost:8889/' dbname]; +javaclasspath('mysql-connector-java-5.1.xx-bin.jar'); +% xx dipende dalla versione, download disponibile all'indirizzo http://dev.mysql.com/downloads/connector/j/ +conn = database(dbname, username, password, driver, dburl); +sql = ['SELECT * from table_name where id = 22'] % Esempio istruzione sql +a = fetch(conn, sql) % conterra i tuoi dati + + +% Funzioni matematiche comuni +sin(x) +cos(x) +tan(x) +asin(x) +acos(x) +atan(x) +exp(x) +sqrt(x) +log(x) +log10(x) +abs(x) +min(x) +max(x) +ceil(x) +floor(x) +round(x) +rem(x) +rand % Numeri pseudocasuali uniformemente distribuiti +randi % Numeri interi pseudocasuali uniformemente distrubuiti +randn % Numeri pseudocasuali distrbuiti normalmente + +% Costanti comuni +pi +NaN +inf + +% Risolvere equazioni matriciali +% Gli operatori \ e / sono equivalenti alle funzioni mldivide e mrdivide +x=A\b % Risolve Ax=b. Più veloce e più accurato numericamente rispetto ad usare inv(A)*b. +x=b/A % Risolve xA=b + +inv(A) % Calcola la matrice inversa +pinv(A) % Calcola la matrice pseudo-inversa + +% Funzioni comuni su matrici +zeros(m,n) % Matrice m x n di zeri +ones(m,n) % Matrice m x n di uni +diag(A) % Estrae gli elementi della diagonale della matrice A +diag(x) % Costruisce una matrice con elementi diagonali uguali agli elementi di x, e zero negli altri elementi +eye(m,n) % Matrice identità +linspace(x1, x2, n) % Ritorna n punti equamente distanziati, con minimo x1 e massimo x2 +inv(A) % Matrice inversa di A +det(A) % Determinante di A +eig(A) % Autovalori e autovettori di A +trace(A) % Traccia della matrice - equivalente a sum(diag(A)) +isempty(A) % Verifica se l'array è vuoto +all(A) % Verifica se tutti gli elementi sono nonzero o veri +any(A) % Verifica se almento un elemento è nonzero o vero +isequal(A, B) % Verifica l'uguaglianza di due array +numel(A) % Numero di elementi nella matrice +triu(x) % Ritorna la parte triangolare superiore di x +tril(x) % Ritorna la parte triangolare inferiore di x +cross(A,B) % Ritorna il prodotto vettoriale dei vettori A e B +dot(A,B) % Ritorna il prodotto scalare di due vettori (devono avere la stessa lunghezza) +transpose(A) % Ritorna la trasposta di A +fliplr(A) % Capovolge la matrice da sinistra a destra +flipud(A) % Capovolge la matrice da sopra a sotto + +% Fattorizzazione delle matrici +[L, U, P] = lu(A) % Decomposizione LU: PA = LU, L è il triangolo inferiore, U è il triangolo superiore, P è la matrice di permutazione +[P, D] = eig(A) % Auto-decomposizione: AP = PD, le colonne di P sono autovettori e gli elementi sulle diagonali di D sono autovalori +[U,S,V] = svd(X) % SVD: XV = US, U e V sono matrici unitarie, S ha gli elementi della diagonale non negativi in ordine decrescente + +% Funzioni comuni su vettori +max % elemento più grande +min % elemento più piccolo +length % lunghezza del vettore +sort % ordina in modo crescente +sum % somma degli elementi +prod % prodotto degli elementi +mode % valore moda +median % valore mediano +mean % valore medio +std % deviazione standard +perms(x) % lista tutte le permutazioni di elementi di x + + +% Classi +% Matlab supporta la programmazione orientata agli oggetti. +% La classe deve essere messa in un file con lo stesso nome della classe e estensione .m +% Per iniziare, creiamo una semplice classe per memorizzare waypoint GPS +% Inizio WaypointClass.m +classdef WaypointClass % Il nome della classe. + properties % Le proprietà della classe funzionano come Strutture + latitude + longitude + end + methods + % Questo metodo che ha lo stesso nome della classe è il costruttore + function obj = WaypointClass(lat, lon) + obj.latitude = lat; + obj.longitude = lon; + end + + % Altre funzioni che usano l'oggetto Waypoint + function r = multiplyLatBy(obj, n) + r = n*[obj.latitude]; + end + + % Se si vuole aggiungere due oggetti Waypoint insieme senza chiamare + % una funzione speciale si può sovradefinire una funzione aritmetica di Matlab come questa: + function r = plus(o1,o2) + r = WaypointClass([o1.latitude] +[o2.latitude], ... + [o1.longitude]+[o2.longitude]); + end + end +end +% End WaypointClass.m + +% Si può creare un oggetto della classe usando un costruttore +a = WaypointClass(45.0, 45.0) + +% Le proprietà della classe si comportano esattamente come una Struttura Matlab. +a.latitude = 70.0 +a.longitude = 25.0 + +% I metodi possono essere chiamati allo stesso modo delle funzioni +ans = multiplyLatBy(a,3) + +% Il metodo può anche essere chiamato usando una notazione con punto. In questo caso, l'oggetto +% non necessita di essere passato al metodo. +ans = a.multiplyLatBy(a,1/3) + +% Le funzioni Matlab possono essere sovradefinite per gestire oggetti. +% Nel metodo sopra, è stato sovradefinito come Matlab gestisce +% l'addizione di due oggetti Waypoint. +b = WaypointClass(15.0, 32.0) +c = a + b + +``` + +## Di più su Matlab + +* Sito ufficiale [http://http://www.mathworks.com/products/matlab/](http://www.mathworks.com/products/matlab/) +* Forum ufficiale di MATLAB: [http://www.mathworks.com/matlabcentral/answers/](http://www.mathworks.com/matlabcentral/answers/) diff --git a/it-it/python-it.html.markdown b/it-it/python-it.html.markdown index 3a4099e7..71f6dc1c 100644 --- a/it-it/python-it.html.markdown +++ b/it-it/python-it.html.markdown @@ -4,9 +4,11 @@ contributors: - ["Louie Dinh", "http://ldinh.ca"] - ["Amin Bandali", "http://aminbandali.com"] - ["Andre Polykanine", "https://github.com/Oire"] + - ["evuez", "http://github.com/evuez"] filename: learnpython.py translators: - ["Ale46", "http://github.com/Ale46/"] + - ["Tommaso Pifferi", "http://github.com/neslinesli93/"] lang: it-it --- Python è stato creato da Guido Van Rossum agli inizi degli anni 90. Oggi è uno dei più popolari @@ -15,8 +17,15 @@ pseudocodice eseguibile. Feedback sono altamente apprezzati! Potete contattarmi su [@louiedinh](http://twitter.com/louiedinh) oppure [at] [google's email service] -Nota: Questo articolo è valido solamente per Python 2.7, ma dovrebbe andar bene anche per -Python 2.x. Per Python 3.x, dai un'occhiata a [Python 3 tutorial](http://learnxinyminutes.com/docs/python3/). +Nota: questo articolo è riferito a Python 2.7 in modo specifico, ma dovrebbe andar +bene anche per Python 2.x. Python 2.7 sta raggiungendo il "fine vita", ovvero non sarà +più supportato nel 2020. Quindi è consigliato imparare Python utilizzando Python 3. +Per maggiori informazioni su Python 3.x, dai un'occhiata al [tutorial di Python 3](http://learnxinyminutes.com/docs/python3/). + +E' possibile anche scrivere codice compatibile sia con Python 2.7 che con Python 3.x, +utilizzando [il modulo `__future__`](https://docs.python.org/2/library/__future__.html) di Python. +Il modulo `__future__` permette di scrivere codice in Python 3, che può essere eseguito +utilizzando Python 2: cosa aspetti a vedere il tutorial di Python 3? ```python @@ -54,6 +63,12 @@ Python 2.x. Per Python 3.x, dai un'occhiata a [Python 3 tutorial](http://learnxi -5 // 3 # => -2 -5.0 // 3.0 # => -2.0 +# E' possibile importare il modulo "division" (vedi la sezione 6 di questa guida, Moduli) +# per effettuare la divisione normale usando solo '/'. +from __future__ import division +11/4 # => 2.75 ...divisione normale +11//4 # => 2 ...divisione troncata + # Operazione Modulo 7 % 3 # => 1 @@ -112,11 +127,19 @@ not False # => True # Una stringa può essere considerata come una lista di caratteri "Questa è una stringa"[0] # => 'Q' -# % può essere usato per formattare le stringhe, in questo modo: -"%s possono essere %s" % ("le stringhe", "interpolate") +# Per sapere la lunghezza di una stringa +len("Questa è una stringa") # => 20 + +# Formattazione delle stringhe con % +# Anche se l'operatore % per le stringe sarà deprecato con Python 3.1, e verrà rimosso +# successivamente, può comunque essere utile sapere come funziona +x = 'mela' +y = 'limone' +z = "La cesta contiene una %s e un %s" % (x,y) # Un nuovo modo per fomattare le stringhe è il metodo format. # Questo metodo è quello consigliato +"{} è un {}".format("Questo", "test") "{0} possono essere {1}".format("le stringhe", "formattate") # Puoi usare delle parole chiave se non vuoi contare "{nome} vuole mangiare {cibo}".format(nome="Bob", cibo="lasagna") @@ -132,9 +155,17 @@ None is None # => True # L'operatore 'is' testa l'identità di un oggetto. Questo non è # molto utile quando non hai a che fare con valori primitivi, ma lo è # quando hai a che fare con oggetti. - -# None, 0, e stringhe/liste vuote sono tutte considerate a False. -# Tutti gli altri valori sono True + +# Qualunque oggetto può essere usato nei test booleani +# I seguenti valori sono considerati falsi: +# - None +# - Lo zero, come qualunque tipo numerico (quindi 0, 0L, 0.0, 0.j) +# - Sequenze vuote (come '', (), []) +# - Contenitori vuoti (tipo {}, set()) +# - Istanze di classi definite dall'utente, che soddisfano certi criteri +# vedi: https://docs.python.org/2/reference/datamodel.html#object.__nonzero__ +# +# Tutti gli altri valori sono considerati veri: la funzione bool() usata su di loro, ritorna True. bool(0) # => False bool("") # => False @@ -144,7 +175,13 @@ bool("") # => False #################################################### # Python ha una funzione di stampa -print "Sono Python. Piacere di conoscerti!" +print "Sono Python. Piacere di conoscerti!" # => Sono Python. Piacere di conoscerti! + +# Un modo semplice per ricevere dati in input dalla riga di comando +variabile_stringa_input = raw_input("Inserisci del testo: ") # Ritorna i dati letti come stringa +variabile_input = input("Inserisci del testo: ") # Interpreta i dati letti come codice python +# Attenzione: bisogna stare attenti quando si usa input() +# Nota: In python 3, input() è deprecato, e raw_input() si chiama input() # Non c'è bisogno di dichiarare una variabile per assegnarle un valore una_variabile = 5 # Convenzionalmente si usa caratteri_minuscoli_con_underscores @@ -155,6 +192,7 @@ una_variabile # => 5 un_altra_variabile # Genera un errore di nome # if può essere usato come un'espressione +# E' l'equivalente dell'operatore ternario in C "yahoo!" if 3 > 2 else 2 # => "yahoo!" # Liste immagazzinano sequenze @@ -207,6 +245,17 @@ li + altra_li # => [1, 2, 3, 4, 5, 6] # Concatena liste con "extend()" li.extend(altra_li) # Ora li è [1, 2, 3, 4, 5, 6] +# Rimuove la prima occorrenza di un elemento +li.remove(2) # Ora li è [1, 3, 4, 5, 6] +li.remove(2) # Emette un ValueError, poichè 2 non è contenuto nella lista + +# Inserisce un elemento all'indice specificato +li.insert(1, 2) # li è di nuovo [1, 2, 3, 4, 5, 6] + +# Ritorna l'indice della prima occorrenza dell'elemento fornito +li.index(2) # => 1 +li.index(7) # Emette un ValueError, poichè 7 non è contenuto nella lista + # Controlla l'esistenza di un valore in una lista con "in" 1 in li # => True @@ -227,8 +276,9 @@ tup[:2] # => (1, 2) # Puoi scompattare le tuple (o liste) in variabili a, b, c = (1, 2, 3) # a è ora 1, b è ora 2 and c è ora 3 +d, e, f = 4, 5, 6 # puoi anche omettere le parentesi # Le tuple sono create di default se non usi le parentesi -d, e, f = 4, 5, 6 +g = 4, 5, 6 # => (4, 5, 6) # Guarda come è facile scambiare due valori e, d = d, e # d è ora 5 ed e è ora 4 @@ -250,6 +300,9 @@ filled_dict.keys() # => ["tre", "due", "uno"] filled_dict.values() # => [3, 2, 1] # Nota - Come sopra riguardo l'ordinamento delle chiavi. +# Ottieni tutte le coppie chiave-valore, sotto forma di lista di tuple, utilizzando "items()" +filled_dicts.items() # => [("uno", 1), ("due", 2), ("tre", 3)] + # Controlla l'esistenza delle chiavi in un dizionario con "in" "uno" in filled_dict # => True 1 in filled_dict # => False @@ -298,6 +351,15 @@ filled_set | other_set # => {1, 2, 3, 4, 5, 6} # Fai differenze su set con - {1, 2, 3, 4} - {2, 3, 5} # => {1, 4} +# Effettua la differenza simmetrica con ^ +{1, 2, 3, 4} ^ {2, 3, 5} # => {1, 4, 5} + +# Controlla se il set a sinistra contiene quello a destra +{1, 2} >= {1, 2, 3} # => False + +# Controlla se il set a sinistra è un sottoinsieme di quello a destra +{1, 2} <= {1, 2, 3} # => True + # Controlla l'esistenza in un set con in 2 in filled_set # => True 10 in filled_set # => False @@ -405,7 +467,7 @@ aggiungi(y=6, x=5) # Le parole chiave come argomenti possono arrivare in ogni # Puoi definire funzioni che accettano un numero variabile di argomenti posizionali -# che verranno interpretati come tuple se non usi il * +# che verranno interpretati come tuple usando il * def varargs(*args): return args @@ -413,7 +475,7 @@ varargs(1, 2, 3) # => (1, 2, 3) # Puoi definire funzioni che accettano un numero variabile di parole chiave -# come argomento, che saranno interpretati come un dizionario se non usi ** +# come argomento, che saranno interpretati come un dizionario usando ** def keyword_args(**kwargs): return kwargs @@ -449,19 +511,19 @@ def pass_all_the_args(*args, **kwargs): # Funzioni Scope x = 5 -def setX(num): +def set_x(num): # La variabile locale x non è uguale alla variabile globale x x = num # => 43 print x # => 43 -def setGlobalX(num): +def set_global_x(num): global x print x # => 5 x = num # la variabile globable x è ora 6 print x # => 6 -setX(43) -setGlobalX(6) +set_x(43) +set_global_x(6) # Python ha funzioni di prima classe def create_adder(x): @@ -474,15 +536,22 @@ add_10(3) # => 13 # Ci sono anche funzioni anonime (lambda x: x > 2)(3) # => True +(lambda x, y: x ** 2 + y ** 2)(2, 1) # => 5 # Esse sono incluse in funzioni di alto livello map(add_10, [1, 2, 3]) # => [11, 12, 13] +map(max, [1, 2, 3], [4, 2, 1]) # => [4, 2, 3] + filter(lambda x: x > 5, [3, 4, 5, 6, 7]) # => [6, 7] # Possiamo usare la comprensione delle liste per mappe e filtri [add_10(i) for i in [1, 2, 3]] # => [11, 12, 13] [x for x in [3, 4, 5, 6, 7] if x > 5] # => [6, 7] +# Puoi fare anche la comprensione di set e dizionari +{x for x in 'abcddeef' if x in 'abc'} # => {'d', 'e', 'f'} +{x: x**2 for x in range(5)} # => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} + #################################################### ## 5. Classi @@ -502,6 +571,9 @@ class Human(object): # Assegna l'argomento all'attributo name dell'istanza self.name = name + # Inizializza una proprietà + self.age = 0 + # Un metodo dell'istanza. Tutti i metodi prendo "self" come primo argomento def say(self, msg): return "{0}: {1}".format(self.name, msg) @@ -517,6 +589,21 @@ class Human(object): def grunt(): return "*grunt*" + # Una proprietà è come un metodo getter. + # Trasforma il metodo age() in un attributo in sola lettura, che ha lo stesso nome + @property + def age(self): + return self._age + + # Questo metodo permette di modificare la proprietà + @age.setter + def age(self, age): + self._age = age + + # Questo metodo permette di cancellare la proprietà + @age.deleter + def age(self): + del self._age # Instanziare una classe i = Human(name="Ian") @@ -536,6 +623,16 @@ j.get_species() # => "H. neanderthalensis" # Chiamare il metodo condiviso Human.grunt() # => "*grunt*" +# Aggiorna la proprietà +i.age = 42 + +# Ritorna il valore della proprietà +i.age # => 42 + +# Cancella la proprietà +del i.age +i.age # => Emette un AttributeError + #################################################### ## 6. Moduli @@ -570,34 +667,67 @@ math.sqrt == m.sqrt == sqrt # => True import math dir(math) +# Se nella cartella corrente hai uno script chiamato math.py, +# Python caricherà quello invece del modulo math. +# Questo succede perchè la cartella corrente ha priorità +# sulle librerie standard di Python + #################################################### ## 7. Avanzate #################################################### -# I generatori ti aiutano a fare codice pigro +# Generatori +# Un generatore appunto "genera" valori solo quando vengono richiesti, +# invece di memorizzarli tutti subito fin dall'inizio + +# Il metodo seguente (che NON è un generatore) raddoppia tutti i valori e li memorizza +# dentro `double_arr`. Se gli oggetti iterabili sono grandi, il vettore risultato +# potrebbe diventare enorme! def double_numbers(iterable): + double_arr = [] + for i in iterable: + double_arr.append(i + i) + +# Eseguendo il seguente codice, noi andiamo a raddoppiare prima tutti i valori, e poi +# li ritorniamo tutti e andiamo a controllare la condizione +for value in double_numbers(range(1000000)): # `test_senza_generatore` + print value + if value > 5: + break + +# Invece, potremmo usare un generatore per "generare" il valore raddoppiato non +# appena viene richiesto +def double_numbers_generator(iterable): for i in iterable: yield i + i -# Un generatore crea valori al volo. -# Invece di generare e ritornare tutti i valori in una volta ne crea uno in ciascuna -# iterazione. Ciò significa che i valori più grandi di 15 non saranno considerati in -# double_numbers. -# Nota xrange è un generatore che fa la stessa cosa di range. -# Creare una lista 1-900000000 occuperebbe molto tempo e spazio. -# xrange crea un oggetto generatore xrange invece di creare l'intera lista -# come fa range. -# Usiamo un underscore finale nel nome delle variabile quando vogliamo usare un nome -# che normalmente colliderebbe con una parola chiave di python -xrange_ = xrange(1, 900000000) - -# raddoppierà tutti i numeri fino a che result >=30 non sarà trovato -for i in double_numbers(xrange_): - print i - if i >= 30: +# Utilizzando lo stesso test di prima, stavolta però con un generatore, ci permette +# di iterare sui valori e raddoppiarli uno alla volta, non appena vengono richiesti dalla +# logica del programma. Per questo, non appena troviamo un valore > 5, usciamo dal ciclo senza +# bisogno di raddoppiare la maggior parte dei valori del range (MOLTO PIU VELOCE!) +for value in double_numbers_generator(xrange(1000000)): # `test_generatore` + print value + if value > 5: break +# Nota: hai notato l'uso di `range` in `test_senza_generatore` e `xrange` in `test_generatore`? +# Proprio come `double_numbers_generator` è la versione col generatore di `double_numbers` +# Abbiamo `xrange` come versione col generatore di `range` +# `range` ritorna un array di 1000000 elementi +# `xrange` invece genera 1000000 valori quando lo richiediamo/iteriamo su di essi + +# Allo stesso modo della comprensione delle liste, puoi creare la comprensione +# dei generatori. +values = (-x for x in [1,2,3,4,5]) +for x in values: + print(x) # stampa -1 -2 -3 -4 -5 + +# Puoi anche fare il cast diretto di una comprensione di generatori ad una lista. +values = (-x for x in [1,2,3,4,5]) +gen_to_list = list(values) +print(gen_to_list) # => [-1, -2, -3, -4, -5] + # Decoratori # in questo esempio beg include say @@ -605,7 +735,6 @@ for i in double_numbers(xrange_): # ritornato from functools import wraps - def beg(target_function): @wraps(target_function) def wrapper(*args, **kwargs): @@ -634,11 +763,13 @@ print say(say_please=True) # Puoi comprarmi una birra? Per favore! Sono povero * [Automate the Boring Stuff with Python](https://automatetheboringstuff.com) * [Learn Python The Hard Way](http://learnpythonthehardway.org/book/) * [Dive Into Python](http://www.diveintopython.net/) -* [The Official Docs](http://docs.python.org/2.6/) +* [The Official Docs](http://docs.python.org/2/) * [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/) * [Python Module of the Week](http://pymotw.com/2/) * [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182) * [First Steps With Python](https://realpython.com/learn/python-first-steps/) +* [LearnPython](http://www.learnpython.org/) +* [Fullstack Python](https://www.fullstackpython.com/) ### Libri cartacei diff --git a/it-it/ruby-ecosystem-it.html.markdown b/it-it/ruby-ecosystem-it.html.markdown new file mode 100644 index 00000000..d745399b --- /dev/null +++ b/it-it/ruby-ecosystem-it.html.markdown @@ -0,0 +1,145 @@ +--- +category: tool +tool: ruby ecosystem +contributors: + - ["Jon Smock", "http://github.com/jonsmock"] + - ["Rafal Chmiel", "http://github.com/rafalchmiel"] +translators: + - ["Cristian Achille", "http://github.com/blackdev1l/"] +lang: it-it +--- + +Generalmente chi usa ruby ha l'esigenza di avere differenti versioni di Ruby +installate, gestire le proprie gemme, e le loro dipendenze. + +## Manager Ruby + +Alcune piattaforme hanno Ruby pre-installato o disponibile come pacchetto. +Molti sviluppatori Ruby non usano questi pacchetti, o se lo fanno, li usano solo +per installare dei manager Ruby, i quali permettono di installare e gestire più +versioni di Ruby in base al progetto su cui si lavora. + +Di seguito i più famosi manager Ruby: + +* [RVM](https://rvm.io/) - Installa e permette di utilizzare diverse versioni di + Ruby. RVM Ha anche il concetto di gemsets i quali isolano completamente l'ambiente di sviluppo del progetto. +* [ruby-build](https://github.com/sstephenson/ruby-build) - Installa solamente + multiple versioni di ruby. Usa questo se vuoi maggior controllo sull'installazione di Ruby. +* [rbenv](https://github.com/sstephenson/rbenv) - + Permette solo la scelta di quale versione Ruby utilizzare. Usato insieme a ruby-build. + Utilizza questo per un maggior controllo su quale versione di Ruby utilizzare. +* [chruby](https://github.com/postmodern/chruby) - + Permette solo la scelta di quale Ruby utilizzare, simile a rbenv. + +## Ruby Versions + +Ruby fu creato da Yukihiro "Matz" Matsumoto, il [BDFL](https://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life), +(acronimo inglese che sta per "Benevolo dittatore a vita") , seppur +ultimamente non è più del tutto vera; l'implementazione di Ruby +è detta MRI (Matz' Reference Implementation), e dunque quando si legge di una +versione Ruby, essa si riferisce sempre al rilascio di una MRI + +Le tre maggiori versioni di Ruby in uso sono: + +* 2.0.0 - Rilasciata nel febbraio 2013. La maggior parte delle librerie e + framework supportano la 2.0.0 +* 1.9.3 - Rilasciata nel ottobre 2011. QUesta è la versione che molti + svluppatori usano, il supporto è + [concluso](https://www.ruby-lang.org/en/news/2015/02/23/support-for-ruby-1-9-3-has-ended/) +* 1.8.7 - Il supporto per Ruby 1.8.7 è + [concluso](http://www.ruby-lang.org/en/news/2013/06/30/we-retire-1-8-7/). + +I cambiamenti tra la 1.8.7 a la 1.9.x sono maggiori di quelli tra la 1.9.3 a la +2.0.0. Per esempio, nella 1.9 vengono introdotti encodings e bytecode VM. +Esistono ancora dei progetti basati sulla 1.8.7, ma stanno diventando una +minoranza man mano che la community si trasferisce alle versioni 1.92 e +1.9.3 + +## Ruby Implementations + +L'ecosistema Ruby gode di molte implementazioni differenti di Ruby, ognuna con +particolari punti di forza, da chiarire che ogni implementazione è scritta con +un linguaggio diverso, ma esse *sono tutte Ruby*. Ogni implementazione ha +feature extra ma tutte esse possono eseguire file ruby. Per esempio, JRuby è +scritto in Java, ma non devi conoscere java per usarlo. + +Implementazioni mature e compatibili: + +* [MRI](https://github.com/ruby/ruby) - Scritto in C, Questa è l'implementazione + standard di Ruby, per definizione è 100% compatibile (con se stessa). Tutte le + altre implemetazioni mantengono la compatibilità con MRI + (vedere [RubySpec](#rubyspec) sotto). +* [JRuby](http://jruby.org/) - Scritto in Java e Ruby, Questa implementazione è + molto veloce e robusta, la forza di JRuby consiste nell'interoperabilità + tra JVM/Java, permettendo l'utilizzo di struemnti Java già esistenti, progetti + e linguaggi +* [Rubinius](http://rubini.us/) - Scritto principalmente in Ruby con un + c++ bytecode VM, molto matura e veloce, permette alcune feature riguardo VM. + +Mediamente mature e compatibili: + +* [Maglev](http://maglev.github.io/) - Sviluppata sui Gemstone, è una Smalltalk +VM, Smalltalk è degli strumenti molto utili, e questo progetto cerca di portare +questi strumenti nello sviluppo Ruby. +* [RubyMotion](http://www.rubymotion.com/) - Porta ruby nello sviluppo iOS. + +Poco mature e compatibili: + +* [Topaz](http://topazruby.com/) - Scritto in RPython (usando PyPy come + toolchain) Topaz è un progetto ancora giovane e non compatibile, ha le + possibilità di diventare una implementazione Ruby molto performante +* [IronRuby](http://ironruby.net/) - Scritto in C# e prendendo di mira la + piattaforma .NET, lo sviluppo sembra fermo da quando Microsoft ha rimosso il + suo supporto. + +Le implementazioni Ruby possono avere una propria versione, ma hanno sempre come +target una specifica versione di MRI. Molte implementazioni hanno l'abilità di +selezionare una versione specifica di MRI. + +##RubySpec + +La maggior parte delle implementazioni Ruby dipendono pesantemente su +[RubySpec](http://rubyspec.org/). Ruby non ha una specifica ufficiale, quindi la +community ha scritto una specifica eseguibile in Ruby per testare la compatibilità +con MRI. + +## RubyGems + +[RubyGems](http://rubygems.org/) è un package manager gestito dalla communtiy +per Ruby. Rubygems viene installato con Ruby, quindi non c'è bisogno di +scaricarlo separatamente. + +I pacchetti Ruby sono chiamate "gemme", e possono essere hostate dalla community +su RubyGems.org . Ogni gemma contiene il codice sorgente e del metadata, tra cui +la versione, le dipendenze, autor* e licenz*. + +## Bundler + +[Bundler](http://bundler.io/) è un risolvitore di dipendenze, Esso usa il Gemfile +di un progetto per cercare le dipendenze, dopo di che ottiene le dipendenze delle +dipendenze ricorsivamente, Questo procedimento viene eseguito finchè tutte le +dipendenze sono state risolte e scaricate, o si fermerà se un conflitto verrà +trovato. + +Bundler genererà un error se troverà dipendenze in conflitto, Per esempio, +se la gemma A richiede la versione 3 o maggiore della gemma Z, ma la gemma B +richiede la versione 2, Bundler ti notificherà del conflitto. Questo diventa +di aiuto nel momento in cui si hanno molte gemme nel progetto, il che porta a +un grande grafo di dipendenza da risolvere. + +# Testing + +Il testing è un pezzo fondamentale della cultura Ruby, Ruby viene installato con +il proprio testing framework chiamato minitest (O TestUnit per ruby 1.8.x). +Esistono molte librerie con obiettivi differenti + +* [TestUnit](http://ruby-doc.org/stdlib-1.8.7/libdoc/test/unit/rdoc/Test/Unit.html) - Testing frameowrk rilasciato insieme a Ruby 1.8.x +* [minitest](http://ruby-doc.org/stdlib-2.0.0/libdoc/minitest/rdoc/MiniTest.html) - Testing frameowrk rilasciato insieme a Ruby 1.9/2.0 +* [RSpec](http://rspec.info/) - Un testing framework che si concentra nella chiarezza +* [Cucumber](http://cukes.info/) - Un BDD testing framework che estrapola testo formattato in Gherkin + +## Sii cordiale + +La community Ruby è orgogliosa di essere una communtiy aperta, accogliente e +variegata. Matz stesso è estremamente amichevole, e la generosità degli sviluppatori +Ruby è fantastica. diff --git a/it-it/rust-it.html.markdown b/it-it/rust-it.html.markdown new file mode 100644 index 00000000..6b379f93 --- /dev/null +++ b/it-it/rust-it.html.markdown @@ -0,0 +1,322 @@ +--- +language: rust +contributors: + - ["Carlo Milanesi", "http://github.com/carlomilanesi"] +lang: it-it +filename: rust-it.html.markdown +--- + +Rust è un linguaggio di programmazione sviluppato da Mozilla Research. +Rust combina il controllo a basso livello sulle prestazioni con alcune comodità +ad alto livello e stringenti garanzie di sicurezza. + +Rust raggiunge questi obiettivi senza richiedere la garbage collection né una grossa +libreria di supporto run-time, rendendo così possibile l'uso di librerie scritte in Rust +come rimpiazzo di librerie scritte in C. + +La prima versione pubblica di Rust, la 0.1, è stata rilasciata nel gennaio 2012, e per 3 anni +lo sviluppo è proceduto così rapidamente che l'utilizzo delle versioni +stabili veniva scoraggiato, e piuttosto si consigliava di utilizzare le versioni notturne +(nightly build). + +Il 15 maggio 2015, la versione 1.0 di Rust è stata rilasciata con la garanzia +che nelle successive versioni 1.x non ci sarebbero state modifiche che avrebbero reso +incompatibile il codice scritto per tale versione. +Nelle nightly build sono attualmente disponibili migliorie al tempo di compilazione +e ad altri aspetti del compilatore. Rust ha adottato un modello di rilascio a scaglioni +con rilasci regolari ogni sei settimane. Per esempio, la versione 1.1 beta è stata resa +disponibile contestualmente al rilascio della versione stabile 1.0. + +Sebbene Rust sia un linguaggio di livello relativamente basso, Rust ha alcuni concetti +di programmazione funzionale che solitamente si trovano solo nei linguaggi di livello più alto. +Ciò rende Rust non solo veloce, ma anche facile ed comodo da usare. + +```rust +// I commenti che stanno su una sola riga sono fatti così... +/* ...mentre così sono fatti +i commenti che richiedono +più righe */ + +/////////////////// +// 1. Fondamenti // +/////////////////// + +// Funzioni +// `i32` è il tipo per gli interi a 32-bit con segno +fn add2(x: i32, y: i32) -> i32 { + // return implicito (senza punto-e-virgola) + x + y +} + +// Funzione "main" +fn main() { + // Numeri // + + // Binding (ossia "variabili") immutabili + let x: i32 = 1; + + // Suffissi intero/virgola mobile + let y: i32 = 13i32; + let f: f64 = 1.3f64; + + // Inferenza di tipo + // La maggior parte delle volte, il compilatore Rust può inferire + // di quale tipo sia l'espressione usata per inizializzare un binding, + // e quindi non è necessario specificare esplicitamente il tipo. + // In tutto questo tutorial, i tipi vengono specificati esplicitamente in molti posti, + // ma solo a scopo dimostrativo. La maggior parte delle volte se ne potrebbe + // fare a meno, grazie all'inferenza di tipo. + let implicito_x = 1; + let implicito_f = 1.3; + + // Aritmetica + let somma = x + y + 13; + + // Variabile mutevole + let mut mutevole = 1; + mutevole = 4; + mutevole += 2; + + // Stringhe // + + // Letterali di stringa + let x: &str = "Ciao mondo!"; + + // Stampa + println!("{} {}", f, x); // 1.3 Ciao mondo! + + // Una `String` – una stringa allocata nello heap + let s: String = "Ciao mondo".to_string(); + + // Uno slice (fetta) di stringa – una vista immutabile + // all'interno di un'altra stringa. + // Uno slice è una coppia immutabile di puntatori al buffer contenuto + // nella stringa - non contiene dei caratteri, solo dei puntatori a + // un buffer statico o a un buffer contenuto in un altro oggetto (in questo caso, `s`) + let s_slice: &str = &s; + + println!("{} - {}", s, s_slice); // Ciao mondo - Ciao mondo + + // Vettori/array // + + // Un array di lunghezza fissa + let quattro_int: [i32; 4] = [1, 2, 3, 4]; + + // Un array dinamico (vettore) + let mut vettore: Vec<i32> = vec![1, 2, 3, 4]; + vettore.push(5); + + // Uno slice – una vista immutabile all'interno di un vettore o di un array + // E' molto simile a uno slice di stringa, ma per i vettori + let slice: &[i32] = &vettore; + + // Usa `{:?}` per stampare qualcosa a scopo di debugging + println!("{:?} {:?}", vettore, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] + + // Tuple // + + // Una tupla è un insieme ordinato di dimensione fissa di valori aventi tipi eventualmente diversi + let x: (i32, &str, f64) = (1, "ciao", 3.4); + + // Il `let` che destruttura + let (a, b, c) = x; + println!("{} {} {}", a, b, c); // 1 ciao 3.4 + + // Indicizzazione + println!("{}", x.1); // ciao + + ///////////// + // 2. Tipi // + ///////////// + + // Strutture + struct Point { + x: i32, + y: i32, + } + + let origine: Punto = Punto { x: 0, y: 0 }; + + // Ana struct con campi senza nome, chiamata ‘tuple struct’ + struct Punto2(i32, i32); + + let origine2 = Punto2(0, 0); + + // Enum basilare, analoga a quelle del linguaggio C + enum Direzione { + Sinistra, + Destra, + Su, + Giu, + } + + let su = Direzione::Su; + + // Enum con campi + enum OpzionaleI32 { + UnI32(i32), + Niente, + } + + let due: OpzionaleI32 = OpzionaleI32::UnI32(2); + let niente = OpzionaleI32::Niente; + + // Generici // + + struct Foo<T> { bar: T } + + // Questo è definito nella libreria standard come `Option` + enum Opzionale<T> { + QualcheValore(T), + NessunValore, + } + + // Metodi // + + impl<T> Foo<T> { + // I metodi di oggetto prendono un parametro `self` esplicito + fn get_bar(self) -> T { + self.bar + } + } + + let a_foo = Foo { bar: 1 }; + println!("{}", a_foo.get_bar()); // 1 + + // I trait (tratti), noti come "interfacce" o "mixin" in altri linguaggi + + trait Maneggiamento<T> { + fn maneggia(self) -> Option<T>; + } + + impl<T> Maneggiamento<T> for Foo<T> { + fn maneggia(self) -> Option<T> { + Some(self.bar) + } + } + + let altro_foo = Foo { bar: 1 }; + println!("{:?}", altro_foo.maneggia()); // Some(1) + + ///////////////////////// + // 3. Pattern matching // + ///////////////////////// + + let foo = OpzionaleI32::UnI32(1); + match foo { + OpzionaleI32::UnI32(n) => println!("E' un i32: {}", n), + OpzionaleI32::Niente => println!("Non vale niente!"), + } + + // Pattern matching avanzato + struct FooBar { x: i32, y: OpzionaleI32 } + let bar = FooBar { x: 15, y: OpzionaleI32::UnI32(32) }; + + match bar { + FooBar { x: 0, y: OpzionaleI32::UnI32(0) } => + println!("I numeri valgono zero!"), + FooBar { x: n, y: OpzionaleI32::UnI32(m) } if n == m => + println!("I numeri sono identici"), + FooBar { x: n, y: OpzionaleI32::UnI32(m) } => + println!("Numeri diversi: {} {}", n, m), + FooBar { x: _, y: OpzionaleI32::Niente } => + println!("Il secondo numbero non vale niente!"), + } + + /////////////////////////////////////////// + // 4. Flusso di controllo (Control flow) // + /////////////////////////////////////////// + + // Ciclo/iterazione con `for` + let array = [1, 2, 3]; + for i in array.iter() { + println!("{}", i); + } + + // Range + for i in 0u32..10 { + print!("{} ", i); + } + println!(""); + // Stampa `0 1 2 3 4 5 6 7 8 9 ` + + // `if` + if 1 == 1 { + println!("La matematica funziona!"); + } else { + println!("Oh no..."); + } + + // `if` come espressione + let value = if true { + "bene" + } else { + "male" + }; + + // Ciclo `while` + while 1 == 1 { + println!("L'universo sta funzionando regolarmente."); + } + + // Ciclo infinito + loop { + println!("Ciao!"); + } + + ///////////////////////////////////////////////// + // 5. La sicurezza della memoria e i puntatori // + ///////////////////////////////////////////////// + + // Puntatore posseduto (owned) – solamente una cosa sola per volta può ‘possedere’ questo puntatore + // Ciò significa che quando il `Box` abbandona il suo scope, verrà automaticamente deallocato in sicurezza. + let mut mio: Box<i32> = Box::new(3); + *mio = 5; // dereference + // Qui, `adesso_e_mio` acquisisce la proprietà di `mio`. In altre parole, `mio` viene spostato. + let mut adesso_e_mio = mio; + *adesso_e_mio += 2; + + println!("{}", adesso_e_mio); // 7 + // println!("{}", mio); // questo non compilerebbe perché `adesso_e_mio` adesso possiede il puntatore + + // Riferimento (reference) – un puntatore immutabile che si riferisce ad altri dati + // Quando un riferimento viene preso a un valore, diciamo che quel valore + // è stato ‘preso in prestito’ (borrowed). + // Mentre un valore è preso in prestito immutabilmente, non può venire mutato né spostato. + // Un prestito dura fino alla fine dello scope in cui è stato creato. + let mut var = 4; + var = 3; + let ref_var: &i32 = &var; + + println!("{}", var); // Diversamente da `mio`, `var` può ancora essere usato + println!("{}", *ref_var); + // var = 5; // questo non compilerebbe, perché `var` è stato preso in prestito + // *ref_var = 6; // neanche questo, perché `ref_var` è un riferimento immutabile + + // Riferimento immutabile + // Mentre un valore è preso in presto mutevolmente, non può essere acceduto in nessun modo. + let mut var2 = 4; + let ref_var2: &mut i32 = &mut var2; + *ref_var2 += 2; // '*' serve a puntare al binding var2, preso in presto mutevolmente + + println!("{}", *ref_var2); // 6 + // var2 non compilerebbe. ref_var2 è di tipo &mut i32, e quindi + // immagazzina un riferimento a un i32, e non il valore stesso. + // var2 = 2; // questo non compilerebbe, perché `var2` è stato preso in prestito +} +``` + +## Ulteriori letture + +C'è molto di più in Rust — questi sono solo i fondamenti di Rust, che servono a capire +le cose più importanti. + +Purtroppo c'è pochissima documentazione in italiano, tra cui: +(https://www.mozillaitalia.org/home/2015/05/30/primi-passi-con-rust/) + +Però ce n'è parecchia in inglese. Per saperne di più, leggi [The Rust Programming +Language](http://doc.rust-lang.org/book/index.html) e tieni d'occhio l'area di interesse di Reddit (subreddit) +[/r/rust](http://reddit.com/r/rust). + +Puoi anche provare a programmare in varie versioni di Rust usando il compilatore online al sito ufficiale +[Rust playpen](http://play.rust-lang.org). |