Manuale di riferimento MALDA™

Il linguaggio di programmazione AI-First - Versione 1.0.11

5. Variabili

5.1 Dichiarazione di variabili

In MALDA le variabili si dichiarano con la keyword var, seguita dal nome e da un valore iniziale opzionale:

var x = 10;
var name = "Alice";
var isActive = true;
var pi = 3.14159;

Le variabili vanno dichiarate prima dell'uso. Il tipo viene inferito dal valore iniziale. Per i binding che non devono mai essere riassegnati, usa const al posto di var (vedi 5.3 Dichiarazioni di costanti).

Dopo il nome puoi aggiungere un type hint informativo. A interpret-time gli hint sono documentazione per te e per l'IDE, non controlli runtime:

var name: Type? = value;

Esempio: var count: int = 0;, var msg: string = "hello";, oppure var p: Person = new Person();

Toolchain: il flag CLI --strict-types trasforma i disallineamenti degli hint in Error di analisi. malda compile --mode transpile e publish rifiutano l'emit quando l'analisi riporta Error; --lenient-types salta quel gate. I nomi di hint noti includono i primitivi Tier 0 (int, string, …), i nomi di class/schema/sum-type dichiarati (stessa unit o moduli importati) e le classi host built-in (per esempio RestServer). Il language server emette un Error di default quando un hint non coincide con un letterale, un'espressione new ClassName(), un altro identificatore che porta un hint noto, o un risultato di chiamata il cui callee dichiara un hint di ritorno (per esempio var n: int = "abc";, var p: Person = 1;, n = s; quando s: string, oppure var n: int = make(); quando make() -> string). Lo stesso controllo copre assegnamenti, argomenti di chiamata e valori di return rispetto agli hint di parametro/->. Gli operatori e i tipi di ritorno dei built-in non vengono inferiti.

5.2 Assegnamento di variabili

Dopo la dichiarazione, le variabili si possono riassegnare con l'operatore di assegnamento =:

x = 20;
name = "Bob";
x = x + 1;

5.3 Dichiarazioni di costanti

Un binding dichiarato con const invece di var non può essere riassegnato. L'inizializzatore è obbligatorio:

const MAX_RETRIES = 3;
const APP_NAME = "malda-demo";

print(MAX_RETRIES);   // 3

Tentare di assegnare a una costante è un errore a runtime che nomina il binding:

const limit = 10;
limit = 20;   // Runtime error: Cannot assign to const 'limit'.

Anche l'assegnamento composto (+=) e gli operatori di incremento sono assegnamenti, quindi su una costante falliscono per lo stesso motivo.

Le costanti sono shallow

const congela il binding, non il valore a cui punta. Una costante che contiene un array, un dizionario o un oggetto consente comunque di modificare i contenuti:

const config = dict { "retries": 3 };

config["retries"] = 5;   // Allowed: the dictionary is mutated, not the binding
print(config["retries"]); // 5

// config = dict { };    // Runtime error: Cannot assign to const 'config'.

Scope e shadowing

Le costanti seguono lo stesso scope di blocco di var, e uno scope interno può fare shadowing di una costante esterna con un proprio binding:

const mode = "prod";

function describe() {
    var mode = "local";   // Shadows the outer constant inside this function
    return mode;
}

print(describe());   // "local"
print(mode);         // "prod"
Quando usarla: usa const per valori di configurazione, limiti e tabelle di lookup che non devono cambiare durante una run. Tutto il resto resta var; MALDA non obbliga a usare le costanti e non le ottimizza in modo diverso.

5.4 Destrutturazione

La destrutturazione permette di estrarre valori da array e oggetti in variabili distinte, in una sola istruzione.

Destrutturazione di array

Estrai gli elementi di un array in variabili:

var arr = [10, 20];
var [x, y] = arr;
print(x);  // Prints: 10
print(y);  // Prints: 20

Pattern rest: usa ...rest per catturare gli elementi rimanenti:

var arr = [1, 2, 3, 4, 5];
var [first, second, ...rest] = arr;
// first = 1, second = 2, rest = [3, 4, 5]
print(length(rest));  // Prints: 3

Note:

Destrutturazione di oggetti

Estrai le proprietà di un oggetto in variabili:

var user = { name: "Alice", age: 30, role: "admin" };
var { name, age } = user;
print(name);  // Prints: "Alice"
print(age);   // Prints: 30

Rinomina: estrai le proprietà con nomi di variabile diversi:

var user = { name: "Bob", age: 25 };
var { name: userName, age: userAge } = user;
print(userName);   // Prints: "Bob"
print(userAge);    // Prints: 25

Destrutturazione nidificata: estrai da oggetti nidificati:

var data = {
    user: { name: "Charlie", age: 35 },
    role: "admin"
};
var { user: { name, age }, role } = data;
print(name);   // Prints: "Charlie"
print(age);    // Prints: 35
print(role);   // Prints: "admin"

Assegnamento con destrutturazione

Puoi usare la destrutturazione anche in assegnamento (su variabili già esistenti):

var x = 0;
var y = 0;
var arr = [10, 20];
[x, y] = arr;  // Assigns 10 to x, 20 to y
print(x + y);  // Prints: 30
var name = "";
var age = 0;
var user = { name: "David", age: 40 };
{ name, age } = user;  // Assigns properties to variables
print(name);  // Prints: "David"
print(age);   // Prints: 40

Destrutturazione del valore di ritorno di una funzione

Destruttura i valori restituiti dalle funzioni:

function getPoint() {
    return { x: 5, y: 10 };
}

var { x, y } = getPoint();
print(x + y);  // Prints: 15

Gestione degli errori

Se un pattern di destrutturazione non corrisponde (per esempio array troppo corto, proprietà dell'oggetto mancante), viene lanciato un errore a runtime:

try {
    var arr = [1, 2];
    var [x, y, z] = arr;  // Error: array has only 2 elements
} catch (e) {
    print("Destructuring failed: " + e);
}
Consigli sulla destrutturazione:

5.5 Scope delle variabili

In MALDA le variabili hanno block scope. Una variabile è accessibile nel blocco in cui è dichiarata e in tutti i blocchi nidificati.

Variabili globali

Le variabili dichiarate fuori dalle funzioni sono globali e accessibili in tutto il programma:

var globalVar = 10;

function test() {
    print(globalVar);  // Can access global variable
}

test();

Variabili locali

Le variabili dichiarate dentro una funzione sono locali a quella funzione:

function test() {
    var localVar = 20;
    print(localVar);  // Can access local variable
}

// print(localVar);  // Error: localVar is not accessible here

Shadowing delle variabili

Le variabili locali fanno shadowing delle variabili globali con lo stesso nome:

var x = 10;  // Global variable

function test() {
    var x = 20;  // Local variable shadows global x
    print(x);    // Prints 20 (local)
}

test();
print(x);  // Prints 10 (global)

Scope di blocco

Le variabili dichiarate nei blocchi (if, while, for) hanno scope limitato a quel blocco:

if (true) {
    var blockVar = 30;
    print(blockVar);  // Can access blockVar
}

// print(blockVar);  // Error: blockVar is not accessible here

Vedi anche