J è l’evoluzione di APL ad opera di Ken Iverson e Roger Hui nel 1990 a partire da APL90.
Come APL, J tratta principalmente array di numeri (interi, floating e complessi) o di caratteri, l’equivalente delle stringhe, ma se ne differenzia per l’utilizzo di soli simboli ASCII per il nome delle funzioni, al posto dei caratteri “esoterici” di APL.
Oltre alle strutture con dimensioni, gli array, ci sono gli atomi, un numero o un carattere o un box; quest’ultimo è una struttura atomica che può contenere atomi o array.
J ha conservato di APL l’interpretazione delle istruzioni, da destra verso sinistra e senza precedenze fra gli operatori, la distinzione delle funzioni in monadiche (fnz op), e diadiche (op1 fnz op2) e l’utilizzo dello stesso simbolo per funzioni diverse, seppure generalmente correlate. J offre un numero di funzioni primitive molto più esteso rispetto ad APL, tramite l’utilzzo di . e : postfissi (inflection), in tal caso, per ogni simbolo, al posto di due funzioni, la monadica e la diadica, in teoria ne sono disponibili 6. Qui di seguito alcune funzioni.
Simbolo |
Monadico |
Diadico |
Monadico. |
Diadico. |
Monodico: |
Diadico: |
= |
|
uguaglianza |
|
|
assegnazione locale |
assegnazione globale |
< |
crea box |
minore di |
intero minore |
minore fra
|
decremento |
minore o uguale |
+ |
coniugato immaginario |
addizione |
componenti immaginario |
MCD
o OR |
doppio |
NOT
OR |
- |
sottrae da 0 |
sottrazione |
sottrae da 1 |
sottrazione
fra insiemi |
dimezza |
uguaglianza dell’oggetto |
* |
segno |
prodotto |
coordinate polari |
MCM
o AND |
quadrato |
NOT
AND |
% |
reciproco |
divisione |
matrice inversa |
divisione
di matrici |
radice quadrata |
radice |
t=:'Condor
Informatique - Turin'
right=: 4 :0 (-x.){.y. )
left=: {.
mid=: dyad define NB. start ll mid stringa cm=:0{(($y.)<.(0{x.)-1)
NB. cm minimo (-1) fra inizio e ll
stringa cm2=:i.(1{x.,(($t)-cm))<.(($t)-cm) NB.
cm2 = 0 1 2 ... ll-1 (cm+cm2){y.
) |
load 'c:\j502a\string.ijs'
t Condor
Informatique - Turin
13 mid t matique
- Turin
11 7 mid t ormatiq
8 left t Condor
I
8 right t - Turin |
Fortunatamente è possibile definire le funzioni con nomi significativi e utilizzare nomi già predefiniti; nella Figura 23 sono riportate la definizione delle funzioni left, right e mid, in particolare left è la semplice ridefinizione (definizione tacita) del verbo take {., right e mid sono invece definite esplicitamente dal blocco nomefnz=: n :0 ... ) (dyad define sono la ridefinizione rispettivamente di 4 e :0).
Figura
23
verbo (verb) |
funzione |
avverbio (adverb) |
funzione su funzione |
nome (noun) |
costante |
pronome (pronoun) |
variabile |
gerundio[1]
(gerund) |
case
di funzioni |
Figura
24
|
La descrizione ufficiale del linguaggio adotta una terminologia linguistica, si è già accennato ai postfissi; gli elementi sintatticamente più significativi sono riportati nella Figura 24 , esistono ancora le congiunzioni che indicano funzioni miste di funzione e variabile.
Ovviamente un istruzioni è detta frase (sentence), ed i suoi componenti sono detti parole (word).
Gli operatori i cui operandi
sono funzioni, generano delle nuove funzioni dette avverbi, in quanto modificano
il comportamento di un verbo, uno di questi è / (insert) che inserisce
il verbo fra gli operandi: +/ lista fornisce la somma dei costituenti la lista:
+/1+i.10 NB. i.10 genera la lista 0 1 ... 9
55
L’operatore & è utilizzato per rendere monadica una funzione diadica fissandone un operando, nella terminologia J & è detta congiunzione:
sconto=.0.90&*
sconto 100 NB. invece di 0.9 * 100
90
Possono essere create delle nuove funzioni giustapponendo semplicemente il nome delle funzioni ed assegnandolo ad una variabile (train), ma con una grave incongruenza di valutazione fra una funzione definita e gli stessi simboli eseguiti nativamente:
isq=:%%: NB. definizione di x diviso radice di x (radice di x)
isq 64
8
%%:64 NB. inverso di radice
0.125
Ciò è dovuto alla particolare interpretazione dei train: se f, g e h sono funzioni e var è l’operando, si ha:
fg var
equivale a var f (g var) NB. Hooks
fgh
var equivale a (f
var) g (h var) NB. Fork
Per train con oltre 3 funzioni lo schema è ricorsivamente analogo ai due casi visti.
L’operatore @ (compose) realizza le funzioni di funzioni: isq=:%@%: è l’inverso (%) della radice quadrata (%:). L’operatore @. ha come operando di sinistra un train di funzioni separate dall’operatore ` (tie) ed a destra un indice che sceglie la funzione da utilizzare, di fatto realizzando il comando case.
La flessibilità nella combinazione di funzioni e il fatto che le operazioni di confronto sono funzioni numeriche, permettono di evitare costrutti condizionali ed iterativi, ad esempio +/'o'=t conta quante ‘o’ ci sono nella stringa t, tuttavia questi esistono, ma sono utilizzabili solo nelle funzioni:
NB. T, T0, ... sono condizioni; B, B1, ...
sono blocchi di istruzioni
for. T do. B
end.
for_xyz. T do.
B end. NB. xyz è
la variabile contatore del ciclo
if. T do. B
[else. B1] end.
if. T do. B
elseif. T1 do. B1
elseif. T2 do. B2
end.
select. T
case. T0 do. B0
fcase. T1 do. B1
NB. Bizzarro: esegue anche il case successivo
...
end.
try. B catch.
B1 catchd. B2 catcht. B3 end. NB. Se fallisce B1 allora B2 o B3
while. T do. B end.
whilst. T do. B
end.
L’esempio di Figura 25
illustra
l’utilizzo di J per applicazioni grafiche.
NB.
J 5.02 LANCI=:'30' NB.
cc genera oggetti della form di posizione e dimensioni date da xyhw DADI=:
0 : 0 pc
dadi closeok;pn "Test generatore numeri a caso"; xywh
130 23 40 12;cc Va button leftmove rightmove;cn "Va"; xywh 130 40 40 12;cc Fine button leftmove rightmove;cn "Fine"; xywh
130 9 30 11;cc numero edit; xywh
7 25 118 100;cc lanci static; xywh
7 125 118 40;cc casi static; xywh 7 9 118 11;cc Label static; pas 4 2;pcenter; rem form end; ) dadi_run=: 3 : 0 wd DADI wd 'set numero *',LANCI wd
'set Label *Immettere numero lanci' wd 'setfocus numero' wd 'pshow;' ) dadi_Fine_button=: wd bind 'pclose' NB. Fine, chiusura della form dadi_Va_button=: 3 : 0 NB. Gestione del bottone Va
".
'N=:',numero NB. ". interpreta una stringa (execute) A=:
?N$6 NB. N
numeri a caso fra 0 e 5 wd
'set lanci *Lanci: ',":A ":
trasforma numero in stringa (format) ":A=:
=(A/:A) NB. ordina per valore B=:
+/|:A NB. somma wd
'set casi *Casi: ',":B wd
'mb "Test Chi Quadro"',":(+/(B-N%6)^2)%(N%6) ) dadi_run'' NB. partenza programma
|
Figura 25
|
L’operatore !:
(foreign conjunction) è utilizzato per interagire con il sistema
operativo, in particolare:
0!:n
controllo dell’esecuzione di scripts
1!:n
gestione dei files
6!:n
funzioni su data e ora
9!:n
variabili d’ambiente
11!:n
ambiente grafico statico ed interattivo
13!:n
debug
15!:n gestione
delle Dynamic Link Library
Anche qui una incongruenza, il blocco m!:n è un verbo monadico e non una funzione diadica.
J è predisposto alle applicazioni grafiche tramite una semplice gestione di proprietà, metodi ed eventi realizzata col verbo 11!:0 o il suo sinonimo wd, il cui operando è una stringa di comandi per l’interprete grafico (v.Figura 25 ).
Nell’esempio seguente un
esempio di crittografia a doppia chiave
.
NB.
J 5.02 P=:
3 : 0 NB. debugger
y. 1!:2 <2 ) Encrypt=: 3 : 0 'q p p1' =. 29 37 41 NB. assegnazione
multipla Testo=.y. if.
(#Testo) = 0 do.
Testo=.'Condor Informatique - Turin' end. if.
(#Testo) > q do.
Testo=. q {. Testo NB. prelevo i primi q
caratteri else. Testo=. Testo,(q-#Testo)$'*' end. P 'Testo originale ',Testo P 'crypt. con p
-> ',Testo=.Testo(q|(i.$Testo)*p)}Testo NB. chiusura mittente P 'crypt. con p1 -> ',Testo=.Testo(q|(i.$Testo)*p1)}Testo
NB. chiusura ricevente P 'decri. con p
-> ',Testo=.Testo(/:(q|(i.$Testo)*p))}Testo NB. apertura mitt. 'decri. con p1 -> ',Testo=.Testo(/:(q|(i.$Testo)*p1))}Testo
NB. apertura ricev. ) |
Encrypt '' Testo
originale Condor Informatique
- Turin** crypt.
con p -> CrToinn omurq*f-nar
u*o dtiIe crypt.
con p1 -> CanouI-ouot*rrn reni*mifT
dq decri.
con p -> CurTo*id-niaoe ur*qo
fntn Irm decri.
con p1 -> Condor Informatique - Turin** Encrypt 'Storia dei linguaggi' Testo
originale Storia dei
linguaggi********* crypt.
con p -> Sl*iu*eiti*aa*i*on*
g* *rg*dg crypt.
con p1 -> Sn* *d*igtg*l*e*agou*i*i* ira decri.
con p -> Sga* *ur*e*ntg
*l*ai*i*goid*i decri.
con p1 -> Storia dei linguaggi********* Encrypt 'Nel mezzo del cammin di nostra vita' Testo
originale Nel mezzo del
cammin di nostr crypt.
con p -> Neimasonel emt
l nzmrdd cozi crypt.
con p1 -> N sd z mmectenodeilarlo izn m decri.
con p -> Nmeidta oo eiz ermmd sclnznl decri.
con p1 -> Nel mezzo del cammin di nostr |
Ed il risultato è:
[1]
Si è tradotto gerund con gerundio, in realtà il
gerundio inglese è tradotto con l’infinito in italiano ad esempio: the
Art of programming.