🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.python
Article #26611

Re: python vs php - potrzebne argumenty

#26611
From: Sebastian Kaliszewski
Date: Thu, 17 Dec 2009 13:02
351 lines
18067 bytes
Piotr Sawicki wrote:
>> Zapisz cały odpowiadający kod a nie kawałek. skąd pochodzą 
>> errorAhandler i errorBhandler? Przecież nie z powietrza?
> 
> Nazwy procedur.

Czyżby. Jak chcesz kontynuować do li tylko nazwanej procedury bez 
podania jej gdzie dla odmiany ona ma kontynuować. Gdzieś w końcu te 
kontynuacje tworzysz -- więc to pokaż, przynjamniej dla tej jednej, 
którą w przykłądzie z wyjątkami załatwiam lokalnie.

> Nie muszą być albo-albo (argumentowane z góry
> albo lokalnie zdefiniowane w tym miejscu) tak samo jak wyjątki.
> Można np. użyć biblioteki do obsługi błędów.

Ale ta biblioteka musi wiedzieć gdzie kontynuować, albo błąd oznacza 
koniec programu.

W podanym przeze mnie przykładzie jeden błąd jest obsługiwany lokalnie 
(w wolanie) po czym program jest kontynuowany, zatem i w przykładzie 
kontynuacyjnym oczekuję, że będzie jego obsługa pokazana (wraz z 
kontynuowaniem działania programu).


[...]
>> w językach dynamicznych w których wszelkie podstawowe 
>> konstrukcje (wykonanie warunkowe, powtarzanie) są 
>> zaimplementowane bez opierania się o kontynuacje, 
>> kontynuacje nie mają sensu do obsługi sytuacji wyjątkowych.
> 
> Ja widzę taką korzyść: funkcje to podstawowa cegiełka programowania,
> z którą można prosto i łatwo zrobić mnóstwo rzeczy gotowymi narzędziami 
> (dowolnie je przekazywać, komponować, transformować, agregować, wrzucać
> w mapę itd) - choćby wspominanymi przez ciebie metafunkcjami. 
> Z tym samym blokiem kodu, ale wrzuconym w specjalną statyczną 
> składnię tylko-dla-wyjątków da się bez zamotanego mambodżambo już 
> zrobić bardzo niewiele (pominąć albo skleić tylko w jednej możliwej 
> kolejności). Dla mnie to jak różnica między programem posługującym
> się na stdin i stdout czytelnym formatem tekstowym możliwym do 
> obróbki narzędziami shellowymi, a takim który dłubie w pliku z blobem
> binarnym, z którym da się zrobić tylko to co z góry przewidziano. 

Ale kontynuacje to nie są takie zupełnie zwykłe funkcje -- to w końcu 
forma goto -- można je także określić jako metodę dynamicznego składania 
funkcji.


[...]
>> Praktycznie to samo masz ze specyfikacjami wyjątków z głupiej Javy. 
>> Nie skompiluje się, jeśli nie ma statycznie zapewnionej (a raczej 
>> zamarkowanej) obsługi wszystkich błędów.
> 
> Kompilator sprawdzi tylko poprawność formalną.
> 
>> kod niby porządny-kontynuacyjny się fatalnie rozwija 
>> (do momentu kiedy nie ulegnie degeneracji). Każda zmiana 
>> dodająca w jednej głupiej funkcji wymaga dodania nowego 
>> parametru w każdym miejscu wołania 
> 
> W razie zmiany interfejsu, a nie implementacji.

Problem taki, że zmiana implementacji zbyt często wymusza zmianę interfejsu.

> No i bardzo dobrze, 
> po takiej zmianie naprawdę trzeba skorygować wszystkie przypadki
> użycia - przynajmniej widać czarno na białym, które już poprawiono 
> a które jeszcze nie. Jeśli zmienił się kontrakt, a stare wywołania 
> są nieodróżnialne od nowych to dopiero jest problem logistyczny 
> z przeprowadzeniem całości kodu do nowej wersji.

Problem taki, że kontrakt z punktu widzenia klasycznej poprawności 
aplikacji się nie zmienił. Zmieniły się "peryferia".

> 
>> Jest tak samo jak ze statycznymi specyfikacjami wyjątków. Albo czas 
>> rzetelnego sprawdzenia leci w kosmos albo i tak jest na oko.
> 
> Tu jest różnica z brakiem jawnej specyfikacji czegokolwiek
> - pewien rodzaj enkapsulacji, uniezależniający od siebie poprawność
> odrębnych kawałków programu.

No właśnie on uzależnia. I to często niepotrzebnie.

> Dzięki temu czas sprawdzania właśnie
> nie rośnie wykładniczo, bo można to zrobić dla każdej funkcji 
> oddzielnie. Więc doceniam wrzucanie wyjątków w sygnaturę (ale to 
> jest tylko w javie AFAIK),

Jest nie tylko w Javie. Ale w Javie to jeden z bardziej krytykowanych 
ficzerów -- okazał się bardziej "plątać pod nogami" zamiast pomagać.

Powód jest prosty -- w typowym przypadku, wystarczająca obsługa 
większości błędów to jeden catch / except gdzieś blisko korzenia 
hierarchii wywołań. Tylko niektóre błędy wymagają bardziej 
specjalizowanej obsługi. W dodatku ta konieczność specjalnej (a nie 
ogólne) obsługi jest wcale często oczywista.

Inną inkarnacją tego samego metasporu jest dyskusja o tym czy GC jest 
dobre czy złe -- przeciwnicy GC twierdzą, że kiedy mają synchroniczne 
zwolnienie zasobów i destruktor (czyli jak w Adzie czy C++) to nie ma 
problemu np. z automatycznym zamknięciem pliku. Zapominają tylko o tym, 
że 95% zwalnianych zasobów to pamięć, która zwykle jest wystarczająco 
liczna by nie potrzebować jej zwolnienia natychmiast po zaprzestaniu 
używania. I zapominają że destruktory tylko plączą się w tych 95% 
przypadków. I że lepiej te 5% przypadków rozwiązać inaczej (choćby 
Pythonowe with, using z C#, różne rozwiązanie "beansowe" z Javy, itd).

Podobnie argument o konieczności jawnej obsługi każdego błędu ignoruje 
fakt, że zdecydowaną większość błędów można obsłużyć ogólnie. Ba, 
nietóre nawet należy (poza wyjątkowymi przypadkami typu odpalanie 
podaplikacji w sandboksie), np. wyjątgki informujące o błędach w 
programie, brak możliwości kontynuacji z powodu braku niezbędnych i 
najbardziej podstawowych zasobów (out of stack, out of memory, out of time).

> tylko nie wiem po co wprowadzać wtórny
> system [quasi]typów dla argumentów ukrytych składniowo (wyjątków).
> 
>> kluczowym ficzerem obsługi błędów przez kontynuację 
>> jest przerzucanie obsługi błędów wzwyż.
> 
> Mam wrażenie (na podstawie przykładowego kodu), że masz zafiksowany 
> w głowie sposób obsługi błędów poprzez wyjątki i każdą alternatywną 
> metodę wyobrażasz sobie przez takie jej naginanie żeby innymi środkami 
> programować nadal na modłę wyjątków. Nie jest kluczowym ficzerem, 
> bo tak się da ale to jednak niekonieczne, można też zupełnie inaczej.

Błąd albo możesz obsłużyć lokalnie albo "podać dalej" (obsługa "wyżej" 
lub inaczej mówiąc "na zewnątrz"). Obsługa na zewnątrz może być jeszcze 
podzielona na bez powrotu (kończącą program -- wszelkie funkcje znane z 
różnych języków typu sys.exit, abort, terminate) i powracającą do programu.

Nie ma to nic wspólnego z zafiksowaniem czy niezafiksowaniem w głowie 
sposobu obsługi błędów.

> 
>>> Nie wiesz konkretnie które z wywołań zadeklarowanych blokowo 
>>> do łapania/przerzucania wyjątków rzuca które z nich,
>> ??? Podkręć jasność.
>>
>> except WyjątekA łapie obiekty klasy WyjątekA 
>> a except WyjątekB łapie obikety klasy WyjątekB.
> 
> Nie wiadomo z którego calla ten wyjątek wyleciał, nie zawsze
> wynika to z klasy wyjątku. Przy czym nie chodzi mi o moment łapania 
> błędu w runtimie, tylko o czytelność przy uprzednim go sprawdzaniu.

Ale ta wiedza albo jest niepotrzebna (mógł wylecieć z dowolnego, bez 
znaczenia) albo jest potrzebna łączenie z weryfikacją semantyki obsługi 
tego błędu oraz semantyki zawołanej funkcji. Ale jeśli znasz semantykę 
to wiesz czy błąd może polecieć -- i kółko się zamyka.

> 
>> Zatem gdzie widzisz różnicę między napisaniem:
>>
>> funkcja(x, y, z, on_a, on_b)
>>
>> a funkcja(x, y, z) throws a, b
> 
> W tym że jedno wywołanie wygląda funkcja(x,y,z,on_a,on_b), a drugie 
> funkcja(x,y,z) - chyba oczywiste. W pierwszym wypadku czytając 
> takie wywołanie od razu wiem że obsługę błędów przewidziano. 
> I ona oczywiście może być niepoprawna, ale to kwestia sprawdzenia 
> tamtego kodu, tu na razie jest ok. W drugim nie mogę odfajkować
> poprawności właśnie oglądanego kodu dopóki nie sprawdzę w wielu
> innych miejscach - w szczególności punktach wołających aktualny
> kawałek kodu.

Nie. W obu wypadkach lokalnie nie wiesz nic o kodzie wołającym. Nie 
wiesz też o jego poprawności.

> Które w trakcie rozwoju programu mogą się jeszcze
> pojawiać albo zmieniać, więc tak czy siak zostawiam tykającą bombę. 

Zatem zostawiasz ją (skoro uważasz, że zowstawiasz) i tu i tu.


>>>> Tak samo jest z kontynuacjami. 
>>> Nie tak samo, bo od razu wiem że błąd jest obsłużony,
>> Jak?
> 
> Tak że podano kontynuację dla wyjątkowego przypadku (i jeśli jest 
> to onGeneralFailure albo None to od razu to widzę).


Parametr None w wywołaniu rzadko wygląda podejrzanie.


Choć np wywołanie
  funkcja(13, "ala ma kota", None, on_unable)
jest złe a
  funkcja(None, "kot nie ma ali", on_io_fail, on_impossible)
dobre - to oba wywołnia rozpatrywane osobno (widziane w różnych 
fragmentach kodu) wyglądają same w sobie dobrze.


> Z wyjątkami
> mogę to wiedzieć na podstawie tego, że wpisano łapanie wyjątku.
> Ale. To jest zupełnie gdzie indziej w kodzie. W wielu miejscach.

Jeśli masz specyfikacje wyjątków to nie zupełnie gdzie indziej tylko w 
najbliższej okolicy.

> [wpisywanie śmieci]
>> I dlatego odpowiednio ograniczona (choć wystarczająca) 
>> forma kontynuacji jaką są wyjątki jest w takiej 
>> sytuacji lepsza, bo trudniej wszystko cwaniacko rozwalić. 
> 
> Na tej zasadzie to równie dobrze można dla każdego catcha wpisać 
> pass. Przecież pisałem od początku o QA, a nie magicznym wzroście 
> poprawności jednoosobowo pisanego programu dzięki używaniu silverbullet.
> Tak naprawdę to największym zagrożeniem nie jest to, że programista
> przewidzi wszystkie błędy i do ich obsługi perfidnie wpisze śmieci.
> Tylko że normalny programista z definicji (niezależnej od znajomości
> języków programowania) uważa że wszystko pójdzie dobrze, i koncentruje
> się na przebiegu algorytmu w poprawnych sytuacjach. A przetykanie kodu 
> możliwościami niepowodzeń na każdym kroku jest dla niego upierdliwe.

No właśnie. I nie tylko upierdliwe ale zaciemnia kod (jest upierdliwe w 
czytaniu). A jak Wielcy Ojcowie Pythona ;) zauważyli kod się przede 
wszystkim czyta. Dlatego  wychodzi na to że wyjątki są dobre.


>>> Jak na zachęcanie to strasznie dużo roboty na takie obejście. 
>>> A sprawdza się je prosto i tylko raz - w definicji wołanej procedury
>>> (sprawdzenie jej jest i tak nie do uniknięcia, więc ta sama robota).
>> W językach dynamicznych sprawdzenie jest przy użyciu.
> 
> Nie piszę o działaniu programu, tylko czytelności.
> 
>>> po dopisku throws cośtam jeszcze nie wiadomo czy 
>>> tak powinno być czy nie, i gdzie tkwi problem. W drugim przypadku 
>>> wszystko co potrzebne do wypatrzenia partactwa jest na miejscu.
>> No właśnie nie widzę tego na miejscu.
> 
> call funkcja(x,y,z, None, onGeneralFailure) //- ja widzę jak na dłoni.

Co widzisz? Że któryś z parametrów jest None. I co z tego? Parametr None 
jest nagminny. BTW onGeneralFailure też może być (i w większym projekcie 
po prostu byłby) zaakceptowanym rozwiązaniem.

> 
>> To, że w różnych rzadko używanych językach zwykle nie widzisz takiego 
>> kodu wynika moim zdaniem *tylko i wyłącznie* z faktu że są właśnie 
>> rzadko używane, a więc nie są używane przez przeciętną programistyczną 
> 
> Kiedy właśnie o to chodzi że widzę. Błędy są zawsze, tylko w języku
> czytelnym je o wiele łatwiej dostrzec niż w kryptycznym. A jeszcze 
> trudniej z przeoczeniami. Rzeczy opisywane jawnie przy czytaniu widać, 
> niejawnych trzeba się domyślać i robić reverse-enginnering.

Całe programowanie wysokopoziomowe opiera się na tym, że gross rzeczy 
nie opisuje się jawnie. Wszystko jawnie to masz w assemblerze.

[...]
>>>>> Zamyka efekty uboczne w piaskownicy, niezły wynik.
> [...]
>> Dla mnie to to jest sandbox wywrócony na lewą stronę :)
> 
> Na prawą: możesz narobić efektów ubocznych, ale tylko wewnątrz
> monady, bez zaśmiecenia nimi całego środowiska.

To nie ja robię efekty uboczne, to świat ma efekty :)

> 
>> Wartość niepoznawalna przede wszytskim jest i jest niezmienna. 
>> Można się nią normalnie posługiwać poza samym poznaniem. 
> 
> Zmienność się modeluje funkcjami.
> 
>> Świat (stan zewnętrzny) to nie jest wartość w normalnym 
>> rozumieniu tego słowa, jest np. jednorazowy (nie dziwne nie daje się 
>> cofnąć ani zatrzymać), itd...
> 
> Bo masz rozumienie wartości z ubogich języków.

Ależ skąd.

> Wartością pierwszego
> rzędu może być nie tylko stała, ale również bez problemu funkcja 
> (nawet z funkcji w funkcje)

Oczywiście. Każda z nich jest niezmienna i nie ma "początku" ani "końca" 
istnienia jak każdy przyzwoity obiekt matematyczny.

> - więc świat może być np. ciągiem 
> statycznych stopklatek, a ciąg już się bardzo ładnie modeluje.

Problem w tym, że nie moższ wrócić do poprzedniej.


>> Tzn. typ w którym reprezentuję niepoznawalną stałą Chatina jest dla mnie 
>> jak najbardziej normalnym typem, jego wartości mogę przypisywać, 
>> przekazywać do wywołań, brać jako wyniki, itd. A tu guzik.
> 
> Też możesz, od tego m.in. są monady stanowe. Nawet w zapisie
> to wygląda podobnie jak używanie zmiennych w komputacji imperatywnej.

Wiem jak działają monady stanowe wraz z lukrowym zapisem tego co robią. 
Problem taki, że jeśli reprezentują stan zewnętrzny to nie ma możliwości 
powrotu, cofnięcia się.

Dla monady np. reprezentującej dodawanie do listy mogę sobie z jej 
pośrednimi wartościami różne rzeczy robić. Z monadami reprezentującymi 
stan zewnętrzny już nie jest tak pięknie.

Nie da się świata cofnąć i "sforkować".

> 
>> Ogólnie zadania w których pewne akcje zależą od wcześniej 
>> wykonanych, od wyników (i błędów) występujących wcześniej. 
> 
> No to niech zależą, funkcjami się opisuje właśnie zależności
> - wystarczy je wpisać w parametr funkcji. Naprawdę takich nie
> widziałeś, np. szkolnego przykładu generatorów kolejnych liczb 
> pierwszych, zależnie od tego jaka była ostatnia policzona? 

Oczywiście że widziałem. Wszystkie te szkolne przykłądy reprezentują 
stan wewnętrzny. Tak na marginesie: to, że funkcjami się opisuje 
zależności to rzecz oczywista, każda funkcja jest relacją. Ale nie każdą 
zależność da się opisać funkcjami -- nie każda relacja jest funkcją.

Ze stanem zewnętrznym kłopot taki, że zależności nie koniecznie są 
znane, często też nie nawet jak są znane nie są funkcyjne (nie ma 
jednoznacznego przejścia stan wcześniejszy (argument) -> stan późniejszy 
(wynik)).


>> Funkcyjnie możesz zapisać stan wewnętrzny, ale ze stanem zewnętrznym 
>> (czas systemowy, zewnętrzne źródło danych losowych, etc.) jest gorzej. 
>> Albo zamiata się pod dywan tworząc pseudowartości których się nie daje 
>> traktować jak wartości i udaje że wszystko ok, 
> 
> To jest wewnętrznie sprzeczne - właśnie się da tak traktować, i dlatego
> marudzisz że to udawanie, bo jednak działa. Wymyśliłeś jakąś ezoteryczną
> kategorię pseudowartości (?), ale tam nie ma żadnego zaszytego w środku
> kompilatora hacku

Jest hack, jeśli nie wprost w kompilatorze, to w ściśle z nim związanym 
runtime języka. Mamy specjalny "magiczny" typ, którego "wartości" nie 
zachowują się jak by od wartości należało oczekiwać.

> - to jest w bibliotece, zamodelowane normalnymi 
> mechanizmami języka, dało się zrobić jak wszystkie inne funkcje.

Dopiero po zastosowaniu ww. kompilatorowo-rantajmowej "magii".

\SK
-- 
"Never underestimate the power of human stupidity" -- L. Lang
-- 
http://www.tajga.org -- (some photos from my travels)
Technical Details
Message-ID: <ttjpv6-011.ln1@bozon.softax.pl>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!news.nask.pl!news.nask.org.pl!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!zen.net.uk!dedekind.zen.co.uk!newsfeed.neostrada.pl!unt-exc-02.news.neostrada.pl!atlantis.news.neostrada.pl!news.neostrada.pl!bozon.softax.pl!news
References: <h83in7$rl3$1@inews.gazeta.pl> <op.u26lj6r2eaqjf2@jzabielloosx.dubtilt.local> <929230b3-8c01-4aa0-ba4d-af46cf4196f1@m16g2000yqc.googlegroups.com> <hdqtq7$2qja$1@news2.ipartners.pl> <9417e837-c468-4fe6-9ec8-5c17b268cecd@u7g2000yqm.googlegroups.com> <hds989$q2i$1@news.lublin.pl> <slrnhg3lqh.ee.ps171721@duch.mimuw.edu.pl> <hdslom$1ps$7@news.lublin.pl> <slrnhg3o3d.60f.ps171721@duch.mimuw.edu.pl> <hdsvmg$8mc$1@news.lublin.pl> <slrnhg4ts4.fq3.ps171721@duch.mimuw.edu.pl> <slrnhgqec3.tfh.ps171721@duch.mimuw.edu.pl> <lntcu6-2q7.ln1@bozon.softax.pl> <slrnhh8r0k.kjc.ps171721@duch.mimuw.edu.pl> <kr1fu6-2br.ln1@bozon.softax.pl> <slrnhhd3u2.sq6.ps171721@duch.mimuw.edu.pl> <qvmiu6-434.ln1@bozon.softax.pl> <slrnhhgo44.er.ps171721@duch.mimuw.edu.pl> <ri2nu6-fci.ln1@bozon.softax.pl> <slrnhhttme.gtn.ps171721@duch.mimuw.edu.pl> <9j55v6-ih2.ln1@bozon.softax.pl> <slrnhi5tn3.jpi.ps171721@duch.mimuw.edu.pl> <s0shv6-gmm.ln1@bozon.softax.pl> <slrnhihv99.clv.ps171721@duch.mimuw.edu.pl>

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!news.onet.pl!news.nask.pl!news.nask.org.pl!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!zen.net.uk!dedekind.zen.co.uk!newsfeed.neostrada.pl!unt-exc-02.news.neostrada.pl!atlantis.news.neostrada.pl!news.neostrada.pl!bozon.softax.pl!news
From: Sebastian Kaliszewski <s.bez_spamu@remove.this.informa.and.that.pl>
Newsgroups: pl.comp.lang.python
Subject: Re: python vs php - potrzebne argumenty
Date: Thu, 17 Dec 2009 14:02:50 +0100
Organization: TP - http://www.tp.pl/
Lines: 351
Message-ID: <ttjpv6-011.ln1@bozon.softax.pl>
References: <h83in7$rl3$1@inews.gazeta.pl> <op.u26lj6r2eaqjf2@jzabielloosx.dubtilt.local> <929230b3-8c01-4aa0-ba4d-af46cf4196f1@m16g2000yqc.googlegroups.com> <hdqtq7$2qja$1@news2.ipartners.pl> <9417e837-c468-4fe6-9ec8-5c17b268cecd@u7g2000yqm.googlegroups.com> <hds989$q2i$1@news.lublin.pl> <slrnhg3lqh.ee.ps171721@duch.mimuw.edu.pl> <hdslom$1ps$7@news.lublin.pl> <slrnhg3o3d.60f.ps171721@duch.mimuw.edu.pl> <hdsvmg$8mc$1@news.lublin.pl> <slrnhg4ts4.fq3.ps171721@duch.mimuw.edu.pl> <slrnhgqec3.tfh.ps171721@duch.mimuw.edu.pl> <lntcu6-2q7.ln1@bozon.softax.pl> <slrnhh8r0k.kjc.ps171721@duch.mimuw.edu.pl> <kr1fu6-2br.ln1@bozon.softax.pl> <slrnhhd3u2.sq6.ps171721@duch.mimuw.edu.pl> <qvmiu6-434.ln1@bozon.softax.pl> <slrnhhgo44.er.ps171721@duch.mimuw.edu.pl> <ri2nu6-fci.ln1@bozon.softax.pl> <slrnhhttme.gtn.ps171721@duch.mimuw.edu.pl> <9j55v6-ih2.ln1@bozon.softax.pl> <slrnhi5tn3.jpi.ps171721@duch.mimuw.edu.pl> <s0shv6-gmm.ln1@bozon.softax.pl> <slrnhihv99.clv.ps171721@duch.mimuw.edu.pl>
NNTP-Posting-Host: 83.18.189.42
Mime-Version: 1.0
X-Trace: atlantis.news.neostrada.pl 1261052251 23159 83.18.189.42 (17 Dec 2009 12:17:31 GMT)
X-Complaints-To: usenet@news.neostrada.pl
NNTP-Posting-Date: Thu, 17 Dec 2009 12:17:31 +0000 (UTC)
User-Agent: Thunderbird 2.0.0.23 (X11/20090817)
In-Reply-To: <slrnhihv99.clv.ps171721@duch.mimuw.edu.pl>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit