🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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

Re: Ciemna strona C++

#267884
From: Sektor van Skijlen
Date: Wed, 12 Dec 2007 22:17
1021 lines
44981 bytes
Dnia Wed, 12 Dec 2007 16:42:49 +0100, Sebastian Kaliszewski skrobie:
> Sektor van Skijlen wrote:
> >>Nie, nie chodziło. Chodzi o to, że w Pythonie masz a = [1, 2, 3]
> >>a w C++ masz:
> >>std::list a;
> >>a.push_back(1);
> >>a.push_back(2);
> >>a.push_back(3);
> > 
> > 
> > Super - ale (skoro, jak mówisz, w Pythonie jest dużo fajnych zbiorników) czy
> > można tak inicjalizować również dowolny, napisany przez siebie zbiornik?

> Tak.

Ok, to oznacza, że nie ma żadnego zbiornika specjalnie wpasowanego w język?

> >>>>Och i ach. Python nie.
> >>>
> >>>No to ma problem na własne życzenie. Żaden z języków skryptowych "starej
> >>>szkoły" takich debilizmów nie robi.
> > 
> >>Sektor zamiast chrzanić, przeczytaj sobie jaka jest różnica. Zostawiam jako 
> >>zadanie domowe :)
> > 
> > Ha ha ha. Wielka mi różnica, że tupli nie mogę modyfikować! I to w języku, w
> > którym i tak nawet głupiego consta nie da się zrobić.

> consta który nie oznacza niezmienności obiektu? ROTFL!

Niezmienności KTÓREGO obiektu?

> >>>Tego typu podejście jest pożądane tylko w
> >>>językach, które mają większe rygory bezpieczeństwa, ale one sprawdzają to i
> >>>tak w czasie kompilacji (bo sprawdzanie tego w czasie wykonywania to pic na
> >>>wodę).
> > 
> >>Bzdura.
> > 
> > Bo nie masz nic więcej do powiedzenia?

> Bo piszesz tak oczywiste bzdury, że szkoda na to czasu.

To napisanie słowa "bzdura" jest tym bardziej marnowaniem czasu.

> A piszesz bzdury, bo np. te typy przez to, ze się różnią mają inne 
> charakteryskytki wydajnościowe.

LOL, Python i wydajność. Weź ty mnie nie rozśmieszaj z łaski swojej.

Ani Perl, ani Tcl nie posiadają osobnego zbiornika do takich zastosowań i
jakoś wcale ich Python przez to nie przegania.

> >>>>>>Tylko czemu interfejs jest tak parszywie niejednolity? begin/end to trochę mało.
> >>>>>
> >>>>>Jak to niejednolity! Jest cholernie jednolity.
> >>>
> >>>>Ależ skąd. Jednolite w miarę są pary vector i deque, map i multimap oraz set 
> >>>>i multiset.
> >>>
> >>>A co jest niejednolitego w vector i list?
> > 
> >>Wszystko.
> > 
> > "Wszystko" to znaczy "nic" albo "nie wiem".

> Napisane było poniżej.

Napisałeś "wszystko". Jeśli vector i list mają wspólne begin(), end(), size(),
iteratory z dereferencją i inkrementacją wspólne, to znaczy, że jawnie mijasz
się z prawdą. Po co?

> >>>>map wyłazi zupełnie z jej iteracją po parach. list jest w ogóle 
> >>>>w poprzek, itd...
> >>>
> >>>>O jakiś spójnych gwarancjach już lepiej nie myśleć.
> >>>
> >>>Nie rozumiem nadal. Nie podałeś ani jednego konkretu. Opisanie które zbiorniki
> >>>są twoim zdaniem niejednolite nic nie znaczy.
> > 
> >>popatrz sobie na interfejs list i vector. Zrób mi vector::sort(), czy 
> >>vector::splice(whatever) list::at, itd...
> > 
> > To ty do tej pory nie wiesz o tym, że do zbiorników swobodnego dostępu należy
> > stosować algorytm introsort (czyli std::sort), a do zbiorników dwukierunkowych
> > algorytm mergesort (czyli std::stable_sort),


> Sektor co ty za bzdury piszesz?!?!!

Doprawdy?

> Standard *nigdzie* nie mówi jaki algorytm gdzie ma być użyty.

I CO Z TEGO???

> Podaje tylko minimalne wymagania wydajnościowe, i właśnie stabilności.

ROTFLOL.

Powiedz mi najpierw może, dlaczego poniższy program się nie kompiluje:

#include <list>
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>

using namespace std;

int main( int argc, char** argv )
{
	int x [] = { 1, 2, 4, 3, 5 };
	list<int> l( x, x + 5 );
	sort( l.begin(), l.end() );

	copy( l.begin(), l.end(),
			ostream_iterator<int>( cout, " " ) );
	cout << endl;

	return 0;
}


> A stable sort moża i czasem trzeba użyć i na wektorze.

Ale co to ma do rzeczy - tłumaczę ci, jak chłop krowie na miedzy: algorytmu
introsort NIE MOŻNA stosować na zbiorniku, który nie jest zbiornikiem
swobodnego dostępu, bo traci to sens - algorytm ten będzie w tym przypadku
działał wolniej, niż mergesort.

> > a list::sort jest to to samo co
> > std::stable_sort, tylko zaimplementowany w sposób bardziej specjalizowany
> > (stable_sort, tak jak sort, wykonywałby kopie wartości, a list::sort po prostu
> > przestawia węzły na żywca)?

> Poza tym że wyszedłeś z całkowicie błednych założeń to co z tego?

A co z tego niby ma być?

> > Lista ma zaimplementowane wewnętrznie te rzeczy, które się tak zaimplementować
> > opłacało ze względu na jej szczególności i specjalizację.

> To było wyspecjalizowac szablon std::sort dla listy a nie robić niejednolity 
> interfejs.

Sebek, przestań...

Obiecaj mi, że następnym razem pomyślisz 7 razy zanim palniesz, ok?

Co miałby przepraszam robić std::sort dla listy, skoro istnieje jawnie
postawione wymaganie, że std::sort może pracować tylko na zbiorniku swobodnego
dostępu, a std::list takowym nie jest?

Rozumiem, gdybyś zaproponował takie rozwiązanie, że istnieje std::stable_sort,
std::quick_sort oraz std::sort, który wybierze, powiedzmy, std::quick_sort dla
zbiornika swobodnego dostępu, a na liście zrobi sort() (i tak się tego nie da
zrobić w obecnych warunkach, ale to jest jeszcze do przedyskutowania).

Ale nie zaproponowałeś.

Taką propozycję można by jeszcze poddać pod dyskusję i ja nawet mam sporo
argumentów przeciw.

> > To nie jest kwestia spójności zbiorników.

> Jest.

Ale ty wolisz argumenty typu "wszystko chuj".

> > To jest kwestia koncepcji, jakie te
> > zbiorniki spełniają (polecam dokumentację do STL-a).

> To jest kwestia chaosu projektowego.

Twoje odpowiedzi sugerują, że w ogóle nie rozumiesz, o czym mowa. Podejmij
dyskusję w tych kategoriach, a może do czegoś ciekawego dojdziemy, zamiast
rzucać naokoło mięsem.

> > Lista nie spełnia
> > koncepcji zbiornika swobodnego dostępu, a jedynie zbiornika dwukierunkowego, a
> > koncepcja zbiornika dwukierunkowego nie zawiera operator[] ani metody at().

> No i co to ma do sort czy splice?

To, że obie te operacje są specyficzne dla zbiornika std::list?

BYĆ MOŻE sort nie jest operacją LOGICZNIE specyficzną dla tego zbiornika, lecz
sposób jej implementacji również ma znaczenie dla interfejsu.

Do czego chciałbyś zastosować "ogólny sort"? Jesteś w stanie napisać algorytm,
który w środku zawiera sortowanie i pracuje na dowolnym zbiorniku?

list::sort sortuje CAŁY zbiornik i może działać tylko na jednym zbiorniku, bo
przestawia węzły. Ale uwaga: tego algorytmu nie da się wykonać na części
zbiornika. A wszystkie algorytmy sortujące mają się dać wykonać na części
zbiornika.

Te algorytmy muszą pracować na części zbiornika, bo taka jest gwarancja dla
wszystkich algorytmów (bezsensowna moim zdaniem, ale tak zdecydowano).

I nie przypadkiem algorytmy sortujące wymagają zbiornika swobodnego dostępu.

Wynika to stąd, że podczas sortowania istnieje konieczność zmierzenia dystansu
pomiędzy elementami (skoro algorytm sortujący nie ma informacji o wewnętrznej
strukturze zbiornika). Jeśli zbiornik nie jest zbiornikiem swobodnego dostępu,
liczenie dystansu ma liniową (a nie stałą) złożoność, co totalnie dezawuuje
ich użycie. Dlatego algorytmy sortujące używają wprost operator-, a nie
std::distance().

Żebyś się zesrał, nie jesteś w stanie napisać procedury sortowania ZAKRESU
elementów zbiornika std::list takiego, żeby nie wymagał jednocześnie podania
referencji do samego zbiornika. Co równocześnie oznacza, że nie jesteś w
stanie napisać zewnętrznej funkcji, która przyjmie tylko granice zakresów, i
będzie działała dla listy.

Skoro tak, to nie jesteś w stanie napisać std::sort tak, żeby działało i dla
vectora i dla listy.

Czemu ja ci muszę takie podstawowe rzeczy tłumaczyć?

> > Czy to jest takie trudne do zrozumienia?

> Widzę, że dla Ciebie tak. Po tych bzdurach co tu powypisywałeś. Pomyli

Może zacznij pisać w końcu coś do tematu.

> > O tym, czy taki podział na koncepcje jest słuszny, możemy dopiero porozmawiać,
> > jak będziesz wiedział, jak należy postawić problem.

> Ja wiem. Ty, jak widzę, wogóle go zgubiłeś.

Nie widzę, żebyś wiedział - nie napisałeś jeszcze nic poza "bzdura, bzdura,
bzdura".

> >>lista z C++ jest wyjątkowo do dupy. Ponawtykali jakiś rzeczy których nie 
> >>powinno być (sort, merge, itp...)
> > 
> > I bardzo słusznie zrobili - na tej samej zasadzie, na jakiej vector posiada
> > metodę reserve(), a list nie.

> Zrobili do *dupy*. Od tego są specjalzacje szblonów a nie rozpieprzanie 
> interfejsu.

Specjalizacje szablonów można zastosować pod warunkiem, że jesteś w stanie
ustalić wspólny interfejs, realizowalny dla różnych zbiorników.

> > Może twoim zdaniem powinny one mieć wszystkie te same metody, wszystkie te
> > same zależności, wszystkie te same wymagania, a nawet jeszcze niech mają taką
> > samą implementację. Wtedy będą spójne. A nie, cholera, będą miały inne nazwy.

> Nonsens. Zgubiłeś problem.
> Operacje robiące to samo mają mieć interfejs taki sam. A nie mają.

Teoretycznie masz rację, tylko pod warunkiem, że jesteś w stanie:
a) zdefiniować wygodny interfejs
b) zrobić implementację do tego interfejsu

W przypadku std::sort, skoro już o tym mowa, możesz zrobić interfejs, który
wymaga podania, zbiornika, początku i końca, ale nie bęzie on wygodny. Można
zrobić metodę sort dla zbiornika, również z zakresami, ale co wtedy ze
zbiornikami, które nie mają metod, a są sortowalne (np. surowa tablica)?

Wspólny i jednolicie opisany interfejs ma sens, jeśli stosujemy go do typów,
które chciałyby mieć ten interfejs jako część swojego generycznego interfejsu.
Jeśli jednak generyczność tego interfejsu nie ma uzasadnienia, to i
ujednolicać go na siłę nie ma po co.

> Dlaczego map::iterator iteruje po parach a vector::iterator nie

Np. dlatego, że elementami mapy są pary, a elementami wektora nie (chyba że
zrobisz vector<map<A,B>>).

> -- przecież 
> oba są zbiornikami danych do których można się odwoływac po kluczu -- w 
> przypadku vectora kluczem jest indeks, w mapie obiekt dowolnej 
> porównowywalnego i przypisywalnego typu.

No tak, oczywiście - popuśćmy wodze fantazji i piszmy bzdury bez
najdrobniejszego przemyślenia.

Czy zastanowiłeś się odrobinę chociażby nad tym, co praktycznie wałkujemy od
początku tej dyskusji: usunięcie elementu "ze środka" vectora przetasuje owe
klucze dla pewnej liczby elementów, a w mapie nie?

> Mapa powinna mieć dwa iteratory -- 
> jeden po wartościach

Po co?

> i *inny* po kluczach (tylko stały).

Przecież wystarczy w zupełności, że i->first jest stałe, a i->second
modyfikowalne.

> Zbiór zaś powinien 
> mieć tylko stały iterator -- po kluczach. Nie stały interator w zbiorze to 
> jest w ogóle kompletna porażka.

To chyba jest jakiś błąd specyfikacji - w gcc na przykład masz tak:

      typedef typename _Rep_type::const_iterator iterator;
      typedef typename _Rep_type::const_iterator const_iterator;

Więc ja tu nie widzę problemu: on ma i tak zawsze stały iterator. Różnica jest
tylko taka, że POSIADA typ iterator. I bardzo dobrze, że posiada, bo niektóre
algorytmy się do takiego typu próbują odwoływać.

Jest zatem typ iterator, ale operator* użyty na nim zwróci ci stałą
referencję. Czyli jest ok.

> >>A w przypadku multi_map i multi_set może być nawet (zależnie od samej 
> >>implementacji kontenera) nieco szybciej szybciej zaimplementowana.
> > 
> > 
> > A tu się zgadza - już nawet Seweryn podał implementację, chociaż mam poważne
> > wątpliwości, czy rzeczywiście jest sensowna.
> > 
> > Tylko że akurat to jest dla mnie głupie. Nie po to pytam, żeby tylko zadać tak
> > sobie pytanie, tylko dlatego, że chciałbym następnie wykonać na znalezionych
> > danych jakąś operację - i to dla mnie robi equal_range.

> Nie zawsze chcesz od razu robić jakąś operację. Całkiem często robi się np. 
> walidację danych, itp.

To wtedy używasz binary_search.

> >>>>>>>Poza tym nie wiem, dlaczego właściwie uważasz, że vector jest bardziej
> >>>>>>>uniwersalny, niż list.  To prawda, że vector nadaje się do tzw. "większości
> >>>>>>>zastosowań", ale ma jedną bardzo paskudną wadę: unieważnienie iteratorów
> >>>>>>>następuje tam po każdej modyfikacji liczebności zbiornika.
> >>>>>
> >>>>>>Po każdej po której zmienia się capacity. capacity zaś zmienia się tylko 
> >>>>>>czasami.
> >>>>>
> >>>>>Weź ty się z łaski swojej nie ośmieszaj, dobrze?
> >>>
> >>>>sam się ośmieszasz. Te gwarancje są po to, by można było określone 
> >>>>konstrukcje wykonać.
> >>>
> >>>Konkretnie które gwarancje?
> > 
> >>Ważności iteratorów po określonych operacjach.
> > 
> > Ty cały czas nie rozumiesz.
> > 
> > Ile znasz algorytmów, w których ze zbiornika swobodnego dostępu usuwa się
> > elementy od końca? Ja znam tylko jeden przypadek - tylko wtedy, gdy ten
> > zbiornik jest stosem.

> To cienki jesteś :-P. Od końca to nie znaczy kolejne od końca. Po prostu 
> jadąc od końca.

Lol, czemu ty się aż tak kompromitujesz.

Czy fakt, że usuwasz elementy od końca, czy od początku zmienia ci w efekcie
końcowym cokolwiek nt. unieważniania iteratorów?

> Poza tym jak masz ze zbiornika 30 elementowego usunąć 
> elementy 5, 13, 17 i 28 to jadąc od końca możesz to zrobić.

To TYLKO jadąc od końca możesz to zrobić. Bo w przeciwnym razie, po usunięciu
elementu #5, element 13 nagle stanie się 12 i podobnie reszta.

Bardzo fajnie, że znasz algorytm selektywnego usuwania elementów z wektora,
ale wybacz, to nie ma nic zupełnie do tematu, który wałkujemy.

> I co ważne 
> zapewne okaże się, że tak jest lepiej niż użyć map (bo samo dodanie elementu 
> do map jest o 2 rzędy wolniejsze niż dodanie do vector).

Zgadza się bezsprzecznie.

Tyle że dodanie tego elementu na końcu wektora unieważnia ci od razu wszystkie
iteratory (co prawda, nie unieważnia ci indeksów, ale to niewiele zmienia, bo
unieważnia je przy usuwaniu). No chyba że na poważnie myślisz o tym, żeby
sprawdzać ilość zarezerwowanego miejsca przed każdym dodaniem elementu - na
upartego, owszem, masz gwarancję, że iteratory nie będą unieważnione, jeśli
dodanie elementu przydzieli miejsce z zapasu.

Natomiast dodanie tego elementu do listy jest nieco wolniejsze od wektora (ale
bardzo nieznacznie - nie aż tyle, co w przypadku std::map), natomiast ani jego
dodanie, ani usunięcie, nie unieważnia żadnego iteratora do pozostałych
elementów.

> >>>>>>>Miałem właśnie
> >>>>>>>ostatnio taki przypadek, że musiałem trzymać iteratory do elementów, żeby je
> >>>>>>>móc szybko usuwać.
> >>>>>
> >>>>>>To możesz trzymać indeksy elementów i usuwac po begin()+index.
> >>>>>
> >>>>>A, jasne, oczywiście! Usunięcie elementu ze środka też oczywiście nie zmieni
> >>>>>mi względnego położenia obiektów od tego miejsca w dal.
> >>>>>
> >>>>>Czy ty na prawdę tak na siłę chcesz coś udowodnić, że aż nie omieszkasz się
> >>>>>kompromitować?
> >>>
> >>>>Akurat usuwanie z vectora można robić jadąc od rbegin do rend i robiąc 
> >>>>zwykłe erase. To jest gwarantowane przez język.
> >>>
> >>>Sebek, do jasnej cholery, mam takie wymagania, że dowolny obiekt ze zbiornika
> >>>może być usunięty w dowolnym czasie.
> > 
> > 
> >>Nie wiem jakie masz wymagania, bo ich nie podałeś. Nie wiem czy usuwasz 
> >>wszystko na raz, czy też w arbitralnym momencie arbitralny kawałek. Nie 
> >>podałeś też nawet rzędu wielkości danch.
> > 
> > 
> > Przecież napisałem, że chcę je móc w szybki sposób usuwać - nigdzie nie
> > napisałem, że wszystkie naraz. Sugestia, że chcę używać do czegoś określenia
> > pozycji w zbiorniku powinna ci była sprawę naświetlić od razu, bo gdybym
> > chciał usuwać wszystkie naraz, to nie potrzebowałbym żadnej pozycji w
> > zbiorniku, tylko zrobiłbym normalnie clear(). Czy tego aż tak trudno się
> > domyślić?

> Nigdzie ci nie kazałem usuwać wszyskich elementów ze zbiornika. Mogłeś mieć 
> np. listę elementów do usunięcia i chcieć usunąć tylko te.

Ok - załóży nawet, że spróbuję nieco potraktować poważnie to, co piszesz.

Załóżmy. Mamy wektor z elementami opisującymi połączenia.

Mamy cykliczne sprawdzanie połączeń. W jednym cyklu okazało się, że odpadły
trzy połączenia z 10: połączenia o numerach 2, 4 i 9.

Każdy z obiektów połączenia trzymał swój indeks zapisany w polu. W związku z
tym, wiemy że należy wywalić ze zbioru połączeń połączenia o indeksach 2, 4 i
9. Możemy sobie nawet zrobić tymczasowo vector<int>, który będzie je
przechowywał.

No więc wykonujemy naszą operację. Sortujemy nasz wektor z identyfikatorami
połączeń (indeksami do wektora z połączeniami) malejąco, a następnie po kolei
usuwamy nasze połączenia.

Usuwamy najpierw #9. Jest to ostatni element, więc nikt na tym nie ucierpi.

Usuwamy następnie #4 i #2.

W tym momencie okazuje się, że musimy przenumerować wszystkie obiekty od #2
(ostatniego elementu z listy indeksów po posortowaniu) do końca zbiornika, bo
element #3 stał się teraz #2, #5 - #3, #6 - #4 i tak dalej.

Nie jest to trudna operacja, ale wystarczy fakt, że w ogóle trzeba ją wykonać,
i że ma ona liniową złożoność.

Uważasz, że to efektywny sposób gospodarowania zasobami?

> > Czemu ty zamiast najpierw zrozumieć dlaczego chcę stosować taki sposób
> > najpierw usiłujesz mi udowodnić, że go nie potrzebuję?

> Czemu ty nie jesteś w stanie podać prostej specyfikacji tego co potrzebujesz?

Podałem, moim zdaniem, wystarczająco dużo danych, nie zaciemniając
równocześnie obrazu zbędnymi szczegółami.

Jeśli nie byłeś w stanie wymyślić sensownego rozwiązania przy brakujących
założeniach, wystarczyło o te brakujące zapytać, a nie samemu je wymyślać.

Bo sory, ale stawianie takich twierdzeń po fakcie rodzi pewne "podejrzenia".

> >>>A ty mi tu proponujesz jakieś śmieszne
> >>>usuwanie od końca?
> >>>
> >>>>Tyle że jest to mało wydajne i nie ma nic wspólnego z szybkim usuwaniem.
> >>>
> >>>To nie ma nic wspólnego z jakimkolwiek usuwaniem, ani z jakąkolwiek mającą
> >>>sens operacją, jeśli rozpatrujemy przestrzeń rozwiązań przemysłowych, a nie
> >>>akademickich rozważań.
> > 
> >>W "przestrzeni rozwiązań przemysłowych" dla dużej liczby małych struktur to 
> >>sie może opłacać (struktury po kilkadziesiąt pozycji których jest wiele -- 
> >>pomagamy cache locality).
> > 
> > 
> > Tak, ale nie stosowane w taki sposób. Jeśli już, to można kombinować z
> > std::deque, albo czymś podobnym (w sensie, lepiej kontrolowanym).

> std::vector jest zupełnie dobrze kontrolowany i przy większej liczbie 
> operacji zachowuje ważność iteratorów.

Czy jesteś w stanie podać mi przynajmniej JEDNĄ taką operację, która
modyfikuje wektor, nie unieważnia iteratorów, i która w tym celu nie wymaga
żadnych dodatkowych wstępnych założeń poza poprawnością danych wejściowych?

Bo w przypadku listy spełnia ten warunek każda operacja poza erase().

> [...]
> > Jeśli każdy istniejący obiekt siedzi w liście, to każdy ma zapisany swój
> > iterator. W efekcie jestem w stanie każdy z nich usuwać z listy w czasie
> > stałym.

> A skąd mam wiedzieć, że te obiekty są jeszcze trzymane przez co innego 
> (czyli jest do nich innny dostęp niż z kontenera je przechowującego)

Nie ma do nich dostępu znikąd innąd, niż z kontenera je przechowującego. Skąd
ci to w ogóle przyszło do głowy?

> >>Nie. Dopiero teraz coś konkretnego jest, ale i tak mało.
> > 
> > Przestawiłem ci nie wymagania co do działania programu, tylko wymagania co do
> > zbiornika. 

> Nie przedstawiłeś żadnych wystarczających wymagań.

Nie wskazałeś mi, dlaczego wymagania są niewystarczające. Najpierw zacząłeś
wymyślać rozwiązania i narzekasz dopiero gdy wytknąłem ci błędy.

> > Jeśli nie przedstawiłem żadnych szczególnych warunków, przy których
> > można poszukać odrębnego lub prostszego rozwiązania, to znaczy, że takowych
> > nie ma.

> Nie przedstawiłeś warunków wystarczających.

Dobrze - skoro chcesz już uprawiać taką zabawę intelektualną, to proszę
bardzo: napisz mi tutaj dokładnie, jakie przedstawiłem warunki, gdzie te
warunki są niedokładne lub co jest nie sprecyzowane.

> >>>żeby można było pod to
> >>>podpasować konkretne rozwiązania: chcę mieć zbiornik taki, którego elementy
> >>>będą miały węzły o stałej pozycji (wyrażanej odpowiednią wartością) nie
> >>>zmieniającej się w przypadku zmiany liczbności zbiornika (poza usunięciem tego
> >>>właśnie elementu).
> >>>
> >>>Zbiornik taki, jak np. mapa (słownik) spełnia te wymagania, ale jest od
> >>>std::list niezaprzeczalnie gorszy, bo:
> >>>
> >>> - złożoność dostępu jest logarytmiczna
> >>> - istnieje potencjalny błąd nieznalezienia elementu
> >>> - istnieje konieczność użycia generatora kluczy
> >>>
> >>>Nadal czekam na propozycję rozwiązania tego w tym wszystkowyrażalnym Pythonie.
> > 
> >>To już powiedziałem -- słownik
> > 
> > 
> > Jest to - jak powiedziałem - rozwiązanie spełniające, owszem, wymagania (i -
> > co ciekawsze - w językach skryptowych wszyscy je stosują), niestety słabe w
> > stosunku do std::list z uwagi na:
> >  - konieczność generowania kluczy (wartości iteratorów std::list są same z
> >    siebie unikalne na całą aplikację)

> hash(object) działa całkiem dobrze.

hash(object) tworzy unikalny klucz do obiektu? Od kiedy?

> >  - logarytmiczny czas znajdowania węzła w zbiorniku (przy stałym czasie w
> >    przypadku std::list)

> Ależ ten czas nie jest logarytmiczny -- jest stały (zamortyzowany) :)

Amortyzacja polega na tym, że tylko jedna na kilka operacji ma złożoność
gorszą niż stałą. Tymczasem czas wyszukiwania elementu po danym kluczu będzie
miał określoną złożoność forever, za każdym razem, gdy jest wyszukiwany.

I pod warunkiem, że hash ci dobrze wyhaszuje obiekt, bo równie dobrze może ci
zrobić "rzadkie drabinki" i cała "amortyzacja" weźmie w łeb.

No więc dobrze, załóżmy nawet teoretycznie, że jesteś w stanie uzyskać lepszy
czas, niż logarytmiczny (kosztem większego zużycia pamięci swoją drogą) - ale
stuprocentowo stałego czasu (co gwarantuje ci std::list) nie uzyskasz i tak.

> >>a jak nie masz kluczy to zbiór (set).
> > 
> > Zbiór akurat składa się z samych kluczy i jest uogólnieniem słownika (mapy).

> Raczej odwrotnie. Mapa uogólnia set.

Szczerze mówiąc, trudno mi jest jednoznacznie stwierdzić, co jest uogólnieniem
czego. Po prostu set to taka mapa, która nie posiada obiektu wartości
przypisanego do tego klucza.

> Btw w Pythonie każdy obiekt domyślnie 
> może być kluczem -- trzeba by mu tego jawnie zabronić.

No, możliwe - ale co to ma do tematu? BTW ciekaw jestem jak w takim razie te
obiekty mają zdefiniowane porządkowanie.

> >>>>Nie robię. Bezpieczna implementacja Pascala jest możliwa i jest naturalna. W 
> >>>>odróżnieniu od bezpiecznej implementacji C czy C++.
> >>>
> >>>Jasne - po pozbawieniu Pascala np. wskaźników.
> > 
> >>Akurat wskaźniki nie przeszkadzają w bezpiecznej implementacji jeśli nie 
> >>masz na nich arytmetyki (a oryginalny Pascal AFAIR nie miał).
> > 
> > Czyżby? I masz udokumentowaną obsługę sytuacji wyjątkowej w przypadku
> > zerowego lub wiszącego wskaźnika?

> Mogę bez problemu mieć taką implementację. Bezpieczna implementacja C (oraz 
> C++) jest praktycznie niemożliwa.

Z czego to wynika?

> >>>>>>Co do przykładu -- na sieci pełno.
> >>>>>
> >>>>>To znajdź i wklej - dopóki tego nie zrobisz, dla mnie bredzisz od rzeczy.
> >>>
> >>>>Nie jestem proxy do google. Oczywistości szukaj sobie sam.
> >>>
> >>>Twoje oczywistości to dla mnie brednie - i obaj wiemy, że tylko ja mam z tego
> >>>ubaw.
> > 
> >>Ja tam mam niezły. Zwłaszcza gdy wymyślasz bzdury -- zrób sobie google 
> >>python container i nie ośmieszaj się.
> > 
> > Zrobiłem. Tylko jestem za leniwy, żeby ci wkleić te pierwsze 10 linków i
> > udowodnić, że nic nie ma na temat wspomnianego zbiornika.

> Zrobiłeś? ROTFL! A 2, 5 i 6 link sprawdziłeś?

We wszystkich sprawach, w których uważasz, że masz rację, i chcesz to
udowodnić, potrafisz rzucić odpowiednim linkiem.

W tej jednej tego nie robisz. Taktyka "jesteś za głupi, żeby zrozumieć, jaki
jestem mądry" to naprawdę tani blef.

> >>>>>>>Co nazywasz "resztą świata" - Javę, czy Lispa?
> >>>>>
> >>>>>>Javę, Smalltalka, skryptowce, itd...
> >>>>>
> >>>>>Javę, powiadasz? Tam, gdzie mapa nazywa się Map, a strumień Stream?
> >>>>
> >>>>>Smalltalk to dla ciebie jest licząca się reszta świata?
> >>>>>Skryptowce, wśród których masz Tcl-a z Tablicą, Perla z Haszem i Pythona ze
> >>>>>Słownikiem?
> >>>
> >>>
> >>>>Masz jeszcze coś takiego jak ogólnie przyjętą nomenklaturę, reprezentowaną w 
> >>>>literaturze. Tu jest słownik lub tablica asocjacyjna, tablica dynamiczna itd.
> >>>
> >>>I chcesz mi może tym stwierdzeniem uzasadnić, że istnieją jakieś "bardziej
> >>>ustandaryzowane" terminy obrazujące te pojęcia, skoro w powyższym zdaniu
> >>>użyłeś już różnych trzech?
> > 
> > 
> >>Fajsnie się topisz. Nie zauważyłeśm że trzecie z nich dotyczy czego innego 
> >>niż dwa piersze.
> > 
> > 
> > Aha, o tym, że niektórym zdarzało się nazywać słownik również tablicą
> > dynamiczną, również nie słyszałeś?

> Zapewne stosowali się do przyjętej terminologii jak autorzy STL (czyli marnie).

Niewykluczone - to niewiele zmienia. A już na pewno nie zmienia niczego w
kwestii tego, czy istnieje coś takiego jak "ustalione konwencje nazewnictwa".

> >>>>Dałoby się, gdyby całość zaprojektowano a nie zrodzono z chaosu. Jak są 
> >>>>idiotyzmy w stylu vector<bool> to być może nie bardzo da się inaczej, by to 
> >>>>jeszcze było używalne jakkolwiek.
> >>>
> >>>A co złego jest w vector<bool>?
> > 
> >>To, że nie jest kontenerem booli tylko pewnego śmiesznego typu 
> >>vector<bool>::reference?
> > 
> > I co w tym złego?

> Że to nie jest referencja.

W jakim sensie nie jest to referencja?

> >>Ze wszystkimi tego konsekwencjami dla rzeczy takich jak non-const 
> >>operator[], itd...
> > 
> > Jakimi znów konsekwencjami? Że trzeba się posłużyć typem pomocniczym? Że w
> > ogóle da się go zrobić?

> Że to nie jest bool. Że jak użyjesz tego w jakimś szblonie specjalizowanym 
> na bool to możesz się zdziwić.

Że jak użyjesz w jaki sposób? Że milcząco założysz, że vector<T>::reference
jest tożsame z vector<T>::value_type& ?

> >>>>>>>Można oczywiście kwestionować sensowność "ograniczania przez użycie" oraz
> >>>>>>>sensowność sposobu pracy komitetu, który wysysa sobie z palca reguły języka,
> >>>>>>>do których potem producenci kompilatorów muszą wyharatać implementacje (bo
> >>>>>>>jakby goście wcześniej zauważyli te spaghetti-messages, to może losy wzorców
> >>>>>>>potoczyłyby się inaczej). Ale na ówczesny stan wiedzy rozwiązanie wydawało się
> >>>>>>>najlepsze.
> >>>>>
> >>>>>>Wydawało? Czy się raczej wyłoniło się z chaosu (poprzedzających implementacji).
> >>>>>
> >>>>>Z tego, co BS napisał w "DAEC++", rozważano wiele możliwości, jeśli chodzi o
> >>>>>sprawdzanie dopasowania wzorców. Okazało się, że takie będzie najmniej
> >>>>>kłopotliwe.
> >>>
> >>>>W zastanej sytuacji chaosu istniejących implementacji.
> >>>
> >>>Nie było jeszcze żadnych implementacji, kiedy to rozważano. Nie mogło być, bo
> >>>omawiano tam całkiem podstawowe kwestie (takie jak np. czy używać template
> >>><class T> class X, czy class X<T>, jak w Javie jest to teraz), których nawet
> >>>nie można by poddać pod rozważanie, gdyby jakiekolwiek implementacje już
> >>>istniały.
> > 
> >>Sorry, Sektor, Ale Koenig lookup to jest rzecz dużo późniejsza, na tyle 
> >>późniejsza, że dopiero teraz kompilatory to poprawnie implementują.
> > 
> > Ale nie SFINAE.

> To czemu SFINAE nie działało w tych częsciej używanych kompilatorach?

Prawdopodobnie z tych samych powodów, z których nie działają inne rzeczy
zgodne ze standardem.

> >>>>>mieć do nich statyczne wsparcie, bo trzeba sobie zdawać sprawę z tego, że
> >>>>>wszelkie statyczne wsparcie to potencjalne utrudnienia dla użytkownika.
> >>>>>
> >>>>>Poza tym, Java nie jest wcale taka znów dynamiczna. Nie widzę w tym względzie
> >>>>>żadnych większych różnic od C++.
> >>>
> >>>>C++ (zwłaszcza modern) dużą większy nacisk kłądzie na statyzm.
> >>>
> >>>Z powodu wzorców?
> > 
> >>Głównie z powodu przyjętych obyczajów (STL vs Smalltalk-like hierarchy). A 
> >>także z braku paru dynamicznych mechanizmów (choćby refleksja, ładowanie 
> >>dynamiczne klas, itp).
> > 
> > 
> > Nie. Słabo znasz historię C++. Początkowo do C++ miały być stworzone właśnie
> > takie kolekcje, z taką właśnie hierarchią, jak to jest w Javie. Zrezygnowano z
> > tego w imię wydajności.

> Zrezygnowano bo nie było żadnej spójnej propozycji a tylko rzeczy powyrywane 
> z szerszych kontekstów (zwykle bibliotek GUI), w dodatku ścierające się. 
> Taką w miarę zamkniętą propozycją (przy czym stosunkowo niedużą) był STL.

Nieprawda - znów, słabo znasz historię C++. Spójne biblioteki definiujące
zbiorniki (w postaci właśnie shierarchizowanej obiektowo) były już dostępne
(nie pamiętam ich nazw - ale jak koniecznie chcesz, to poszukam, chyba że
wystarczy ci, jak sam przejrzysz D&EC++) dość dawno. Tyle że nie włączono ich
do standardu, bo w momencie, gdy się ten motyw pojawił, nagle zafascynowano
się generyzmem wzorców.

> To 
> trochę na tej zasadzie, jak w I Rzeczpospolitej w kółko wybierano obcych na 
> królów -- miejscowi nie mogli się zgodzić, by jedez z nich nagle był lepszy 
> oid innych.

Analogia cokolwiek osobliwa.

> [...]
> >>>>Za to Java w której jest istotny odsetek elementów dynamicznych ma nagle
> >>>>statyczną kontrolę wyjątków.
> >>>
> >>>Poza statyczną kontrolą - która do samego działania wyjątków niczego nie wnosi
> >>>- nie ma tam nic statycznego.
> > 
> >>Statyczność jeżyka to jest właśnie statyczna kontrola! Obliczenia zawsze są 
> >>dynamiczne, nawet w Sparku.
> > 
> > Jakie obliczenia i jaką kontrolę masz tu na myśli?

> Ma na myśli "pracę programu" zaś kontorlę w czasie kompilacji.

Ale od strony praktycznej.

Co w wyjątkach jest kontrolowane statycznie. Ja mówię o tym, że wyjątki są
dynamiczne, bo tylko od dynamicznych warunków zależy, czy zostanie rzucony,
czy nie (a z kilku możliwych tyko jeden może być rzucony). Dynamiczne jest
również dopasowanie wyjątku do klauzul catch(). Dynamiczna jest również
propagacja wyjątku. To wszystko jest tak samo w Javie, jak i C++.

Oczywiście żadnej z tych rzeczy nie można robić statycznie, bo taki jest
charakter wyjątków. Niestety sprawdzanie, czy "na pewno wyjątek został
obsłużony" to zaprzeczenie dynamicznemu charakterowi wyjątków.

> >>>>Jakby było odwrotnie to byłoby lepiej, co nie znaczy że byłoby dobrze :)
> >>>
> >>>Nie widzę związku - jakby C++ miał statyczną kontrolę wyjątków, to ludzie
> >>>nienawidziliby go jeszcze bardziej :). Natomiast brak ten kontroli mógłby
> >>>pomóc Javie, ale to nie ma znaczenia, skoro programiści i tak Javę kochają.
> > 
> >>Akurat statyczna kontrola wyjątków by wiele nei zmieniła. Wyjechałoby 
> >>unexpected. Bo to że teraz można zrobić:
> > 
> > 
> >>void foo() throws();
> >>{
> >>   throw bar;
> >>}
> > 
> > 
> >>jest wyraźną niekonsekwencją języka.
> > 
> > 
> > Tu się zgadzam, że kompilator mógłby przynajmniej postarać się o ostrzeżenie
> > (ale ponieważ wszystkie autorytety dzisiaj zgodnie olewają specyfikację
> > wyjątków w C++, to i wartość biznesowa tego ficzera jest zbyt niska).

> Przy dynamicznej kontroli kompilator może co najwyżej postarać się -- ale 
> niegdy nie odfiltruje każdej sytuacji. Żeby mógł, potrzebna byłaby statyczna 
> kontrola specyfikacji (jak w Javie).

Albo weryfikiacja skrośna.

Przecież jeżeli masz funkcję, która woła inną fukcję, to znikąd nie dowiesz
się, że ta inna funkcja rzuca wyjątkiem. Chyba że założysz milcząco - jak to
jest w Javie - że tylko niektóre wyjątki są przepuszczane, chyba że jawnie
zdecydowano inaczej.

Natomiast uważam, że można by to weryfikować skrośnie i nawet ewentualnie
umożliwiać uzyskiwanie listy propagowanych wyjątków dla każdej poszczególnej
funkcji.

> > Jedynym sensownym sposobem na statyczne sprawdzanie wyjątków byłby analizator
> > kodu, który sam sprawdza, jakie wyjątki są rzucane przez jakie funkcje. I
> > dodatkowo, żeby produkował z tego raport, na bazie którego kompilator mógłby
> > dokonać optymalizacji.

> Co nie działałoby w przypadku zewnętrznych binarny-only modułów. (Bo wyjątek 
> może lecieć gdzieś w sródku i może to nie być reprezentowane w żadnym pliku 
> nagłówkowym).

Może. Więc poszlibyśmy dalej - informacje o rzucanych przez daną funkcję
wyjątkach byłyby zawarte w binariach biblioteki.


> [...]
> >>Pobaw się trochę z sygnałami na systemie bez NPTL a poitem z NPTL :)
> > 
> >>Albo choćby taki "szczegół" jak get_pid() :)
> > 
> > Ano to ja wiem, że implementacja LinuxThreads jest niezgodna z POSIX. Ale
> > szczęściem nie mam dziś nigdzie w użyciu systemu z jądrem sprzed 2.6.

> Ty nie, ale się trafia.

Ale pocieszę cię - z Cygwinem jest jeszcze gorzej.

Szef mi właśnie to, swoją drogą, wytknął na ostatniej konferencji. Tego mojego
Driver'a nie będzie można uruchomić lokalnie na Windowsie. Na razie wpadłem na
szybki pomysł zamiany posix threads na boost::thread.

> >>>>>>Ani o tym ani o tym. Chodzi o to, by błędy wykonania były "contained". Niech 
> >>>>>>sobie będzie abort, wyjątek, cokolwiek, ale niech po pierwsze będzie a po 
> >>>>>>drugie niech będzie tylko to (a nie losowa poprawka do przetwarzanych danych).
> >>>>>
> >>>>>Dobrze, nawet się zgadzam. To teraz przystaw to do praktycznych możliwości
> >>>>>realizacji powyższych założeń.
> >>>>>
> >>>>>Jeśli chodzi np. o odwołanie się do zerowego wskaźnika, to masz tu dwie
> >>>>>możliwości: albo w języku sprawdzasz wskaźnik przed każdym odwołaniem
> >>>>>(usuwając jedynie zbędne sprawdzenia, gdy jest to bezużyteczne), albo
> >>>>>posiadasz platformę wirtualną, na której uruchamiany jest program, i która to
> >>>>>platforma sama posiada odpowiednie właściwości pozwalające na wygenerowanie
> >>>>>wyjątku w takim przypadku. W obu przypadkach mamy do czynienia z dodatkowym
> >>>>>narzutem, który jest tylko czasem akceptowalny.
> >>>
> >>>>W większości systemów nie embedded masz tą wirtualizację daną z góry i nie 
> >>>>masz wyboru.
> >>>
> >>>Ale to się do niczego nie nadaje.
> > 
> >>Co się nie nadaje? To się zachowuje całkowicie deterministrycznie. Zarówno 
> >>na windowsach, gdzie jest SEH jak i nauniksach, gdzie masz sygnały moża 
> >>rzecz załatwić na poziomie runtime języka.
> > 
> > 
> > Rzecz w tym, że to nie takie proste.
> > 
> > Nie każdy system posiada systemową implementację takiej np. malloc. Czy dziś
> > jakieś systemy nie mają - tego nie wiem, ale w którymś ze starszych
> > posixowych systemów funkcja malloc była normalną funkcją użytkownika i sama
> > zarządzała zasobami, w kwestii systemu poprzestając jedynie na sbrk().

> Nadal malloc jest funkcją użytkownika tylko nie koniecze z systemu woła się 
> sbrk(). Tylko co to ma do rzucania GPF przy odwołaniu pod adres 0? Na 
> Windzie mie działa, na Linuksie takoż.

Rzecz w tym, że nie działa spójnie, ani na jednym, ani na drugim.

Na Windowsie to nie wiem, czy daje się przechwycić (ale jakoś musi się dać,
skoro Cygwin to tłumaczy na SIGSEGV).

Na posixach powiedzmy, że na upartego by się dało przechwytując SIGSEGV, ale
odwołanie do zerowego wskaźnika to nie jedyna przyczyna tego sygnału i nie da
się jej nijak wyodrębnić.

> > Co
> > oznacza np., że aplikacja nigdy nie oddawała do systemu przydzielonej pamięci,
> > a także przydzielała przez sbrk() większe bloki i wydzielała kawałki tortu z
> > jej środka. W takim przypadku niemożliwe jest określenie, czy odwołanie do
> > określonego miejsca w pamięci odwołuje się do przydzielonego kawałka, czy nie.

> Mówiliśmy od odwołaniu do NULL a nie do dowolnego kawałka.

Tak, ale NULL to nie jest jedyny problem. Co więcej, nawet ten problem nie
jest rozwiązywalny.

> > Anyway, nie wiem, czy nie wystarczyłoby coś w rodzaju platformy w podobnym
> > stylu, co robi C#. W sensie, że niby masz ograniczenia platformy, ale i tak
> > program wykonuje się na platformie natywnej.

> ???
> Program C# jest kompilowany do CIL i wykonuje się na VM z .Net.

Nie ma czegoś takiego, jak VM z .NET, jeśli mówimy o powszechnym rozumieniu,
czym jest maszyna wirtualna.

> Ta VM jest 
> realizowana całkiem wydajnie jako JIT ale wirtualizacja cały czas jest.

Wirtualizacja jest czysto teoretyczna - kod w CIL-u, który dochodzi już do
etapu wykonywania, jest kodem wyłącznie natywnym. Goście od .NET jasno piszą,
że język CIL nigdy nie był pisany z uwzględnieniem możliwości implementacji
jako VM. Od zawsze miał być tylko i wyłącznie kompilowany JIT-owo.

> Że są wyjścia unmanaged do poziomu platofrmy natywnej?

To akurat jest bez różnicy - jedyna różnica to jak zostaną skompilowane
poszczególne operacje.

> W Javie też możesz tak sobie zrobić.

Doprawdy? Jak? Czy istnieje jakieś unchecked/unsafe w Javie, o którym nie
wiem, czy można metody natywne implementować w Javie? Nigdy o tym nie
słyszałem.

> >>>>>Wątki po prostu powinny pracować na niezależnych danych.
> >>>
> >>>>Wtedy mogą być równie dobrze procesami. Tzn. niech mają osobną przestrzeń 
> >>>>adresową i już.
> >>>
> >>>
> >>>Gdyby na ZUPEŁNIE niezależnych danych pracowały, to wtedy tak, co więcej,
> >>>takie procesy nawet nie wymagają komunikacji.
> >>>
> >>>Ale - jak to napisałem gdzieś - jest to sytuacja idealna, której na dodatek
> >>>nikt nie zamierza osiągać. Im mniej danych wątki wymieniają między sobą, tym
> >>>lepiej, ale jeśli nie wymieniałyby ich w ogóle, to istnienie wątków traci
> >>>sens.
> >>>
> >>>Chodzi więc o to, że w przypadku wątków dane przekazuje się znacznie wygodniej
> >>>i wątki mogą raz na jakiś czas korzystać z tych danych. Nie powinny jednak na
> >>>nich "pracować" to znaczy odwoływać się do wspólnych danych przez cały czas
> >>>swojej pracy.
> > 
> >>Akurat można sobie zogranizować komunikację między procesami też żeby była 
> >>zupełnie wygodna.
> > 
> > 
> > I tworzyć np. obiekty w dzielonej pamięci? Nie bardzo mi się to widzi.

> Na wielu OS możesz mieć te same adresy logiczne po obu stornach -- wtedy 
> całkiem normalnie to się robi.

Jeśli już stwierdzasz, że "na wielu OS", to znaczy że nie jest to rozwiązanie
przenośne.

> > Nie bez powodu stworzono normalny mechanizm wątków - gdyby komunikacja
> > międzyprocesowa wystarczała, nikt by tego nie tworzył.

> Kiedyś wydawało się, że tak będzie super. Bo przełączanie ciężkich 
> kontekstów było wooolne, mechanizmy dzielonej pamięci bardzo ograniczone. 

E tam ograniczone. Takie samo było jak jest teraz.

> Tak miało być dużo szybciej.

> Dziś takie rzeczy jak MPI pokazują że szybciej nie jest. Lepsze wsparcie dla 
> pamięci dzielonej, np. poprzez memory mapped files

I na czym polega owo "lepsze wsparcie" poza faktem, że jesteś w stanie tą
pamięć zidentyfikować poprzez ścieżkę do pliku? Problemy z tworzeniem obiektów
w takiej pamięci są dokładnie takie same, jak w shm.

> pozwala na zrobienie 
> wspólnego okna w przestrzeniach adresowych wielu procesów, gdzie wskaźniki 
> zachowują się normalnie.

A pamięć dzielona z IPC działała źle lub nie spełniała któregokolwiek z tych
założeń?

> A przełączanie kontekstów nie jest już tak istotne 
> z uwagi na to że procesory są szybsze a systemy lepiej zoptymalizowane.

Terefere. To po co w systemach operacyjnych na siłę robiono LWP?

> [...]
> >>>Ależ oczywiście, że chodzi o oba. Zresztą znaczenie 'volatile' w Javie i w C++
> >>>jest identyczne\
> > 
> >>Ależ skąd!
> > 
> >>>(jeśli oczywiście uwzględnimy fakt, że gcc ma rozszerzenie w
> >>>stosunku do standardu, co pozwala zmiennym oznaczonym volatile pracować
> >>>poprawnie z posix threads).
> > 
> >>Chyba coś zmyślasz... Volatile które ma semantykę acquire/release? W GCC??? 
> >>Takie volatile to jest sobie w MSVC z VS.NET 2005, ale nie w GCC.
> > 
> > To zależy.

> Nie bardzo zależy. W Javie volatile jest ściśle wyspecyfikowane -- odowłanie 
> do takiego pola oznacza na natywnej platformie wystosowanie odpwoiednich 
> barier pamięci (acquire przed i release po odwołaniu). W GCC nic takiego nie 
> ma. Jak architektura nie ma strict memory ordering to wszystko się rozjeżdża.

Nie stawiałbym tutaj takich tez nt. gcc - chyba że wyraźnie tak piszą w
specyfikacji tego kompilatora na każdą platformę.

> >>A w standardzie C++ volatile dotyczy tylko i wyłącznie sygnałów i nic 
> >>więcej. O wątkach nie ma mowy bo takie pojęcie w C++ nie występuje
> > 
> > To się akurat zgadza.

> I tu jest różnica w stosunku do Javy. Sygnały są wykonywane zawsze w tym 
> samym kontekscie (na tym samym rdzeniu) co proces.

Pod warunkiem, że nie jest to sygnał, który dostaje wątek potomny w
zastępstwie.


-- 
//  _    ___         Michal "Sektor" Malecki <sektor(whirl)kis.p.lodz.pl>
\\ L_ |/ `|  /^\ ,()                         <ethouris(O)gmail.com>
// \_ |\  \/ \_/ /\ C++ bez cholesterolu: http://www.intercon.pl/~sektor/cbx
"Java is answer for a question that has never been stated"
Technical Details
Message-ID: <fjpmln$o6q$1@kujawiak.man.lodz.pl>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.rmf.pl!agh.edu.pl!news.agh.edu.pl!newsfeed.silweb.pl!news.man.lodz.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> <fimb7n$80v$1@bozon2.softax.pl> <fj5k6j$r3e$1@kujawiak.man.lodz.pl> <fj68ei$vbo$1@bozon2.softax.pl> <fjmo4o$a5r$1@kujawiak.man.lodz.pl> <fjouia$gr3$1@bozon2.softax.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!newsfeed.silweb.pl!news.man.lodz.pl!not-for-mail
From: Sektor van Skijlen <ethouris@guess.if.gmail.com.is.valid.or.invalid>
Newsgroups: pl.comp.lang.c
Subject: Re: Ciemna strona C++
Date: Wed, 12 Dec 2007 22:17:27 +0000 (UTC)
Organization: LODMAN - Metropolitan Area Network in LODZ, Poland
Lines: 1021
Sender: Michal Malecki <sektor@student.kis.p.lodz.pl>
Message-ID: <fjpmln$o6q$1@kujawiak.man.lodz.pl>
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> <fimb7n$80v$1@bozon2.softax.pl> <fj5k6j$r3e$1@kujawiak.man.lodz.pl> <fj68ei$vbo$1@bozon2.softax.pl> <fjmo4o$a5r$1@kujawiak.man.lodz.pl> <fjouia$gr3$1@bozon2.softax.pl>
NNTP-Posting-Host: student.kis.p.lodz.pl
Mime-Version: 1.0
X-Trace: kujawiak.man.lodz.pl 1197497847 24794 212.191.89.21 (12 Dec 2007 22:17:27 GMT)
X-Complaints-To: abuse@man.lodz.pl
NNTP-Posting-Date: Wed, 12 Dec 2007 22:17:27 +0000 (UTC)
User-Agent: tin/1.8.3-20070201 ("Scotasay") (UNIX) (FreeBSD/6.2-RELEASE-p3 (sparc64))
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit