Powershell 7: eksperymentujemy #3

https://xpil.eu/zhg

Po operatorze trójwartościowym i współbieżnej pętli ForEach przyszedł czas na Null-e.

Null to takie bydlę, które z jednej strony jest całkiem wygodnym konceptem, a z drugiej przysparza programistom (i twórcom języków programowania) mnóstwo kłopotów.

Null z definicji oznacza brak wartości. Nie: zero. Nie: pusty ciąg znaków. Nie. BRAK wartości.

Najwięcej problemów z NULL-em pojawia się przy operacjach boole-owskich: czy null AND true da w wyniku false? A może null?

Czy null OR true da w wyniku true? false? null?

Hmmm…

Niektóre języki próbują to rozwiązać poprzez wprowadzenie specjalnej wartości UNKNOWN: null AND true da w wyniku UNKNOWN. 3 + NULL - również. Ale tu pojawia się problem wyższego rzędu: skoro UNKNOWN samo w sobie jest wartością (specjalną, ale jednak), trzeba dorobić logikę, która ją uwzględnia... czy UNKNOWN and NULL dają na wyjściu UNKNOWN? A może NULL? A może 42? Hm.

Inne języki zakładają po prostu, że jakakolwiek operacja z NULL-em da w wyniku NULL.

Jeszcze inne konwertują niejawnie NULL na 0.

Różnych algorytmów postępowania z NULL-ami jest całkiem sporo (niektóre się wzajemnie wykluczają!), ale ja dziś nie o tym.

Ja dziś o tym, jak rozpoznać NULL-a w Powershell oraz co z tego wynika.

Zacznę od tego, że implementacja NULL w Powershell nie jest byt elegancka. W wersji 5.x na przykład można było zrobić coś takiego:

$zmienna = $null
$zmienna -eq $null

Wynik powyższego dawał na wyjściu True. Ale już:

[string] $innazmienna = $null
$innazmienna -eq $null

… generował na wyjściu False. Wystarczy więc dodać deklarację typu, żeby się rozjechało. Jeżeli chcieliśmy sprawdzić "null-owatość" zmiennej typu string, musieliśmy się łapać "brudnych" chwytów typu [String]::Empty lub im podobnych. Groch z kapustą.

Jeszcze gorzej było z NULL-ami zwracanymi przez zapytania SQL. Żeby sprawdzić, czy dostaliśmy NULL, trzeba było używać [DBNull]::Value, co prowadziło do jeszcze większego zamieszania.

Powershell 7.0 próbuje to wszystko uporządkować - czy robi to prawidłowo czy nie, chyba nie da się jednoznacznie określić, krzaków po drodze jest mnóstwo. Ale jest postęp.

Ci z Czytelników, którzy liznęli w życiu nieco SQL-a wiedzą o istnieniu operatora COALESCE, który zwraca pierwszą napotkaną wartość parametru niebędącego NULL-em. Innymi słowy jeżeli a i b są NULL, a c i d nie są, wówczas COALESCE(a, b, c, d) zwróci wartość zmiennej c, bo jest to pierwszy parametr niebędący NULL. I tak dalej.

W Powershell 7 pojawił się operator ??, który robi mniej więcej to samo, tylko trochę inaczej:

$x = "iks"
$y = "igrek"
$z = "zet"
$a ?? $b ?? $c ?? $x ?? $y ?? $z

Powyższy kod da na wyjściu "iks", ponieważ zarówno $a jak też $b i $c są NULL, a $x jest pierwszą zmienną niebędącą NULL.

Drugim ważnym operatorem, który pojawił się w PS7, jest operator "podstaw jeżeli NULL", który najpierw sprawdza, czy po lewej stronie jest NULL i jeżeli tak, podstawia do lewej strony to, co jest po prawej, a jeżeli nie, to nic nie robi. Przykład:

$a ??= "literka a"
$a ??= "literka b"
$a ??= "literka c"

Tutaj na dzień dobry $a jest NULL (bo nie ma takiej zmiennej, a nieistniejące zmienne w PS są zawsze NULL), więc najpierw do $a zostanie podstawiony tekst "literka a". Potem próbujemy tam podstawić "literka b", ale operator ??= "widzi", że po lewej stronie ma już jakąś wartość ("literka a") i zignoruje podstawienie. To samo dzieje się w kolejnej linii, tej z literką c.

Wniosek końcowy? Operatory ?? oraz ??= mogą zaoszczędzić nam zbędnego klepania if-ów, ale trzeba ich używać z głową. Jak wszystkiego zresztą.

https://xpil.eu/zhg

Leave a Comment

Komentarze mile widziane.

Jeżeli chcesz do komentarza wstawić kod, użyj składni:
[code]
tutaj wstaw swój kod
[/code]

Jeżeli zrobisz literówkę lub zmienisz zdanie, możesz edytować komentarz po jego zatwierdzeniu.