eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programmingCo jest nie tak z C++ (było: Rust)Re: Co jest nie tak z C++ (było: Rust)
  • Data: 2017-08-13 11:23:29
    Temat: Re: Co jest nie tak z C++ (było: Rust)
    Od: "M.M." <m...@g...com> szukaj wiadomości tego autora
    [ pokaż wszystkie nagłówki ]

    On Sunday, August 13, 2017 at 7:44:52 AM UTC+2, g...@g...com wrote:
    > Mógłbyś doprecyzować, co masz na myśli, używając frazy
    > "kryterium porównawcze"? (ja ją rozumiem w taki sposób,
    > że to jest "kryterium, względem którego porównujemy",
    > ale to ma sens dopiero wtedy, kiedy porównujemy, a nie
    > kiedy próbujemy ustalić, jakie coś ma wady)

    Jeśli nie uściślimy sposobu w jaki chcemy porównywać języki, to
    rozmowa nabierze luźnego charakteru. Czasami z luźniej rozmowy
    też wynikają dobre rzeczy, można się wymienić doświadczeniami.
    Ale też można się pokłócić, bo jeden pisze strkite o języku, a
    drugi o dostępnych narzędziach.

    A kryterium, to np. cechy języka które ułatwiają/umożliwiają
    generowanie wydajnego kodu maszynowego. Albo cechy języka
    ułatwiające tworzenie przejrzystego kodu, bardziej podatnego na
    rozwój - co zapewne dobrze wiesz.


    > > > Moim zdaniem, dużą wadą C++ jest to, że nie daje programiście
    > > > środków do tego, żeby mógł go używać stosownie do swoich
    > > > upodobań -- oczywiście w niektórych kontekstach można by to
    > > > było uznać za zaletę, jednak "w ogólności" wydaje się to raczej
    > > > wadą.
    > > Tutaj pozwolę sobie trochę się nie zgodzić. W C++ generalnie
    > > jest dużo środków i można w nich przebierać. No chyba chodzi o
    > > biblioteki, w przypadku bibliotek trzeba brać albo taką jaka
    > > jest, albo se napisać swoją.
    >
    > Nie chodzi o biblioteki. Chodzi o to, że jako programista
    > nie możesz sobie napisać pętli for(iterator : kolekcja),
    > tylko musisz poczekać, aż przyjdzie Komitet i Ci to zrobi.
    Hmmm Ale w jakim sensie nie możesz? Czy chodzi o to, aby
    język C++ był taki, aby można było przediefiniowywać nie
    tylko operatory, ale i instrukcje? Czy o to, że jak w
    jednej firmie chcą mieć innego ifa, to nie mogą zmienić
    kompilatora? Jeśli chodzi o to pierwsze, to mówią, że
    język C++ ma już za dużo ficzerów ;-) Jeśli chodzi o to
    drugie, to dużym nakładem pracy można to zrobić, ale potem
    stary kod może nie być kompatybilny z nowymi lepszymi
    cechami języka lub bibliotekami. Więc może obecny stan
    rzeczy jest dobry?


    > Tzn. ostatnio odkryłem, że jakieś 10 lat temu się bawiłem w takie
    > rzeczy, i sobie sam zrobiłem (dla gcc)
    >
    > #define for_every(ITERATOR, COLLECTION) \
    > for(typeof(COLLECTION.begin()) ITERATOR = COLLECTION.begin(); \
    > ITERATOR != COLLECTION.end(); ++ITERATOR)
    >
    > ale niewykluczone, że od takich rzeczy głupieją narzędzia w rodzaju IDE.

    Hmmm widocznie mamy inne upodobania co do wyglądu kodu. O Javie często
    słyszałem, i zgadzam się z tym, że kod w Javie jest rozwlekły, ale
    jest bardzo ładny, czytelny, przejrzysty. W C++ zazwyczaj nie zależy mi
    na uniknięciu wypisywania kilku znaków więcej. Niemnie jednak przyznaję
    rację, że pięciokrotnie kwalifikowany dostęp do składowej powoduje, że
    pętla for nie mieści się na szerokość monitora w rozdzielczości 1900 :/
    No ale zrobili w C++11 typ auto, co po pierwsze powoduje że składnia
    jest bardziej zwarta, a po drugie, ta sama pętla działa na wektorze, na
    zbiorze, na hash-mapie, i nie chce mi się wymieniać dalej. Ma to swoje
    zalety, kod jest bardziej podatny na zmiany. Z drugiej strony, moja
    ostatnia implementacja drzewek czerwono czarnych nie zawiera wypasionych
    iteratorów, ta sama pętla nie zadziała na std::vector, ale jest o
    wiele szybsza niż std::set.

    Może takie jest motto języka C++: jak bierzesz ten język, to aplikację
    dostosujesz lepiej do sprzętu, będzie działała szybciej, ale licz się
    z tym, że nakład pracy (licząc: wykonanie, poprawki, eksperymenty z
    wydajnością) będzie znacznie większy niż gdybyś wziął Javę?

    Co do głupienia środowiska, to zgadzam się, że to jest ważne. WIele
    razy nie używałem jakiegoś ficzera języka tylko dlatego, że środowisko
    go nie wspierało, nie wspominając o głupieniu.

    > > Właśnie kolekcje do uporządkowanych
    > > zbiorów mi nie odpowiadają ani w QT, ani w STD, więc napisałem
    > > swoją. Ale to jest wada każdego języka. Chociaż taka Java od
    > > razu była nastawiona na prostotę i standaryzację ogromnej
    > > biblioteki...
    >
    > Dla mnie wygląda tak, jakby C++ był ofiarą swojego procesu
    > standaryzacyjnego, który jest kumulatywny -- ficzery do języka
    > są tylko dodawane, i kompatybilność wsteczna jest świętością.
    > (Z Javą zresztą jest podobnie).
    > Proces standaryzacyjny np. w Haskellu nie miał problemów z tym,
    > żeby eksperymentować i zrywać z różnymi decyzjami projektowymi,
    > które były uważane za błędne. Użytkownicy może trochę na tym
    > ucierpieli, co z pewnością odbiło się na popularności tego systemu,
    > ale wpływ na sam projekt języka miało dobry.

    Nie znam Haskella. W Javie nadal "pisze się gładko". Jakby C++ był
    bardziej podobny do Javy, jakby C++ to była taka Java bez zarządzania
    pamięcią, to... nie wiem co by było. Najgorsza estetyczna masakra
    składniowa w C++ to szablony. (Początkujący mówią też, że w C++ tę
    masakrę powoduje jeszcze nadmiar operatorów, ale obyci z językiem
    mówią, że operatorów nie ma ani za dużo, ani za mało, bo weźmy takiego
    perla.) Ale na szablony podobno nie ma sposobu aby uczynić składnię
    bardziej przejrzystą. Za to kod genetyczny często jest trochę
    bardziej wydajny, no i kompilator sprawdzi typy lepiej, niż w
    przypadku wskaźnika na void.


    > > > Przykładowo, gdybym chciał, żeby wszystkie zmienne w C++
    > > > były domyślnie zadeklarowane jako "const", i tylko te, które
    > > > zasadniczo chcę zmieniać, były zadeklarowane (np. jako "var"),
    > > > C++ (z tego co wiem) nie daje mi możliwości uzyskania takiego
    > > > zachowania.
    > > Ale takiego efektu w żadnym języku nie można uzyskać, o ile
    > > zrozumiałem co masz na myśli. Jeśli zostanie przewidziane
    > > przed pisaniem kodu, to można sprytne define zrobić, jeśli nie,
    > > to w żadnym języku tak się nie da.
    >
    > W Scali masz zasadniczo coś podobnego -- deklarujesz, czy określona
    > zmienna jest "var", czy "val", tzn. czy jest mutowalna czy niemutowalna.
    > W Scheme mógłbym bez problemu przesłonić operator przypisania, żeby
    > sprawdzał, czy dana zmienna posiada deklarację pozwalającą na jej zmianę.
    >
    > > > Podobnie, interfejsy dostarczane przez STL są bardzo dziwne.
    > > > Jest sobie chociażby taki kontener "stack". Jak można się spodziewać,
    > > > stack<T> ma funkcję push(T element), która kładzie element na stosie,
    > > > oraz pop(), która zdejmuje element ze stosu.
    > > Idzie z tym żyć. Ja na tę sprawę mam inny pogląd. W innych językach,
    > > jest mniej możliwości. Naturalne dla innych języków jest to, że
    > > biblioteka zazwyczaj jest taka jaka powinna być w danym języku. A w
    > > C++ jest bardzo dużo środków wyrazu. Zazwyczaj z biblioteką taką jak
    > > STL czy QT można żyć. Problem w tym, że czasami chce potrzeba
    > > biblioteki "skrojonej na miarę" do danego programu. Przy czym
    > > skrojona na miarę oznacza albo wygodę programowania, albo
    > > bezpieczeństwo, albo przejrzysty kod, albo ekstremalną wydajność.
    > > W innych językach nie tylu środków wyrazu, więc inne języki
    > > nie dają okazji do dzielenia włosa na czworo. W Javie nigdy w
    > > życiu nawet bym nie pomyślał o pisaniu swojego kontenera, bo
    > > po co? W C++ zazwyczaj używam swoich drzew, tablic hashujących, itd,
    > > ponieważ (w moim przypadku najczęściej) to skraca czas obliczeń.
    >
    >
    > > > Problem w tym, że funkcja pop() nie zwraca zdejmowanego elementu.
    > > > Uzasadnienie autorów biblioteki jest takie, że w ten sposób można
    > > > uzyskać większą wydajność, i że STL jest projektowany w taki sposób,
    > > > żeby "nie płacić za to, czego się nie używa" -- jednak brak
    > > > ergonomii biblioteki jest w istocie pewną ceną -- tym więszką, gdy
    > > > programiści przyzwyczają się, że zepsute interfejsy to norma.
    > > Zazwyczaj jest bardzo wysoka cena za bardzo małe zwiększenie wydajności.
    > > Stos ma metodę top która zwraca. Można wywołać top a potem pop. I
    > > pewnie w konkretnym przypadku będzie efekt przeciwny do zamierzonego,
    > > pewnie wydajność będzie gorsza dla dwóch wywołań niż dla jednego z
    > > odpowiednim typem zwracanym. A jakby dziedziczyć po stosie i sobie
    > > napisać taką metodę pop? W QT chyba nazywa się taka metoda take.
    >
    > możliwości są różne. projektanci C++ mogliby zrobić "dispatch on return
    > value" (Haskell ma coś takiego), i wówczas stack mógłby dostarczać dwóch
    > implementacji "pop" -- jednej z typem void, a drugi z typem T.
    >
    > > > Jeśli ktoś ma ochotę posłuchać sobie tego rodzaju narzekań, to jest
    > > > ten gość, Scott Meyers, który najpierw pisał dużo książek o C++,
    > > > a później zaczął jeździć po konferencjach, narzekając na dziwność
    > > > interfejsów C++ (sławiąc taką mantrę, żeby projektować interfejsy
    > > > w taki sposób, żeby łatwo było ich używać poprawnie, i żeby trudno
    > > > było ich używać niepoprawnie), i teraz zdaje się zajmuje się
    > > > rozwijaniem języka D. Można sobie go w wolnej chwili obejrzeć
    > > > np. tutaj
    > > Nie, mam dosyć swojego narzekania ;-)
    > >
    > > > Poza tym długie czasy kompilacji i niezrozumiałe komunikaty diagnosyczne
    > > > również są pewną ceną, którą programiści C++ muszą płacić.
    > > Kompilacje można zrównoleglać w make. Komunikaty diagnostyczne...
    > > nie wiem.. zazwyczaj wiem co kompilator do mnie mówi, czasami
    > > tylko muszę chwilę się zastanowić.
    >
    > to musisz spróbować boosta ;]

    Próbowałem skompilować QT na intel Atom. Nie udalo się. Ale na
    klastrze i na dysku SSD pewnie można skompilować całe QT w 5-10 minut.


    > > > W każdym razie jeżeli używasz C++ i jesteś z tego zadowolony,
    > > > to ja nie zamierzam Cię przekonywać, że nie jesteś. Jednak dla mnie
    > > > duży stopień komplikacji tego języka (np. skomplikowana
    > > > składnia i różne założenia utrudniające formułowanie wniosków
    > > > dotyczących programów napisanych w C++) są na tyle poważnym problemem,
    > > > że jeśli nie muszę, raczej staram się z niego nie korzystać.
    > > Dla mnie to co nazywasz komplikacją, jest bogactwem możliwości.
    > > Ale jeśli nie muszę, to też wolę np. Jave, PHP.
    >
    > Raczej miałem na myśli n. to, o czym wspominał Meyers w prezentacji.
    > Że poziom skomplikowania C++ doprowadził do tego, że dające się
    > używać narzędzia do refaktoryzacji kodu dla C++ pojawiły się
    > w środowiskach IDE o dekadę później, niż dla innych języków.
    >
    > Co do owego "bogactwa możliwości" to C++ w istocie daje dużą kontrolę
    > nad tym, co będzie robił komputer w trakcie wykonywania programu.
    > Osobiście nie sądzę, żeby taka kontrola była potrzebna. Raczej
    > wolałbym mieć narzędzie, które samo dobierze optymalne struktury
    > danych do mojego programu, żebym mógł korzystać tylko z jednego
    > prostego interfejsu do kolekcji (interfejsy w STLu wołają o pomstę
    > do nieba). Sądzę, że takie podejście na dłuższą metę miałoby lepszy
    > wpływ na wydajność programów, niż to, co oferuje C++.

    Właśnie nie jestem pewien. Kompilatory już dawno generują lepszy kod
    niż programiści asemblerowi, no chyba że jakiś programista da sobie
    bardzo dużo czasu na mały kawałek kodu, lub znajdzie jakąś naprawdę
    słabą stronę kompilatora. Pomimo tego że kompilatory są takie dobre,
    nadal widzę że programowanie z "podpowiedziami dla kompilatora" daje
    kod nawet 2-3 razy bardziej wydajny. Cały czas widzę, że pętelka
    na wskaźnikach lepiej działa niż na iteratorach z kolekcji. Nie
    wiem dlaczego kompilator po prostu nie "rzutuje" iteratorów
    na wskaźniki, może to w ogóle nie jest możliwe, może w ten sposób
    czasami generowałby błędny kod wynikowy? Czasami nawet widzę, że
    for( int i=0 ; i<size ; i++) operacje( tablica[i] );
    jest gorszy od kodu:
    for( int *i = tablica ; i != tablica+size ; i++ ) operacje( *i );

    Dlaczego kompilator jednego na drugie nie zamieni sam, to
    nie wiem. Może to co proponujesz jest w ogóle niemożliwe, a
    konkretnie, może niemożliwe jest generowanie wydajnego kodu na
    podstawie jednego prostego interfejsu?

    Pozdrawiam

Podziel się

Poleć ten post znajomemu poleć

Wydrukuj ten post drukuj


Następne wpisy z tego wątku

Najnowsze wątki z tej grupy


Najnowsze wątki

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: