Ciclo While

Il ciclo while in TypeScript rappresenta una struttura di controllo che esegue ripetutamente un blocco di codice finché una condizione specifica rimane vera. La condizione viene valutata prima di ogni iterazione, offrendo un controllo preciso sull’esecuzione quando il numero di iterazioni non è predeterminato.
Sintassi e Comportamento
Il ciclo while valuta la condizione prima dell’esecuzione del blocco, garantendo che se la condizione è inizialmente falsa, il ciclo non venga mai eseguito.
let counter: number = 0;
while (counter < 5) {
console.log(`Iteration: ${counter}`);
counter++;
}
// Ciclo che potrebbe non eseguire mai
let condition: boolean = false;
while (condition) {
console.log("This will never execute");
}
Condizioni Complesse e Type Guards
TypeScript permette condizioni complesse che beneficiano di type narrowing e type guards, migliorando la sicurezza del codice all’interno del ciclo.
// Type guard con while
function processQueue<T>(queue: (T | null)[]): T[] {
const result: T[] = [];
let index = 0;
while (index < queue.length) {
const item = queue[index];
if (item !== null) {
result.push(item); // TypeScript sa che item è T
}
index++;
}
return result;
}
// Condizione con multiple verifiche
interface Task {
id: string;
completed: boolean;
priority: number;
}
function findHighPriorityTask(tasks: Task[]): Task | null {
let index = 0;
while (index < tasks.length) {
const task = tasks[index];
if (!task.completed && task.priority > 8) {
return task;
}
index++;
}
return null;
}
Pattern di Ricerca
Il while è ideale per algoritmi di ricerca dove la condizione di terminazione dipende dal contenuto dei dati.
// Ricerca lineare
function linearSearch<T>(array: T[], target: T): number {
let index = 0;
while (index < array.length) {
if (array[index] === target) {
return index;
}
index++;
}
return -1;
}
// Ricerca binaria
function binarySearch(sortedArray: number[], target: number): number {
let left = 0;
let right = sortedArray.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (sortedArray[mid] === target) {
return mid;
} else if (sortedArray[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
Gestione di Stream e Buffer
Il while è efficace per processare stream di dati dove la quantità non è nota a priori.
class BufferReader {
private data: number[];
private position: number = 0;
constructor(data: number[]) {
this.data = data;
}
readAll(): number[] {
const result: number[] = [];
while (this.position < this.data.length) {
const value = this.data[this.position];
result.push(value);
this.position++;
// Condizione di early exit
if (value === -1) {
break;
}
}
return result;
}
hasMore(): boolean {
return this.position < this.data.length;
}
}
Pattern Async
Il while può essere utilizzato in contesti asincroni per polling e operazioni ripetute.
// Polling asincrono
async function pollUntilReady(): Promise<boolean> {
let attempts = 0;
const maxAttempts = 10;
while (attempts < maxAttempts) {
const status = await checkStatus();
if (status.ready) {
return true;
}
await delay(1000); // Attesa di 1 secondo
attempts++;
}
return false;
}
function delay(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function checkStatus(): Promise<{ ready: boolean }> {
// Simulazione chiamata API
return { ready: Math.random() > 0.7 };
}
Parsing e Tokenizzazione
Il while è fondamentale per parser dove l’analisi procede carattere per carattere.
class SimpleParser {
private input: string;
private position: number = 0;
constructor(input: string) {
this.input = input;
}
parseNumbers(): number[] {
const numbers: number[] = [];
while (this.position < this.input.length) {
this.skipWhitespace();
if (this.position >= this.input.length) break;
const number = this.readNumber();
if (number !== null) {
numbers.push(number);
}
}
return numbers;
}
private readNumber(): number | null {
let numStr = "";
while (
this.position < this.input.length &&
/\d/.test(this.input[this.position])
) {
numStr += this.input[this.position];
this.position++;
}
return numStr ? parseInt(numStr) : null;
}
private skipWhitespace(): void {
while (
this.position < this.input.length &&
/\s/.test(this.input[this.position])
) {
this.position++;
}
}
}
Controllo di Flusso
Il while offre controlli di flusso sofisticati per algoritmi complessi.
// Algoritmo con multiple condizioni di uscita
function processUntilCondition<T>(
items: T[],
processor: (item: T) => boolean,
maxItems: number = Infinity
): number {
let index = 0;
let processedCount = 0;
while (index < items.length && processedCount < maxItems) {
const shouldContinue = processor(items[index]);
if (!shouldContinue) {
break; // Condizione di uscita early
}
processedCount++;
index++;
}
return processedCount;
}
Il ciclo while fornisce quindi un controllo flessibile per iterazioni basate su condizioni, ideale quando il numero di iterazioni dipende dallo stato dei dati o da condizioni esterne piuttosto che da contatori predefiniti.