Crystal ha quelle che vengono chiamate espressioni di controllo: servono a controllare il modo in cui il programma verrà eseguito e assumono un valore truthy o falsey. Ci sono operatori che possono essere usati per creare valori truthy o falsey, questi sono noti come operatori di uguaglianza e confronto.
Ci sono due espressioni di controllo principali che servono a controllare quale codice verrà eseguito e quale no. In altre parole, quale ramo verrà eseguito.
Queste due sono: if e l'espressione unless.
Gli operatori di confronto servono a confrontare valori e restituiscono un valore true o false.
Questi operatori richiedono che vengano confrontati due valori dello stesso tipo.
Se i valori non sono dello stesso tipo, il compilatore genererà un errore.
Ecco un elenco degli operatori di confronto e un esempio di quando restituiscono un valore true:
| Metodo | Descrizione | Esempio |
|---|---|---|
| < | minore di | 4 < 5 |
| <= | minore o uguale | 4 <= 4 |
| > | maggiore di | 3 > 1 |
| >= | maggiore o uguale | 2 >= 2 |
Gli operatori di uguaglianza sono simili a quelli di confronto, ma servono a verificare se due valori sono uguali o meno.
L'operatore == verifica se due valori sono uguali, incluso il tipo del valore.
Se i valori sono uguali restituisce true, altrimenti restituisce false.
L'operatore == può confrontare qualsiasi tipo di valore con qualsiasi altro tipo di valore.
L'operatore != funziona allo stesso modo, ma restituisce true se i valori non sono uguali e false se lo sono.
L'istruzione if serve a verificare se una determinata condizione è truthy o falsey.
Se la condizione è truthy, il codice dentro l'istruzione if verrà eseguito.
Un'istruzione if termina con la parola chiave end.
if 1 == 1
puts "1 is equal to 1"
end
# => 1 is equal to 1
if 1 > 2
puts "1 is greater than 2"
end
# => no output
L'istruzione unless funziona in modo molto simile all'istruzione if, ma esegue il codice al suo interno se la condizione è falsey.
unless 1 == 1
puts "1 is not equal to 1"
end
# => no output
unless 1 > 2
puts "1 is not greater than 2"
end
# => 1 is not greater than 2
L'istruzione else può essere usata insieme alle istruzioni if e unless.
L'istruzione else viene eseguita se il ramo if o il ramo unless non viene eseguito.
Anche se un ramo `else` può essere usato insieme a `unless,` è sconsigliato farlo perché riduce la leggibilità.
Al contrario, si consiglia di usare `if !condition` con un ramo else.
if 1 == 1
puts "1 is equal to 1"
else
puts "1 is not equal to 1"
end
# => 1 is equal to 1
unless 1 < 2
puts "1 is not greater than 2"
else
puts "1 is greater than 2"
end
# => 1 is greater than 2
L'istruzione elsif può essere usata insieme all'istruzione if.
L'istruzione elsif viene eseguita se il ramo if non viene eseguito e la condizione dell'istruzione elsif è truthy.
Le istruzioni elsif possono essere concatenate tra loro e verrà eseguita la prima condizione truthy.
Alla fine dell'istruzione if può esserci anche un'istruzione else, che verrà eseguita se nessuna delle istruzioni precedenti è risultata vera.
if 1 != 1
puts "1 is not equal to 1"
elsif 1 > 2
puts "1 is greater than 2"
else
puts "1 is not equal to 1 and 1 is not greater than 2"
end
# => 1 is not equal to 1 and 1 is not greater than 2
Quando si assegnano tipi diversi, la variabile porterà entrambi i tipi. Questo perché il compilatore non sa quale ramo verrà eseguito. Questa assegnazione multipla, nota anche come union, verrà spiegata nei concetti successivi. Lo si può vedere nell'esempio seguente:
if 1 == 1
a = 1
else
a = "1"
end
typeof(a) # => Int32 | String
Crystal ha un operatore ternario, un'istruzione if-else su una sola riga: condition ? expression_if_truthy : expression_if_falsey
1 == 1 ? puts("1 is equal to 1") : puts("1 is not equal to 1")
# => 1 is equal to 1
In questo esercizio svilupperemo un semplice sistema di controllo per un reattore nucleare.
Perché un reattore produca energia, deve trovarsi in uno stato di criticità. Se il reattore si trova in uno stato al di sotto della criticità, può danneggiarsi. Se lo stato del reattore va oltre la criticità, può sovraccaricarsi e provocare una fusione del nocciolo. Vogliamo ridurre le probabilità di una fusione del nocciolo e gestire correttamente lo stato del reattore.
I tre compiti che seguono riguardano tutti la scrittura di codice per mantenere lo stato ideale del reattore.
La prima cosa che un sistema di controllo deve fare è verificare se il reattore è in equilibrio di criticità. Si dice che un reattore è critico se soddisfa le seguenti condizioni:
Implementa il metodo Reactor.criticality_balanced?, che prende come parametri temperature, misurata in kelvin, e neutrons_emitted, e restituisce true se le condizioni di criticità sono soddisfatte, false altrimenti.
Reactor.criticality_balanced?(750, 600)
# => true
Una volta che il reattore ha iniziato a produrre energia, bisogna determinarne l'efficienza. L'efficienza può essere raggruppata in 4 fasce:
green -> efficienza dell'80% o superiore,orange -> efficienza inferiore all'80% ma almeno del 60%,red -> efficienza sotto il 60%, ma comunque del 30% o superiore,black -> efficienza inferiore al 30%.Il valore percentuale si può calcolare come (generated_power/theoretical_max_power)*100, dove generated_power = voltage * current.
Nota che il valore percentuale di solito non è un numero intero, quindi assicurati di usare correttamente i confronti < e <=.
Implementa il metodo Reactor.reactor_efficiency, con tre parametri: voltage, current e theoretical_max_power.
Questa funzione deve restituire la fascia di efficienza del reattore: "green", "orange", "red" o "black".
Reactor.reactor_efficiency(200,50,15000)
# => "orange"
L'ultimo compito consiste nel creare un meccanismo fail-safe per evitare sovraccarichi e fusioni del nocciolo. Questo meccanismo determinerà se il reattore si trova sotto, esattamente su o sopra la soglia di criticità ideale. La criticità può quindi essere aumentata, diminuita o fermata inserendo (o rimuovendo) le barre di controllo nel reattore.
Implementa il metodo chiamato Reactor.fail_safe(), che prende 3 parametri: temperature, misurata in kelvin, neutrons_produced_per_second e threshold, e restituisce un codice di stato per il reattore.
Se temperature * neutrons_produced_per_second è inferiore al 90% di threshold, restituisci un codice di stato "LOW", che indica che le barre di controllo devono essere rimosse per produrre energia.
Se temperature * neutrons_produced_per_second rientra in un margine di più o meno il 10% rispetto a threshold, il reattore è in criticità e va restituito il codice di stato "NORMAL", che indica che il reattore è in condizioni ottimali e che le barre di controllo sono nella posizione ideale.
Se temperature * neutrons_produced_per_second non rientra negli intervalli sopra indicati, il reattore sta andando in fusione del nocciolo e va restituito un codice di stato "DANGER", per spegnere immediatamente il reattore.
temperature = 1000
neutrons_produced_per_second = 30
threshold = 5000
Reactor.fail_safe(temperature, neutrons_produced_per_second, threshold)
# => "DANGER"
Iscriviti a Exercism per imparare e padroneggiare Crystal con 26 concetti142 esercizi e il mentoring di persone reali, tutto gratis.