Article View: pl.comp.lang.c
Article #267826Re: Ciemna strona C++
From: Marcin ‘Qrczak’ Kowalczyk
Date: Mon, 26 Nov 2007 13:43
Date: Mon, 26 Nov 2007 13:43
142 lines
9258 bytes
9258 bytes
Dnia 26-11-2007, Pn o godzinie 12:26 +0000, Sektor van Skijlen pisze:
> Podobny los spotkał przecież Tcl-a, a jest to z języków inspirowanych
> Lispem (nawet w niewielkim stopniu) jeden z najsensowniejszych.
W tym przypadku od podróbki wolę oryginał. Największy grzech Tcl to
nieuznawanie wskaźników, czyli konieczność symulowania ich unikalnymi
symbolicznymi nazwami, nieodróżnialnymi od stringów i bez szans na
odśmiecanie. No i z dwojga złego wolę składnię Lispa od Tcla. Poleganie
na eskejpowaniu cudzysłowów i spacji w semantyce podstawowych konstrukcji
językowych jest chore.
> > Różnica jest zasadnicza. Bibliotekę Javy można owinąć w interfejs innego
> > języka programowania polegając wyłącznie na informacji dostępnej w czasie
> > wykonania. Podobnie jak w wielu innych językach. Można zobaczyć, jakie są
> > w niej klasy, jakie one mają metody, wywoływać metody po nazwie znanej
> > w czasie wykonania, przekazywać obiekty nie znając statycznie ich typu.
>
> Pod warunkiem, że projekt jest skompilowany javac-em, a nie gcj-em.
Nieprawda, refleksja działa tak samo w gcj.
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/package-summary.html
> > W C++ niczego takiego nie ma
>
> Poprawka: dla C++ nikt do tej pory nie napisał kompilatora kompilującego na
> taką platformę, która by to udostępniała.
A w Javie to jest w standardzie, więc jest w każdej implementacji.
> Przecież jeśli - dajmy na to - chciałbym wywołać sobie metodę Javy spod
> skryptu w Tcl-u (Jacl?), to MUSZĘ znać nazwę tej metody, jej właściwości,
> interfejs, typy argumentów, typ zwracany, posiadać facility do przekształcania
> danych w razie konieczności itd.
Nie, dokładnych typów argumentów nie trzeba znać. Na przykład nie trzeba
w miejscu wołania wiedzieć, czy argument jest typu int, czy long, ani
nie trzeba w żaden sposób jawnie informować o typie wyniku - on musi być
odczytywalny automatycznie, skoro jest wyznaczony jednoznacznie przez
funkcję. Niedopuszczalna byłaby konieczność powiadamiania o dokładnym
typie (w tym typie wyniku) połączona z zachowaniem niezdefiniowanym,
jeśli nie trafimy. A tak jest przy dlsym w C i C++. Oraz w niektórych
prymitywnych FFI do C opartych wyłącznie na dlsym, bez wykorzystywania
informacji pochodzących z pliku nagłówkowego.
> Na cholerę mi do tego jest potrzebne iterowanie po wszystkich
> elementach definiowanych przez bibliotekę!?
Może być bez iterowania. Byle dało się użyć elementu znając jego nazwę
(dynamicznie) i wiedząc mniej więcej, skąd pochodzi. Może nie być
możliwości sprawdzenia, ilu argumentów potrzebuje, byle pomyłka była
wykryta, a nie skutkowała zachowaniem niezdefiniowanym. Chcę uzyskać
z danej biblioteki interfejs bez zachowania niezdefiniowanego, bo ono
nie pasuje do docelowego języka.
Kogut ma minimalną refleksję. Zresztą w dynamicznie typowanym języku
granica między refleksją a zwykłym użyciem się rozmywa (statycznie
typowany język może sobie nazwać refleksją wszystko, co sprawdza typy
dynamicznie zamiast statycznie, czyli co dla dynamicznie typowanego
języka jest normą). W Kogucie można:
- Odwołać się do pola obiektu znając nazwę pola (odwołanie do pola
jest aplikacją do symbolu). To nie jest refleksja, tylko dynamizm.
- Odczytać nazwę typu i nazwę nazwanej funkcji.
- Dodać nadtyp istniejącego typu.
- Sprawdzać relację podtypu, wylistować nadtypy danego typu.
- Dodać metodę funkcji generycznej dla danych typów dispatchowanych
argumentów (to też nie jest refleksja).
- Uzyskać konstruktor i listę nazw pól obiektu typu rekordowego.
Typ rekordowy to mniej więcej odpowiednik typu POD w C++.
- Uzyskać obiekt reprezentujący dany moduł (pola tego obiektu to
zmienne eksportowane przez moduł). Nazwa modułu musi być znana
statycznie, ale wzbogacenie tego o znalezienie modułu dynamicznie
byłoby trywialne (z użyciem dlsym).
- Uzyskać opis aktywnych funkcji na stosie z historią rzuconych,
nieobsłużonych jeszcze wyjątków, ale bez gwarancji dokładności -
służy to tylko pokazaniu tego użytkownikowi w ramach debugowania
przy niezłapanym wyjątku.
- Wylistować zawartość modułu na poziomie potrzebnym do kompilacji
kodu, który używa tego modułu. To będzie potrzebne, kiedy będę robił
interpreter używający skompilowanych modułów swojego hosta z tymi
samymi typami.
- Zrobić typ z konstruktorem bądź nazwaną funkcję generyczną na
podstawie informacji znanej dynamicznie. To są dodatkowe konstrukcje,
które będą potrzebne do interpretera, bo normalnie te rzeczy tworzy
się bardziej statycznymi sposobami, np. normalnie nazwa tworzonego
typu musi być znana statycznie.
- Monitorować kończenie programu, wypadnięcie nieobsłużonego wyjątku
poza program, tworzenie wątków, fork procesu.
- Iterować po istniejących wątkach.
Nie można za to:
- Odczytać informacji o liczbie argumentów oczekiwanych przez funkcję
(w ogóle nie musi to być jedna liczba ani nawet skończony zbiór,
formalnie nie ma takiego pojęcia, choć kompilator statycznie to
sprawdza kiedy tylko może) ani tym bardziej oczekiwanych typów
ani typu wyniku.
- Odczytać informacji o polach obiektu (z wyjątkiem typów rekordowych).
Obiekty w ogóle nie muszą mieć pól, np. mogą być zrealizowane w C.
- Skonstruować obiektu danego typu mając tylko ten typ.
- Dostać się do prywatnych składników obiektu albo modułu.
- Zmienić czegoś, co jest uznawane za niezmienialne, np. typu
istniejącego obiektu albo działania istniejącej funkcji.
- Usunąć nadtypu danego typu ani usunąć metody funkcji generycznej.
- Wylistować podtypów danego typu (nie są nawet fizycznie zebrane
w jednym miejscu).
- Wylistować istniejących metod danej funkcji generycznej.
- Wyekstrahować implementacji metody funkcji generycznej dla danych
argumentów bez jej wołania.
To, co można, wystarcza np. do tego, żeby interpreterowi Pythona
udostępnić funkcjonalność danego modułu Koguta (tudzież zbioru modułów)
bez konieczności listowania zawartości tego modułu. Obecnie trzeba
jednak statycznie zaimportować ten moduł, tzn. nie można znaleźć go
z poziomu Pythona znając dynamicznie jego nazwę.
Jeszcze jedno, z trochę innej beczki: można statycznie sprawdzić,
czy dana nazwa jest zdefiniowana przy obecnie zaimportowanych nazwach
albo czy dany moduł jest dostępny przy obecnym zestawie dołączonych
"bibliotek". Dzięki temu można robić coś w rodzaju warunkowej kompilacji
zależnej od obecności danej funkcjonalności bez czegoś w rodzaju
autoconfa. Ale tylko jeśli atomowym testem jest obecność modułu
bądź nazwy. Można przy tym wstrzykiwać takie nazwy z linii poleceń
kompilatora. Makr na razie nie ma, kiedyś będą (w stylu podobnym
do syntax-case
w Scheme).
> > W C++ nie można też złapać wyjątku i np. przekazać go do innego wątku
> > bez statycznej znajomości jego typu.
>
> Owszem, można. Pod warunkiem oczywiście, że jest wyprowadzony z
> std::exception.
Nie można go potem rzucić z powrotem bez wyliczenia każdej możliwej
podklasy, bo przy rzucaniu wyjątku liczy się statyczny typ argumentu
throw, a nie dynamiczny typ rzucanego obiektu.
--
__("< Marcin Kowalczyk
\__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Technical Details
Message-ID:
<1196084612.2991.60.camel@qrnik>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news2.icm.edu.pl!newsfeed.atman.pl!newsfeed.tpinternet.pl!atlantis.news.tpi.pl!news.tpi.pl!not-for-mailReferences:
<fghgeo$spf$1@nemesis.news.tpi.pl> <fghsb4$kpq$1@news.dialog.net.pl> <fgo4c7$mtu$1@news.vectranet.pl> <20071106073039.433f4934@Vorago> <fgqn9m$74j$2@news.vectranet.pl> <618565031.20071107113041@pkierski.net> <fgt6sh$jov$1@news.vectranet.pl> <fgtb6j$nur$1@news.vectranet.pl> <fgv6ba$k14$1@bozon2.softax.pl> <fgvkne$u3b$1@news.vectranet.pl> <fh1tjd$dtt$1@bozon2.softax.pl> <fh2lj6$qkh$1@news.vectranet.pl> <fha3as$pap$1@bozon2.softax.pl> <fhaj8u$e02$1@news.vectranet.pl> <fhf09d$ohq$1@bozon2.softax.pl> <fhfi9l$640$1@news.vectranet.pl> <fhurmu$5d9$1@bozon2.softax.pl> <fhv020$8k1$1@news.vectranet.pl> <fi1bs4$nn3$1@bozon2.softax.pl> <fi27ds$gt1$1@kujawiak.man.lodz.pl> <fi458p$fmv$1@bozon2.softax.pl> <fi9ckc$2u5$1@kujawiak.man.lodz.pl> <1195918508.27382.40.camel@qrnik> <fiee2a$af0$1@kujawiak.man.lodz.pl>Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news2.icm.edu.pl!newsfeed.atman.pl!newsfeed.tpinternet.pl!atlantis.news.tpi.pl!news.tpi.pl!not-for-mail From: Marcin ‘Qrczak’ Kowalczyk <qrczak@knm.org.pl> Newsgroups: pl.comp.lang.c Subject: Re: Ciemna strona C++ Date: Mon, 26 Nov 2007 14:43:32 +0100 Organization: tp.internet - http://www.tpi.pl/ Lines: 176 Message-ID: <1196084612.2991.60.camel@qrnik> References: <fghgeo$spf$1@nemesis.news.tpi.pl> <fghsb4$kpq$1@news.dialog.net.pl> <fgo4c7$mtu$1@news.vectranet.pl> <20071106073039.433f4934@Vorago> <fgqn9m$74j$2@news.vectranet.pl> <618565031.20071107113041@pkierski.net> <fgt6sh$jov$1@news.vectranet.pl> <fgtb6j$nur$1@news.vectranet.pl> <fgv6ba$k14$1@bozon2.softax.pl> <fgvkne$u3b$1@news.vectranet.pl> <fh1tjd$dtt$1@bozon2.softax.pl> <fh2lj6$qkh$1@news.vectranet.pl> <fha3as$pap$1@bozon2.softax.pl> <fhaj8u$e02$1@news.vectranet.pl> <fhf09d$ohq$1@bozon2.softax.pl> <fhfi9l$640$1@news.vectranet.pl> <fhurmu$5d9$1@bozon2.softax.pl> <fhv020$8k1$1@news.vectranet.pl> <fi1bs4$nn3$1@bozon2.softax.pl> <fi27ds$gt1$1@kujawiak.man.lodz.pl> <fi458p$fmv$1@bozon2.softax.pl> <fi9ckc$2u5$1@kujawiak.man.lodz.pl> <1195918508.27382.40.camel@qrnik> <fiee2a$af0$1@kujawiak.man.lodz.pl> NNTP-Posting-Host: hjd150.internetdsl.tpnet.pl Mime-Version: 1.0 X-Trace: atlantis.news.tpi.pl 1196084682 13446 79.187.237.150 (26 Nov 2007 13:44:42 GMT) X-Complaints-To: usenet@tpi.pl NNTP-Posting-Date: Mon, 26 Nov 2007 13:44:42 +0000 (UTC) In-Reply-To: <fiee2a$af0$1@kujawiak.man.lodz.pl> X-Mailer: Evolution 2.12.1 PLD Linux Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit