Wyjątki, Either i programowanie funkcyjne

Wyjątki, Either i programowanie funkcyjne
KA
  • Rejestracja:ponad 3 lata
  • Ostatnio:5 miesięcy
  • Postów:7
0

Ostatnio w książce 'Functional thinking' natknąłem się na stwierdzenie, że rzucanie wyjątków łamie dwie zasady programowani funkcyjnego:

  • powoduje side-effect, więc funkcja nie jest już 'pure'
  • powoduje, że tracimy 'referential transparency'

jednakże niektóre wątki na stackoverflow zdają się być sprzeczne z tym co Neal Ford opisał w swojej książce (np. ten https://stackoverflow.com/questions/10703232/why-is-the-raising-of-an-exception-a-side-effect).

Jak to jest z tym rzucaniem exceptionów - jest to dopuszczalne w programowaniu funkcyjnym czy nie? Jak to wygląda w praktyce - czy wprowadzenie Either albo czegos Either-podobnego zamiast try/catch daje wam jakiś zysk? Jest mniej błędów? można mieć spokojniejszy sen podczas oncalla?. Czy robicie to tylko po to, żeby poczuć wyższość nad ludźmi, którzy nie chcą wyjść poza świat OOP?

Całe życie byłem przyspawany do Javy i try/catch to było to dzięki czemu miałem pracę, ale zauważyłem, że sporo języków np. golang czy typescript pozwala na coś bardzo zbliżonego do Either, ale lepiej zintegrowane z językiem.

stivens
Golang i either? Jak to ma blizej do C i zwracania errno. To nie jest either
stivens
result, err := foo(); if (err != Nil) panic() - patolka to jest
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 5 godzin
1

λλλ
hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:13 dni
5

wprowadzenie Either albo czegos Either-podobnego zamiast try/catch daje wam jakiś zysk?

Podstawową zaletą Either (i podobnych, jak Result w Ruscie) jest to, że wymusza obsługę błędu, co prowadzi do tego, że zazwyczaj można spać spokojniej (bo wiemy, że wywołujący obsłużył jakoś błąd).

Czy robicie to tylko po to, żeby poczuć wyższość nad ludźmi, którzy nie chcą wyjść poza świat OOP?

Nie wiem co ma piernik do wiatraka, bo błędy jako zwracane wartości są zupełnie niezależne od OOP.


SL
  • Rejestracja:około 7 lat
  • Ostatnio:około 4 godziny
  • Postów:866
4

Źle współgra, ale to co piszą w tej książce to imo trochę bełkot. Rzucanie wyjątków nie prowadzi problemów, bo:

  • powoduje side-effect, więc funkcja nie jest już 'pure': nie widzę problemu, żeby funkcje rzucające wyjątki były pure. Jeśli założymy, że rzucony wyjątek jest pewnego rodzajem wynikiem funkcji to nie wiem, czemu div(0) -> Either<int> jest pure a div(0) -> int throws YouCannotDivideByZeroError już nie
  • powoduje, że tracimy 'referential transparency' jak wyżej możemy zastąpić każde wywołanie div(0) rzuceniem wyjątku YouCannotDivideByZeroError co spełnia referential transparency

Problemem jest łapanie wyjątków, bo samo łapanie we wszystkich znanych mi językach opiera się o statements, co nie jest funkcyjne. Nie widzę problemu, żeby napisać jakiegoś haskella od zera z javowymi wyjątkami jako taki "sugar". Nie ma to za bardzo sensu, ale nie widzę problemu dlaczego nie miałoby to działać

Jak to wygląda w praktyce - czy wprowadzenie Either albo czegos Either-podobnego zamiast try/catch daje wam jakiś zysk?

To po prostu inny typ obsługi błędów. Osobiście jestem za zwracaniem błędów, ale wyjątki też mają swoje zalety. Np. języki imperatywne operujące na zwracanych błędach (Rust, Go) i tak mają mechanizm do rzucania wyjątków (panic), które nie powinny być normalnie łapane. W językach z wyjątkami możesz użyć tego samego mechanizmu do obsługi obu rodzajów błędów, co jest eleganckie

że sporo języków np. golang ... ale lepiej zintegrowane z językiem.

heh (mówie to jako programista go).

czy wprowadzenie Either albo czegos Either-podobnego zamiast try/catch daje wam jakiś zysk?

Obsługa błędów ręcznie daje mnóstwo korzyści:

  • wymusza prostszy design, bo nie ma wyjątków rzucanych przez wiele funkcji
    • a jak są to wygląda to brzydko i człowiek musi się zastanowić, czy ma to sens
  • pozwala na traktowanie wyjątków jak wartości. Przykładowo mogę je sobie włożyć do jakiejś tablicy
  • wymusza obsługę błędów w każdym miejscu, co pozwala na lepiej przemyślany kod
  • działa lepiej z programowanie funkcyjnym
edytowany 2x, ostatnio: slsy
Zobacz pozostałe 3 komentarze
hauleth
@slsy: nie mówię o Javie, mówię o idei, zwłaszcza w językach funkcyjnych. @karellen to zależy od wymagań biznesowych. Np. jak główna DB leży, to raczej jest to sytuacja wyjątkowa, ale błąd wysłania emaila z potwierdzeniem rejestracji raczej nim nie jest i po prostu spróbuje się ponownie później.
jarekr000000
@slsy w Javie wprowadzono CheckedException i to jest właśnie ten "oczekiwany błąd", którego obsłużenie jakies jest wymuszone. (IMO wyszło, że checked exception to jednak kiepski pomysł).
somekind
główną motywacją był brak konieczności drabinek if/else - a jak wszyscy wiemy, drabinka try-catch jest lepsza od drabinki if-else. ;)
SL
@jarekr000000: to prawda. Z drugiej strony CheckedException to taka świnka morska, która ani nie jest świnką ani morską. Checked exceptiony miały wprowadzić trochę porządku a jedyne co robią, to sprawiają, że dobre cechy wyjątków (możliwość bez skrępowanego rzucania przez wiele warstw) działa słabo, w zamian dostajemy coś ala return value, tylko bez ich zalet.
SL
@somekind: o ile dobrze pamiętam to chodziło o brak konieczności przepychania wyjątków przez warstwy. Co samo w sobie ma mało sensu, bo wyjątki tak czy owak często są przekształcane np. specyficzny błąd zwracany z postgresa (constraint error) jest mapowany na domenowy problem np. taki użytkownik już istnieje
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:2 dni
  • Lokalizacja:Wrocław
3
karellen napisał(a):

Czy robicie to tylko po to, żeby poczuć wyższość nad ludźmi, którzy nie chcą wyjść poza świat OOP?

Tak, na pewno o to chodzi. 😄

Zwracać obiekt opisujący błąd można też w języku obiektowym, i nie ma to za bardzo związku z wychodzeniem poza świat OOP. Ot, po prostu dzięki temu wiadomo, co się dzieje, i nie zachowujemy się jak psychopaci zbierający niepotrzebnie stacktrace.

loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
karellen napisał(a):

Ostatnio w książce 'Functional thinking' natknąłem się na stwierdzenie, że rzucanie wyjątków łamie dwie zasady programowani funkcyjnego:

  • powoduje side-effect, więc funkcja nie jest już 'pure'
  • powoduje, że tracimy 'referential transparency'

W branży pokrewnej programowaniu funkcyjnemu jest tak że jak zaczynasz dostawać nieskończoności albo dzielić przez zero to znaczy że zrobiłeś coś źle. A jak zrobiłeś coś źle to cały tok jest o kant d. potłuc.

Dlatego książka ma jak najbardziej rację. Lepiej położyć program niż pozwolić czemuś takiemu obrażać logikę.


Przetrzyma wszystko
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 7 godzin
  • Postów:3277
2

Mocno zależy jak się tych wyjątków używa. Programowanie funkcyjne opiera się na matematycznej definicji funkcji, czyli jakieś wyrażenie, które każdemu elementowi dziedziny jest w stanie przyporządkować dokładnie jeden element przeciwdziedziny. Czyli coś takiego:

Kopiuj
fun reciprocal(x: Double): Double -> 1/x

Ponieważ dla 0 funkcja y=1/x jest nieokreślona, podczas wywołania reciprocal(0) dostaniemy wyjątek, DivideByZero który jeżeli nie zostanie wychwycony, wywali całą aplikację (a to trochę nie dobrze).
Natomiast jeżeli zaimplementujemu to w ten sposób:

Kopiuj
fun reciprocal(x: Double): Either<Double, Undefined> -> when(x)(0 -> Eiher(Undefined) default: Either(1/x))

To po pierwsze coś, co nie było funkcją zaczyna być funkcją, po drugie programista korzystający z niej wie, że musi obsłużyć ścieżkę, albo świadomie jej nie obsłuży.

Teoretycznie da się coś takiego robić poprzez checked exception, ale praktyka wskazuje, że 99% tej obsługi wygląda tak:

Kopiuj
try{...}
catch(Exception e){
  throw new RuntimeException(e);
}
loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
piotrpo napisał(a):

To po pierwsze coś, co nie było funkcją zaczyna być funkcją, po drugie programista korzystający z niej wie, że musi obsłużyć ścieżkę, albo świadomie jej nie obsłuży.

Ale to jest przypadek trywialny. Co jeśli liczba wyjątków idzie w tysiące? Kto to ogarnie - no i po co?


Przetrzyma wszystko
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 7 godzin
  • Postów:3277
0

No jest trywialny, bo po co tworzyć jakieś skomplikowane przykłady, skoro sens jest widoczny na podstawie prostego? Najzwyczajniej wygodnie jest używać funkcji, któa zawsze zwróci oczekiwaną wartość, niż takiej, która w jakichś tam przypadkach wrzuci odbezpieczony granat.

loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
1
piotrpo napisał(a):

No jest trywialny, bo po co tworzyć jakieś skomplikowane przykłady, skoro sens jest widoczny na podstawie prostego? Najzwyczajniej wygodnie jest używać funkcji, któa zawsze zwróci oczekiwaną wartość, niż takiej, która w jakichś tam przypadkach wrzuci odbezpieczony granat.

Undefined to nie oczekiwana wartość. To jest inna enkapsulacja wyjątku. I za cholerę nie wiadomo co z tym zrobić - to jest przyznanie po stronie funkcji, ups, dostałem zestaw inputu który za cholerę nie przeze mnie kalkulowalny, baw się z tym dalej co prowadzi nas do punktu poniżej:

ale praktyka wskazuje, że 99% tej obsługi wygląda tak:

Który jest workaroundem na to że położenie aplikacji nie powinno mieć miejsca co jest bzdurą - logika natrafiła na coś co nie zostało w niej zamodelowane albo zostało zamodelowane z błędem - pozwolenie na dalsze działania czegoś takiego to jest etap machania rękami i liczenia na cud.


Przetrzyma wszystko
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 7 godzin
  • Postów:3277
0

To jaka jest oczekiwana wartość dla wyrażenia 1/0? Bo w matematyce jest to właśnie wartość nieokreślona. Jeżeli piszesz kalkulator, gdzie użytkownik wpisuje 0, a następnie wciska guzik 1/x, to on powinien grzecznie użytkownika poinformować, że taka operacja matematyczna nie zwraca wyniku, a nie umierać.

loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
piotrpo napisał(a):

To jaka jest oczekiwana wartość dla wyrażenia 1/0? Bo w matematyce jest to właśnie wartość nieokreślona. Jeżeli piszesz kalkulator, gdzie użytkownik wpisuje 0, a następnie wciska guzik 1/x, to on powinien grzecznie użytkownika poinformować, że taka operacja matematyczna nie zwraca wyniku, a nie umierać.

logika natrafiła na coś co nie zostało w niej zamodelowane albo zostało zamodelowane z błędem

Czy twoim zdaniem kalkulator nie zamodelował w tym wypadku 1/0? Bo jeśli nie to dalej nie wiem co chciałeś przekazać swoją odpowiedzią.

Żeby skrócić - Either to odpowiednik funkcji złożonej. Problem jest taki że o ile w czystej matematyce zazwyczaj input jest pod ściśłą kontrolą a cały model operuje na systemie zamkniętym to tego samego nie można powiedzieć o 99% aplikacji w IT.

Więc będziesz miał do czynienia albo z lawiną eskalacją wyjątków albo z lawinową eskalacją złożoności poprzez kompleksowe zagnieżdżanie funkcji które będą próbowały obsłużyć otwarte wejście (co z zasady jest niemożliwe). Tak czy siak skończysz albo z łapaniem wyjątków w jakiejś god-clasie albo z unmaintable mess w przypadku Either.


Przetrzyma wszystko
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:2 dni
  • Lokalizacja:Wrocław
1
loza_prowizoryczna napisał(a):

albo z unmaintable mess w przypadku Either.

Co należy zrobić, żeby to osiągnąć?

piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 7 godzin
  • Postów:3277
5

No to wyszło, że nie da się napisać kalkulatora. Oczywiście błąd bierze się z tego, że dziedziny fun reciprocal(x: Double): Double -> 1/x oraz f(x) = 1/x są różne, bo Double to nie to samo co R =/= 0. Tylko co w związku z tym? Bo możliwości jakie widzę to:

  • Pogodzenie się z faktem, że w przypadku złych danych na wejściu aplikacja się wyzajączkuje. Niech się bambus uczy, że przez 0 się nie dzieli.
  • Walidacja danych na UI, ale wtedy UI musi wiedzieć, że przez 0 się nie dzieli, a to trochę tak jak gdyby na klawiaturę zrzucać odpowiedzialność za korektę ortografii.
  • Wprowadzić nowy typ danych, odpowiadający dziedzinie funkcji, np. RealExcept0. Tylko taki obiekt trzeba utworzyć, co oznacza przeniesienie problemu na poziom konstruktora/fabryuki tego obiektu, a to niekoniecznie jest "lepiej"
  • Przechwycić wyjątek na samej górze (UI) i obsłużenie go właśnie w tym miejscu. Tylko wysokie przechwytywanie wyjątków jak leci nie jest dobrą praktyką, bo po paru pięterkach wywołań ciężko już dojść dlaczego coś, gdzieś nisko poszło nie tak.
  • Zmiana typu zawracanego przez funkcję w taki sposób, żeby był w stanie poinformować, że funkcja jest nieokreślona dla wprowadzonej wartości.

Z tych opcji, żadna nie jest idealna, ale w moim przekonaniu ta ostatnia jest najbardziej sensowna.

edytowany 1x, ostatnio: piotrpo
loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
somekind napisał(a):

Co należy zrobić, żeby to osiągnąć?

Popracować na realnym kodzie w języku gdzie typowanie błędów/wyjątków nie jest objawieniem na miarę Optionala

piotrpo napisał(a):
  • Zmiana typu zawracanego przez funkcję w taki sposób, żeby był w stanie poinformować, że funkcja jest nieokreślona dla wprowadzonej wartości.

Z tych opcji, żadna nie jest idealna, ale w moim przekonaniu ta ostatnia jest najbardziej sensowna.

Zgadzam się, lepiej wiedzieć że funkcja ma zachowanie undefined niż wiedzieć że zrobić throwa. Co prawda w typowym use casie oznacza to jedynie tyle że trzeba dopisać mniej testów ale w końcu programowanie piszemy przez programistów dla programistów.


Przetrzyma wszystko
edytowany 1x, ostatnio: loza_prowizoryczna
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:2 dni
  • Lokalizacja:Wrocław
0
loza_prowizoryczna napisał(a):

Popracować na realnym kodzie w języku gdzie typowanie błędów/wyjątków nie jest objawieniem na miarę Optionala

Pracuję na realnym kodzie, nie zauważam żadnej niezarządzalności.
Stąd moje pytanie - co trzeba spieprzyć, żeby wprowadzenie czegoś, co ułatwia pisanie kodu, go skomplikowało?

loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
somekind napisał(a):

Pracuję na realnym kodzie, nie zauważam żadnej niezarządzalności.
Stąd moje pytanie - co trzeba spieprzyć, żeby wprowadzenie czegoś, co ułatwia pisanie kodu, go skomplikowało?

Skoro tak czytasz taski to muszę współczuć menedżerom prowadzącym ten projekt.

Odpowiadając - nie dyskutujemy na temat technik strukturyzacji wyjątków/errorów/scenariuszy nieprzewidzianych w modelu tylko na temat tego czy bezpieczniej w razie wyjątku położyć program czy pozwolić mu dalej działać nie będąc pewnym jak ten wyjątek obsłużyć.

To są podstawy modelowania systemów zamkniętych vs modelowanie systemów otwartych.


Przetrzyma wszystko
somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:2 dni
  • Lokalizacja:Wrocław
0
loza_prowizoryczna napisał(a):

Odpowiadając - nie dyskutujemy na temat technik strukturyzacji wyjątków/errorów/scenariuszy nieprzewidzianych w modelu tylko na temat tego czy bezpieczniej w razie wyjątku położyć program czy pozwolić mu dalej działać nie będąc pewnym jak ten wyjątek obsłużyć.

W przypadku wyjątku kładziemy program.

Ale my tu nie rozmawiamy o wyjątkach, tylko o błędach zwracanych przez funkcje.

loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
somekind napisał(a):

Ale my tu nie rozmawiamy o wyjątkach, tylko o błędach zwracanych przez funkcje.

A czy błąd to nie inna nazwa na ładnie opakowany wyjątek?


Przetrzyma wszystko
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 5 godzin
1

Nie. Istnieje ogromna roznica miedzy np. blednym inputem od uzytkownika, a niedostepnym polaczeniem z baza danych

Albo cos co jest implementacja logiki biznesowej (tylko ze nie happy path), to tez ciezko nazwac wyjatkiem


λλλ
edytowany 2x, ostatnio: stivens
loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
stivens napisał(a):

Nie. Istnieje ogromna roznica miedzy np. blednym inputem od uzytkownika, a niedostepnym polaczeniem z baza danych

No brawo, czyli dochodzimy do sedna. Możemy sobie zamodelować interakcję z systemem zamkniętym ale wszystko idzie się j***ć jak mamy do czynienia z systemem otwartym. Jak w życiu.

Albo cos co jest implementacja logiki biznesowej, to tez ciezko nazwac wyjatkiem

Logika biznesowa opiera się na założeniu że jest systemem zamkniętym. A że w rzeczywistości jest kompletnie na odwrót to wie każdy z doświadczenia.

BTW: Jobs dlatego uznał że w ajfonach lepiej crash aplikacji pokazać jako jej zamknięcie do ekranu głównego niż na Androidzie gdzie apka rzucała ci w twarz komunikatem o crashu. Ten gość był bardziej łebski w zrozumieniu IT niż niektórzy chcieliby przyznać.


Przetrzyma wszystko
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 5 godzin
1

No i dlatego najlepiej wyjatki zostawic do sytuacji wyjatkowych, a faktyczne bledy traktowac jak bledy.

Jesli uderzasz do zewnetrznego API, to masz system otwarty, ale chwilowa niedostepnosc zewnetrznej uslugi jest raczej czyms "spodziewanym". Jesli uderzenie do tego API sie nie powiedzie, to zawsze mozna zrobic jakies retry policy (exponensial backoff np. albo w ogole uderzenie do konkurencyjnego API - np. kursy walutowe z innego banku)


λλλ
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 5 godzin
0

Kolejna sprawa. Jak masz unchecked exception, to mozesz zapomniec to obsluzyc, albo w ogole nie miec w swiadomosci koniecznosci obsluzenia tego. Nie problem jesli, to jest tak krytyczne, ze faktycznie ma wylozyc aplikacje. Wiekszy jesli chcialbys to jednak obsluzyc.

Jak masz checked exceptions, to masz duzo bardziej ubogie i paskudne api/mechaniki do handlowania takich wyjatkow anizeli te udostepniane przez wartosci bledow (a przynajmniej przez te porzadne implementacje)


λλλ
edytowany 4x, ostatnio: stivens
loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
stivens napisał(a):

No i dlatego najlepiej wyjatki zostawic do sytuacji wyjatkowych, a faktyczne bledy traktowac jak bledy.

Jeśli outputem funkcji jest funkcja złożona either to nie masz błędu tylko jasne zachowanie. Problemem się pojawia gdy w 99% przypadków ta błędogenna część jest zestawem otwartym. Bo wtedy możesz się oszukiwać że obsłużyłeś błąd a resztę pchasz do góry w nadziei że ktoś inny go przejmie. Co w większości przypadków prowadzi do:

Jesli uderzasz do zewnetrznego API, to masz system otwarty, ale chwilowa niedostepnosc zewnetrznej uslugi jest raczej czyms "spodziewanym". Jesli uderzenie do tego API sie nie powiedzie, to zawsze mozna zrobic jakies retry policy (exponensial backoff np. albo w ogole uderzenie do konkurencyjnego API - np. kursy walutowe z innego banku)

Tak, wszystko przy założeniu że baza danych automagicznie po drugiej stronie API używając swoich automagicznych algorytmów zapewni nam spójność bo przecież jeśli API jest niedostępne dla nas to przecież musi być niedostępne dla innych. Bo w przeciwnym wypadku mógłby się pojawić rozjazd albo nawet niepoprawne naliczenie pewnych wartości (idempotentność, heheh).

A wtedy po prostu rzucimy użytkownikowi generyczny błąd na twarz i każdemy się skonsultować ze wsparciem albo zrobimy rollback licząc na to że zmiany wprowadzone przez użytkownika są tak małej wartości że nie będzie awanturował.

Powyższe to tylko ładniejsze opakowanie wywalenia aplikacji w starych systemach. Tylko tam system obsługiwali specjaliści więc jak coś się wywalało to się szukało problemu a dziś liczy się na to że otwarty input w postaci usera machnie na to ręką jak w życiu.


Przetrzyma wszystko
edytowany 1x, ostatnio: loza_prowizoryczna
stivens
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 5 godzin
2

Zaczynasz gadac od rzeczy

T.j. piszesz duzo i tak zeby wygladalo madrze, ale nic z tego nie wynika. Ale to chyba standardowa technika trolli. * Nie mowie jeszcze, ze w tym watku trollujesz, ale kiedy kojarze Cie w ogolnosci z bycia quasi-trollem na tym forum, to trudno Cie na powaznie pozniej traktowac. Szczegolnie kiedy zaczynasz belkotac. ** No chyba ze Cie z kims pomylilem, to wtedy przepraszam ;)


λλλ
edytowany 3x, ostatnio: stivens
cerrato
Nie, nie pomyliłeś. Kolega Loża sobie tutaj wpada pisać z czapy, a że (tego nikt mu nie zabierze) jest inteligenty, wygadany i elokwentny to ciężko tak jednoznacznie i szybko stwierdzić, że to troll.
loza_prowizoryczna
To by wyjaśniało czemu Sejm to cyrk i zbieranina trolli a mimo to ludzie dalej ich wybierają. Widocznie desygnata to nie wszystko.
loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
stivens napisał(a):

Zaczynasz gadac od rzeczy

Jak się komuś zarzuca gadanie od rzeczy to trzeba wypunktować do rzeczy. A moje rzeczy są proste:

  • dyskusja jest jałowa bo wyjątek a błąd to praktycznie to samo tyle że ten drugi został zamodelowany a ten pierwszy wynika z skutków nieprzewidzianych (promieniowanie kosmiczne, błąd hardware'u whatever)
  • źródłem nieporozumienia jest jak zwykle Java która utożsamiła błąd zamodelowany z wyjątkiem (wszystko jest wyjątkiem) wobec czego całe sterowanie błędami zostało przerzucone na wyjątki (może są jakieś rozumne wyjątki, nie moja bajka). W założeniach Javy to że wszystko rzucić wyjątkiem ma sens bo większość programów operuje na systemach otwartych a prawdopodobieństwo złego zamodelowania logiki biznesowej jest wprost proporcjonalne do jej skomplikowania więc jest to rozsądne. To rzecz zostało zgwałcone i użyte do sterowanie przepływem zamodelowanych błędów już nie
  • odpowiadając więc wprost na pytanie OPa - mierność programistów Javy doprowadziła do tego że zwrócenie błędu jako częśći wyniku funkcji stało objawieniem języków funkcyjnych. Jak do tego doszło, pytaj Haskella.

EDIT: W Swifcie throws pod spodem tak naprawdę nie jest rzuceniem wyjątku tylko syntactic sugarem na stare dobre przekazanie **NSError z Obj-C. Wyjątki typu segfault, segdump zawsze i bez wyjątku kładą aplikację.


Przetrzyma wszystko
edytowany 1x, ostatnio: loza_prowizoryczna
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 7 godzin
  • Postów:3277
0

To da się napisać kalkulator, czy się nie da?
Java założenie do do wyjątków miała nawet OK, bo checked exceptions były rzucane z miejsc, gdzie problemy mogły się objawić problemy niezależne od aplikacji, np. zapis pliku. Tylko później się okazało, że jak ktoś bardzo nie chce obsłużyć takiej sytuacji, to jej nie obsłuży, a z drugiej strony pojawiły się pomysły na sterowanie wyjątkami i masz potworki typu Spring, gdzie jak użytkownik nie ma prawa wykonac jakiejś operacji, to rzucasz jakimś "Unauthorized", które później framework przekłada na HTTP401.

loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
piotrpo napisał(a):

To da się napisać kalkulator, czy się nie da?

Da - ponieważ to system zamknięty o ograniczonej liczbie wyjątków (dzielenie przez zero) łatwy do zamodelowania. Co prawda niekoniecznie musi być spójny (arytmetyka Peano) ale skoro działa w 99% przypadków to znaczy że działa.

Java założenie do do wyjątków miała nawet OK,

I nikt z tym nie dyskutuje - w normalnym świecie każda operacja może zakończyć się failem. To nie matematyka tylko rzeczywistość. Problem zaczyna się taki że jak liczba tych operacji urasta do monstrualnych rozmiarów to kod odpowiedzialny za obsłużenie przewidzianych (i zamodelowanych) błędów również to w ostateczności kończysz z podejściem - chwytamy w tym miejscu wszystkie wyjątki i udajemy że nic się nie stało albo nie chwytamy i delegujemy to wyżej (co zazwyczaj kończy się wywaleniem aplikacji).

Syntactic sugar w postaci Either czyni rozróżnienie oczywistym ale to jak stwierdzenie że skoro wiemy że umrzemy to możemy się lepiej do tego przygotować.


Przetrzyma wszystko
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:mniej niż minuta
  • Postów:4884
0

Co prawda niekoniecznie musi być spójny (arytmetyka Peano) ale skoro działa w 99% przypadków to znaczy że działa

Czy Ty już zacząłeś Hell Win?😀 Przecież to nie ma sensu w swietle tego, że pracujemy na konkretnych reprezentacjach i algorytmach; poza tym chodzi o zupełność, nie spójność.


loza_prowizoryczna
  • Rejestracja:ponad 2 lata
  • Ostatnio:około 13 godzin
  • Postów:1595
0
lion137 napisał(a):

Czy Ty już zacząłeś Hell Win?:smile

Tak ale jeszcze nigdy go nie skończyłem :(

Przecież to nie ma sensu w swietle tego, że pracujemy na konkretnych reprezentacjach i algorytmach;

No i to jest problem z konkretnymi reprezentacjami - na fladze kolor wolności, rewolucji i monarchii a w szczególe sama czerń. Jeśli o algorytmy to się nie wypowiem bo którykolwiek nie zastosuję to praktycznie zawsze co jakiś czas dostanę wynik niezgodny z książkowym. Ja tu ufać czemuś takiemu?

poza tym chodzi o zupełność, nie spójność.

Ciężko udowodnić spójność w niezupełności.


Przetrzyma wszystko
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)