Pagina principale faq Amiga Life a Pianeta Amiga La redazione
Galleria Indice generale
Enigma Amiga Life

AmigaLife 122 ?

AmiVerse
L'Ambiente Digitale parlerà SHEEP
In collaborazione con Quantum Leap

Lo scripting è un punto di forza dell'Amiga Classic, perché consente all'utente di combinare e automatizzare operazioni da tutti i vari programmi del sistema, attivando automaticamente l'interscambio dei dati, in modo da utilizzare le migliori caratteristiche di ciascun programma per ottenere risultati che nessuna applicazione, per quanto potente, potrebbe garantire.

Il nuovo linguaggio di scripting fondamentale dell'Amiga Digital Environment (Ambiente Digitale Amiga - DE) è chiamato in codice SHEEP (si tratta di un nome ad uso interno per questo linguaggio. Il nome definitivo sarà diverso). Esso riguarda scripting, querying, la shell e la comunicazione tra gli oggetti, e la programmazione in genere. Consente all'utente di interagire con gli oggetti nell'Ambiente Digitale Amiga, e permette agli oggetti all'interno del DE di controllarsi a vicenda. È la colla che tiene unito il flessibile Ambiente Digitale e rende tutto universalmente controllabile con script, configurabile e modificabile.

Avere un linguaggio come SHEEP come parte integrante di un sistema amplifica la sua utilità, poiché la maggior parte delle applicazioni saranno programmate tenendo presente la possibilità di scripting. Questa integrazione permette agli utenti di sfruttare le funzionalità disponibili nel sistema operativo o nelle applicazioni e di combinarle con codice personale per colmare le lacune. SHEEP gestirà sia l'interazione con interfaccia grafica che a linea di comando e renderà tutto il più facile possibile.

"Realizzare un lavoro sul proprio computer può essere facilissimo oppure estremamente difficile", dice Wouter van Oortmerssen. Secondo la sua opinione il fattore decisivo è avere a portata di mano un programma adatto al compito. "E anche quando si dispone di una applicazione con interfaccia grafica che permette di realizzare ciò che si vuol fare, l'interfaccia grafica è tradizionalmente poco flessibile, specialmente per i compiti ripetitivi. In quei casi ci sono pochissimi alternative all'uso di un linguaggio di scripting", afferma.

A dirigere il progetto SHEEP per Amiga è Wouter van Oortmerssen, un programmatore che gode di altissima considerazione in ambito Amiga Classic e che ha preso al volo la possibilità di contribuire al progetto del nuovo sistema. Wouter è conosciuto soprattutto per il suo linguaggio Amiga-E, conciso eppure potente, ma questo è soltanto uno della dozzina e più di linguaggi che ha progettato nel corso del suo Dottorato in Informatica. Ora sta lavorando a tempo pieno per Amiga Inc, sviluppando SHEEP.

Tim Sweeny, creatore dello "spara-e-fuggi" 3D Unreal e programmatore eccezionale, riassume le sue opinioni sulle capacità di Wouter in questo modo: "Wouter è un brillante designer di linguaggi di programmazione, e probabilmente il più prolifico sulla faccia della terra. Ha scritto il linguaggio di programmazione E ai primi tempi di Amiga, e da allora ha implementato una tonnellata di linguaggi imperativi, funzionali, visuali, reattivi, lineari ed altri ancora davvero notevoli. Ci scambiamo email ogni tanto, ed ogni volta che gli descrivo qualche nuova idea che mi è venuta in mente per un linguaggio lui mi risponde: 'Io l'ho implementata 5 anni fa, ed ecco i problemi a cui vai incontro'...".

Eredità

Il linguaggio di scripting dell'Amiga Classic era ARexx, componente standard a partire dalla versione 2 che risale a 10 anni fa. ARexx fu sviluppato partendo da Rexx, la versione originale per i mainframe IBM, con molte estensioni specifiche per Amiga. Altre versioni di Rexx sono state portate successivamente su molti altri sistemi, come OS/2, Unix e Qdos. Rexx è un linguaggio di alto livello general-purpose [NdT: cioè non indirizzato ad un compito specifico], versatile ma facile da apprendere.

La vera rilevanza di ARexx ha avuto origine dal modo in cui si è integrato nell'Amiga Classic. Quasi tutti i componenti del sistema, dai programmi al desktop, e anche gli emulatori di altri sistemi, avevano una porta ARexx, così ogni operazione che poteva essere effettuata manualmente con il mouse o la tastiera poteva essere automatizzata sotto il controllo di ARexx. In alcuni casi ciò rendeva possibili operazioni o configurazioni personalizzate che erano attuabili solo col supporto di ARexx.

Non c'era alcun bisogno che ogni programma avesse un suo proprio e complicato linguaggio di scripting incorporato, come quello che ha generato i noti problemi di compatibilità e sicurezza in sistemi "più maldestri" [NdT: è chiara l'allusione ai danni causati dalle macro di Microsoft Outlook e dai vari virus che le sfruttano] . Anche se l'idea era brillante, ben realizzata ed integrata, ARexx non era perfetto: risaliva agli anni Ottanta e a volte poteva essere lento, prolisso o grossolano. Ha fatto molto, ma avrebbe potuto fare di più.

Prima che ARexx diventasse parte del sistema, i vecchi Amiga venivano consegnati con un'implementazione del Microsoft BASIC. Come per molti home computer, gli utenti erano incoraggiati a scrivere il loro programmi in quel dialetto, esteso col supporto per le capacità multimediali di Amiga. Anche se superiore alle loro altre proposte, il Microsoft BASIC era lento, pesante e pieno di bug. Non era flessibile ed era incompatibile con i sistemi a 32 bit, così negli anni Novanta programmi di terze parti come Amos, Blitz, Maxon e Hisoft BASIC arrivarono per colmare il vuoto tra ARexx e i linguaggi di programmazione professionali come C, Oberon e l'assembly (per gli esperti).

Entra SHEEP

SHEEP riempie quel vuoto e soddisfa anche l'esigenza di un linguaggio di scripting standard e potente. Si può benissimo scrivere programmi e utility in SHEEP, ed in effetti si tratta un approccio molto efficiente per costruire prototipi o risolvere quel tipo di problemi che possono impegnare un programmatore sia per alcuni minuti che per alcuni giorni. Mentre i compilatori per Java, C, C++ e il nostro super-efficiente codice VP portabile sono maggiormente indicati per progetti più ampi o routine che probabilmente dovranno essere eseguite molte volte, il design interpretato e funzionale di SHEEP produce risultati più in fretta, anche se non sempre più velocemente. È ideale per lo sviluppo interattivo e il testing, un ambito in cui i linguaggi compilati non possono competere.

ARexx era strettamente integrato con l'Amiga OS e le applicazioni e "ti permetteva di fare un genere di programmazione che semplicemente non era possibile in alcun altro modo", dice van Oortmerssen. "Tra l'altro, ARexx era anche un ottimo progetto che realizzava il suo compito in maniera semplice ed amichevole, in modo che tutti potessero prenderlo e fare cose utili in poco tempo."

Si può passare dalla fase di editing di un programma SHEEP alla sua esecuzione, e tornare nell'editor preferito, immediatamente. Le prossime versioni permetteranno di compilare il codice SHEEP dopo che è stato testato, e di realizzare programmi stand-alone e sicuri che surclassano Java ed in molti casi raggiungono la velocità del C++ compilato.

SHEEP è ideale per gli script di installazione, per la comunicazione tra programmi - come ARexx, compreso l'accesso ad ARexx nell'ambiente Amiga Classic emulato - e per quel tipo di "programmini" che sui vecchi sistemi si realizzerebbero con script della shell, BASIC, E, Perl o Python. Comunque SHEEP è molto più sicuro di ARexx, C o BASIC. Non c'è alcuna possibilità di sovrascrivere per sbaglio una locazione di memoria o di rovinare qualche risorsa del sistema non relativa al programma. SHEEP fa a meno dei pericolosi POKE e dei puntatori che vengono utilizzati negli altri linguaggi, ciò nonostante può manipolare strutture di dati complesse in modo semplice ed efficiente.

SHEEP può essere usato per interrogazioni di database, nello stesso modo in cui SQL (Structured Query Language) viene utilizzato sui grossi sistemi. Il nuovo Amiga dispone di modi estremamente potenti per archiviare ed organizzare i dati; SHEEP fornisce una finestra pulita sul Digital Environment.

Varietà di SHEEP

SHEEP può essere interpretato, per facilità di manutenzione, oppure compilato in veloce VP code. SHEEP è la sintesi di parecchi concetti dell'Amiga Classic e di molte buone idee di diverse origini, in un linguaggio potente ma semplice che è facile da leggere e scrivere, senza le sintassi arbitrarie e complicate di molti altri linguaggi.

SHEEP funziona senza la "garbage collection" che spreca tempo e memoria in modo imprevedibile nella maggior parte degli altri linguaggi che consentono strutture di dati dinamiche. Lo fa usando nuovi principi di programmazione funzionale e gestendo automaticamente la memoria, senza costringere il programmatore ad usare questa tecnica in modo diverso dai linguaggi convenzionali.

SHEEP è polimorfico, così si possono scrivere programmi che ignorano il tipo esatto di dati che processeranno, e si può riutilizzare il codice senza fare versioni specifiche per ogni tipo (di dati) o dover effettuare dei test lenti, complicati e dall'errore facile. SHEEP permette di specificare i tipi dei dati nei casi in cui ciò potrebbe rendere i programmi più efficienti se essi fossero predefiniti, ma non obbliga a farlo in casi più generali. Nuovi tipi possono essere definiti con qualsiasi combinazioni di dati all'interno. I tipi possono essere un sopra-insieme di altri [vari] tipi. Quindi un albero con qualsiasi numero di rami o foglie può essere definito in una sola linea:


type tree = branch(left:tree, right:tree) | leaf(data)

Questa definisce due tipi, "branch" (ramo) e "leaf" (foglia), ed un super-tipo, "tree", che può essere usato per riferirsi ai valori di entrambi questi tipi. La barra verticale indica che un albero (o un sottoalbero, implicitamente) può essere sia un ramo fatto di ulteriori (sotto)alberi o una foglia, con una "data" proprietà.

Ogni valore è caratterizzato da un tipo, ma possiede anche il più generico tipo "any" (qualunque), a meno che non venga specificato diversamente. Se un tipo generico viene passato in un contesto più specifico, ad esempio nel caso in cui una stringa di caratteri viene passata ad una routine che si aspetta un intero, allora SHEEP forza la stringa su un formato numerico e genera un errore di tipo dinamico se non è possibile adattarla. Se entrambi i tipi sono strettamente definiti il compilatore rileva la non corrispondenza prima che il programma si avvii.

Come Van Oortmerssen sostiene, "il nuovo Amiga OS è molto più basato su oggetti che espongono automaticamente all'esterno le loro interfacce programmabili. Il potenziale di scripting in stile ARexx è quindi molto superiore". SHEEP fornisce una finestra sull'Amiga DE e sui suoi sistemi estremamente potenti per archiviare e organizzare i dati.

SHEEP riporta gli errori di contesto. Nel dubbio presenta un avvertimento. SHEEP incorpora la rilevazione degli errori e la gestione delle eccezioni, così se succede un inconveniente si può identificare il problema e risolverlo, o modificare il programma in modo che il caso speciale venga identificato e risolto automaticamente, senza appesantire il sorgente con test condizionali. Ciò aiuta e rassicura i principianti, senza limitare lo stile degli esperti.

Contare SHEEP

SHEEP usa il concetto di "vettori" per realizzare strutture normalmente archiviate in array statici o liste dinamiche. I vettori di SHEEP uniscono l'efficienza degli array al dinamismo delle liste. Vettori completi o parziali possono essere confrontati, estesi o sostituiti.

Le funzioni possono accettare qualunque numero di parametri, applicare valori predefiniti o modelli se necessario, e possono restituire qualunque numero di valori. Si possono contrassegnare i parametri quando si chiama una funzione, così è sufficiente specificare solo i parametri che interessano, e si possono indicare in qualsiasi ordine. In questo modo si potrebbero specificare i dettagli desiderati di un nuovo schermo, lasciando gli altri ai valori predefiniti, invocando una funzione "openscreen" come segue:


openscreen width: 640

height: 480

title: "Goats and SHEEP"

colourdepth: 32

foreground: 1

background: 0

Si possono definire varie istanze di una funzione, dipendenti dal tipo di valori o parametri che si desidera trattare. SHEEP sceglie automaticamente quella giusta per il caso specifico in cui la funzione viene invocata. Non sono richieste parentesi inutili, sia nell'invocazione che nella definizione di una funzione.

Il pattern matching è una caratteristica intrinseca di SHEEP, semplificando la programmazione. SHEEP può estrarre pattern da liste, dividendole in base alla posizione dei pattern stessi. Può fondere insieme pattern e liste senza problemi. Il pattern matching permette anche di estrarre particolari valori da tipi di dati definiti dall'utente.

Ci sono vari metodi per analizzare grosse quantità di dati in un solo passaggio. "Find" effettua una ricerca condizionale su un vettore, restituendo un indice del primo elemento trovato. "Filter" è simile, ma restituisce un vettore contenente tutti gli elementi trovati. "Fold" combina tutti gli elementi trovati accumulando un totale.

Spazio

SHEEP è un linguaggio senza limiti, con nessuna restrizione, che non sia la memoria disponibile, sulla lunghezza di stringhe, vettori, identificatori, programmi o singole linee.

SHEEP rileva il rientro della prima linea di una lista. Se una nuova linea ha lo stesso rientro della precedente allora è un nuovo comando. Se rientra di più viene considerata come una continuazione ed in questo modo è possibile presentare in modo pulito lunghi comandi. Se rientra meno il token successivo denota la fine della lista.

Funzionalità

Una caratteristica impressionante di SHEEP è la semplicità con cui si può insegnargli delle regole, per poi aspettarsi che queste vengano rispettate ed applicate nel contesto in uso. Si possono aggiungere funzioni, o definizioni, senza doverle avvolgere in oscure sintassi. Per fare un esempio molto semplice, si immagini di dover comunicare in modo "umano" il numero di file che un programma ha copiato. Piuttosto che ricorrere a sequenze di test, o a cose da analfabeti tipo "n files(s) copied", si può scrivere:


print (nfiles n) + " copied"

define nfiles 0 -> "no files"

define nfiles 1 -> "one file"

define nfiles n -> n + " files"

Le stringhe possono essere costruite con la stessa facilità offerta dal linguaggio Java. Così se si desiderano adottare particolari formattazioni - come il padding o come l'esempio precedente - si inseriscono funzioni extra. Riferimenti tipo "file(s)" sono finalmente sorpassati! Il minimo programma in SHEEP è un programma di una linea soltanto. Ecco il classico programma "Hello World" completamente realizzato in SHEEP:

print "Hello, World!\n"

L'unica complicazione è la sequenza "\n", che ordina al sistema di andare a capo dopo aver stampato "Hello, World!" È la stessa sintassi del C, del codice VP e di altri linguaggi di programmazione. I tabulatori possono analogamente essere indicati con \t, le virgolette si indicano con \", e \\ significa un solo backslash.

Ordinamento

Questo è un esempio un po' più complicato: un'implementazione dell'algoritmo QuickSort, che in molti linguaggi richiede due dozzine di linee di codice. SHEEP lo può fare in sole 4 linee (le linee che iniziano con due trattini sono commenti) senza strani simboli a parte le parentesi, i segni più e le frecce che hanno tutti significato piuttosto evidente.


-- polymorphic quicksort

define qsort [] -> []

define qsort [pivot] + rest ->

(qsort filter x in rest where before x pivot) + [pivot] +

(qsort filter x in rest where not before x pivot)

Si noti che non c'è alcun bisogno di dichiarare i tipi dei parametri x, rest o pivot. Non si sta trascurando niente, semplicemente il tipo dei dati non è rilevante per SHEEP. Lo stesso codice ordina con efficienza e senza problemi testo, numeri interi o frazioni, mentre con linguaggi tradizionali sarebbe stata necessaria una routine diversa per ciascun tipo.

In questo caso,


print qsort [5,2,6,3,8]

restituisce

[2,3,5,6,8]

Non serve notificare al programma la lunghezza del vettore o verificarla internamente da programma. Funziona con tutte le lunghezze dal momento che il programma è ricorsivo - funziona invocando se stesso ripetutamente, dividendo la lista in parti più piccole finché sono tutte in ordine, ma non serve occuparsi di programmare o controllare lo stack - SHEEP ci pensa da solo.

SHEEP presenta alcune delle stesse caratteristiche eccellenti di ARexx: "è semplice e facile da affrontare sin dall'inizio", afferma van Oortmerssen. "ARexx, comunque, aveva il problema di essere spesso sovrasfruttato dagli utenti: appena appreso il linguaggio si rendevano conto che script appena più lunghi diventavano insopportabilmente lenti e facilmente confusionari. SHEEP è progettato per durare molto più a lungo", dice.

La definizione dell'ordine secondo cui la lista deve essere ordinata è analogamente flessibile. Il termine "before" nel listato potrebbe avere qualsiasi nome e qualsiasi definizione ad esso associata può determinare l'ordine di due oggetti. Se si vuole ordinare un vettore di numeri interi, definiti come int(eger), si definisce "before" come segue:


define before x:int y:int = x

Che significa che quando "x" e "y" sono interi, "before" è vero se "x" è minore di (<) "y".

L'operazione "filter" scandisce una lista assegnando di volta in volta ciascun valore ad "x" e chiedendo "before z pivot?". Se la condizione è vera, cioè il valore di "x" precede il valore di "pivot", allora "x" viene spostato nel risultato. Quando tutto il vettore "rest" è stato scandito, la lista è più vicina all'ordine poiché i valori minori sono stati rimossi. "Quicksort" invoca se stesso per liste progressivamente più corte finché ogni valore è nella sua giusta posizione.

Unire e Dividere SHEEP

L'espressione "[pivot] + rest" dimostra come le liste di valori (vettori) possono essere divise e unite in SHEEP. L'espressione prende un vettore ed assegna il primo elemento a "pivot" e il rimanente a "rest". L'operazione "+" può sia unire che dividere modelli. Permette di creare vettori in questo modo:


a = [1,2,3]

a = a+[4,5,6]

Questo ha come risultato per "a" il vettore [1,2,3,4,5,6]. L'operazione "+" costruisce vettori, mentre il pattern matching li analizza e scompone. Si immagini una funzione "chop" (trancia) che viene applicata ad un vettore. La seguente istruzione estrapola un vettore:

define chop [1,2]+v

L'operazione di pattern matching divide il parametro scorporando un vettore di due elementi che deve contenere gli interi 1 e 2, e mette il resto del vettore in "v", in modo che "v" diventa [3,4,5,6] se a "chop" viene passato l'argomento "a".

Grafica

L'ultimo esempio dimostra come SHEEP può implementare un classico algoritmo grafico. Si assume che un dispositivo con larghezza ed altezza appropriate sia pronto ad accettare l'output del comando "plot".

L'esempio evidenzia come le funzionalità sofisticate di SHEEP non siano un ostacolo alla programmazione di tipo convenzionale. A parte la mancanza di ingombri sintattici [NdT: le punteggiature e i simboli tipici degli altri linguaggi] il listato di Mandelbrot potrebbe essere stato fatto in qualunque linguaggio strutturato a blocchi. Può essere eseguito e modificato facilmente come BASIC interpretato, ma ha la velocità e la struttura di un moderno dialetto compilato:


-- SHEEP Esempio di generatore di frattali di Mandelbrot

width = 640

height = 480

maxdepth = 128

define count x:real y:real do

xc = x

yc = y

i = 0

while i t = x

x = x*x-y*y+xc -- z = z*z + c

y = (t+t)*y+yc

i = i+1

end

return I

end

w = 3.5 -- cambiare questo parametro per zoomare o muovere

h = 2.8

top = -1.6

left = -2.0

for x = 0 until width do

for y = 0 until height do

plot w x y (count x/width*w+left y/height*h+top)

end

end

Conclusioni

Quando esistono già migliaia di linguaggi per computer serve una ragione speciale per proporne uno nuovo, per non parlare di sviluppare qualcosa di sofisticato come SHEEP, che è semplice in superficie, ma basato su tecnologie informatiche d'avanguardia all'interno.

SHEEP prende in prestito concetti da linguaggi classici come ARexx, Prolog, BASIC e Perl e nuovi come Python e Java, e beneficia dell'eperienza sul campo derivante da 15 anni di sviluppo e integrazione del prodotto Amiga Classic. SHEEP aggiunge nuove idee significative, elimina gli escamotage più pericolosi o troppo complicati, ed ha la coesione che deriva da un'unica mente brillante, piuttosto che da un manipolo di lobbisti.

SHEEP dimostra che se un lavoro merita veramente di essere realizzato, allora vale la pena di partire da zero. SHEEP non è soltanto qualcosa di nuovo ed entusiasmante: esso rende possibili e facilita cose stupende che altrimenti non si potrebbero mettere in pratica. È un componente chiave del nuovo Amiga, e niente altro può reggere il confronto.

© 1996 - 2000 Amiga Inc

Per gentile concessione di Amiga Inc, detentrice dei diritti sul testo originale, reperibile in http://www.amiga.com/press/zine/11-1-00/sheep/. Tradotto da Francesco Zonta e Fabio Ferriccioli per Quantum Leap.
Revisione e adattamento per Amiga Life di Daniele Franza.
Amiga è un marchio registrato di Amiga Inc.

Torna al sommario

Copyright (C) 1999-2002, la redazione di AmigaLife.
Il logo e le copertine della rivista sono tratti dal sito Pluricom e sono Copyright (C) 1992-2001 Pluricom S.r.l.