🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.c
Article #267826

Re: Ciemna strona C++

#267826
From: Marcin ‘Qrczak’ Kowalczyk
Date: Mon, 26 Nov 2007 13:43
142 lines
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-mail
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>

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