Czasami mam funkcję, która powinna zwracać wartość prawda lub fałsz. Ale czasami trzy możliwe wartości miałyby większy sens.
W niektórych tezach językowych przypadki byłyby obsługiwane za pomocą liczb całkowitych lub wyjątków.
Na przykład chcesz poradzić sobie z wiekiem użytkownika, który ma ponad 18 lat. I masz taką funkcję.
if(user.isAdult(country_code)){
//Go On
}else{
// Block access or do nothing
}
Ale w niektórych przypadkach, w zależności od budowy aplikacji, mogłem zobaczyć przypadek, w którym pole urodzin jest niepełne. Wtedy ta funkcja powinna zwrócić coś nieokreślonego.
switch(user.isAdult()){
case true:
// go on
break;
case undetermined:
//Inform user birthday is incomplete
case false:
//Block access
}
Jak powiedziałem, możemy sobie z tym poradzić z Exceptions i Int, ale uważam, że to całkiem seksowne, aby mieć prawdziwe, fałszywe, nieokreślone osadzone w języku zamiast używać stałych zdefiniowanych w domu.
Odpowiedzi:
Można to obsłużyć za pomocą wyliczeń, liczb całkowitych, symboli (np. Lisp, Ruby), typów zerowalnych (użyj null jako nieokreślonego stanu), typów opcji (np. ML) lub podobnej konstrukcji - w zależności od języka.
Więc chociaż twój przykład i uzasadnienie są solidne, nie widzę, aby znajdowało się na liście priorytetowej funkcji językowych do opracowania.
źródło
null
. W C / C ++ możesz zwrócić enum.Nie widziałem przypadku, w którym byłoby to konieczne. W podanym przykładzie, jeśli to pole jest konieczne, powinno zostać sprawdzone w innym miejscu.
isAdult()
jest nieuchronnie metodą dwustanową: albo jesteś albo nie jesteś. Nie trzeba nic robić, ale zwraca wartość false, jeśli napotka dane, których nie może obsłużyć. Na przykład:źródło
.isAdult()
zapytać samego użytkownika, jeśli naprawdę tego chcesz, a to działałoby lepiej.prawda, fałsz, nieznane
tak nie może
w C # możesz użyć zerowalnego boola (możesz teraz odskoczyć z przerażeniem)
w MS-SQL możesz użyć zerowego pola bitowego (to samo)
źródło
unknown
.W C ++ można to obsłużyć za pomocą typu non-
bool
return lub przez zgłoszenie wyjątku. Jeśli chcesz trójwartościowy typ zwrotu, użyjenum
. Nie jest tak seksowny, ale działa, a co ważniejsze, możesz to zrobić bez zepsucia języka dla reszty z nas.Posiadanie
bool
trzech wartości spowodowałoby problemy. Jak sobie z tym poradzićbool foo; ... if (foo)...
, zakładając, żefoo
może mieć jedną z trzech wartości? Zalety posiadaniabool
zmiennych takich, które są dokładnie jedną z nichfoo
i!foo
są prawdziwe przez cały czas. Pomaga rozumować o programach.Sprawdź, co ludzie robią w przetwarzaniu numerycznym, kiedy mogą uzyskać
NaN
wartości. To skomplikowane. Wolałbym nie przechodzić przez to do zwykłego przetwarzania wartości logicznych.Jeśli chcesz
.isAdult()
obsługiwać niewystarczające informacje, które mają to zrobić wewnętrznie, a następnie powrócić albotrue
albofalse
. W przeciwnym razie za każdym razem, gdy go użyjesz, musisz sprawdzić kod powrotu przed zrobieniem czegokolwiek innego i znaleźć sposób na jego obsługę. Oznaczałoby to, że musisz sprawdzić dokumenty, aby zobaczyć, czy funkcja rzeczywiście zrobiła to, co jej nazwa mówi, że to zrobiła, a to byłoby katastrofą dla czytelności.źródło
Pomysł jest dość przydatny. Jest całe pole poświęcone radzeniu sobie z niepewnością, zwane logiką rozmytą .
Na szczęście dla nas, programistów, można wdrożyć logikę rozmytą ze standardowymi funkcjami językowymi.
Na przykład w podanym przez ciebie przypadku niepewne informacje można łatwo ustalić, pytając użytkownika. Tak więc wyliczenie trójstanowe, jak opisujesz, będzie działać dobrze.
Istnieją różne sposoby, aby być niepewnym. Takie pytania obejmują:
Wiele z tych pytań można rozwiązać za pomocą prawdopodobieństw w zakresie od 0,0 (fałsz) do 1,0 (prawda) i stosując matematykę zmiennoprzecinkową.
Chemik obliczeniowy i informatyk David E. Shaw zastosował tego rodzaju rzeczy na Wall Street i jest teraz wart około 2,5 miliarda dolarów. Tak, to jest przydatne. :-)
źródło
Wiele lat temu bawiłem się niektórymi algorytmami wychodzącymi z przypisywania wiary wartościom. To była dobra zabawa. Ostatecznie zyskałem dzięki temu, że wartość logiczna jest często wymyślnym dopasowaniem. Naprawdę powinna to być trójlistna wartość prawda / fałsz / inna wartość. W eksperymentach wydawało mi się, że w owym czasie otrzymałem „najlepszy” kod. Od tamtej pory ułożyłem się i robiłem to, co robią wszyscy inni, jednocześnie myśląc wewnętrznie, o ile prostsze mogłoby być, gdybyśmy przestali robić rzeczy w ten sam stary sposób ... :-)
źródło
Instrukcje Case lub Switch działałyby w tym przypadku dobrze, wykorzystując liczby całkowite do arbitralnego radzenia sobie z przełącznikiem.
Również w Ruby, podczas gdy „zero” w niektórych okolicznościach zwraca wartość false, jeśli użyjesz operatora równości,
nil == false
zwracafalse
, więc możesz użyć rubynil
do obsługi logiki trójskładnikowej.źródło
Inną opcją w twoim przypadku może być odwrócenie kontroli poprzez zastosowanie zasady „mów nie pytaj” i zmień ją na (przepraszam za słowo „dorosłość”, „blokada mózgu”):
gdzie
OnlyAllowAdultsToLoginStrategy
implementuje interfejs:źródło
void userIsAdult()
zrobić? Może miałeś na myślibool userIsAdult()
?Mój syn pytał mnie, jak efektywnie wdrożyć podobne do tego testy. Testowane flagi były tylko prawdą / fałszem, ale klucze dopasowania miały trzy stany (musi to być prawda, musi być fałszem, inaczej mnie to nie obchodzi). Oczywiście można to zaimplementować za pomocą 2-bitowej struktury danych i odrobinę kręcącego się kodu, ale ten rodzaj kodu naprawdę musi zostać skomentowany, ponieważ cel nie jest łatwy do odróżnienia od samego spojrzenia na kod.
źródło
C ma tę funkcję zaimplementowaną w większości funkcji bibliotecznych. np. strcmp porównuje 2 łańcuchy i zwraca 0, jeśli są one takie same, 1 (tj. dowolna dodatnia liczba całkowita), jeśli pierwsza jest „większa” niż druga, i -1 (tj. dowolna liczba całkowita ujemna), jeśli druga jest większa niż pierwsza .
To samo podejście można zastosować gdzie indziej, + / 0 / - jako twój stan trójstronny. Pozwala także wykonywać logiczną wartość logiczną na wartościach, jeśli znasz 0, jeśli fałsz i dowolna inna wartość jest prawdą.
źródło
W przypadku C ++ Boost faktycznie implementuje Tribool opisany jako taki:
źródło
Pole wyboru VB6 ma tę funkcję. Wartości pól wyboru mogą być 0 = wyłączone, 1 = włączone, 2 = wyszarzone
źródło