Article View: pl.comp.objects
Article #15288Re: =?ISO-8859-2?Q?Warto¶ci?= i obiekty
From: Sektor van Skijl
Date: Mon, 12 Mar 2007 21:28
Date: Mon, 12 Mar 2007 21:28
250 lines
11777 bytes
11777 bytes
Dnia Sun, 11 Mar 2007 23:15:23 +0100, Marcin 'Qrczak' Kowalczyk skrobie: > Dnia 11-03-2007, nie o godzinie 15:29 +0000, Sektor van Skijlen > napisa³(a): > > Obojêtnie, jak mamy zaimplementowany sposób porównania warto¶ci i to¿samo¶ci, > > obojêtnie te¿, czy typ jest warto¶ciowy, czy obiektowy, dla ka¿dego typu > > istnieje tylko i wy³±cznie jeden sensowny sposób porównania. > To jest prawie prawda. > Po pierwsze, co t³umaczê od paru postów, zdarza siê, ¿e typ ma > niejednoznaczny charakter i czasem jest u¿ywany w roli typu > warto¶ciowego, a czasem typu z to¿samo¶ci±. Zgadzam siê, ¿e to > jest k³opotliwe, ale to bywa faktem. A ja równie¿ t³umaczê od paru postów, ¿e na tak± okoliczno¶æ powinny zostaæ stworzone osobne typy statyczne. To prawda, ¿e mo¿esz u¿ywaæ tego samego typu jêzyka jako logicznego typu warto¶ciowego i niewarto¶ciowego, tyle ¿e to sprowadza jêzyk do niskopoziomowego rozwi±zania, w którym tego samego typu mo¿na u¿ywaæ do przechowywania logicznie ró¿nych rzeczy. Je¶li mamy jêzyk taki, jak C, to rozumiem, ¿e za bardzo nie mamy wyj¶cia. Dlatego tam u¿ywa siê tego samego typu - tablicy char - jako ³añcucha tekstowego i jako tablicy o elementach typu char. Natomiast dla jêzyka wysokopoziomowego to po prostu wstyd, ¿eby nie zrobiæ tego na osobnych typach. Rozumieli to zarówno twórcy C++, jak i Javy, i C# (nb. Tcl-a te¿, dlatego te¿ tam trzeba stosowaæ pewne myki, ¿eby móc przekszta³ciæ napis na listê znaków). Najwyra¼niej nie zrozumieli tego twórcy jêzyków Haskell i D. Je¶li taki typ ma osobne specyfiki dla ró¿nych przypadków, to i tak przynajmniej jednej specyfiki zawsze trzyma siê jeden obiekt (czyli nie zmienia siê nagle z typu obiektowego w warto¶ciowy w trakcie dzia³ania). Je¶li tak, to mo¿na u¿yæ osobnych definicji typów dla ka¿dego obiektu u¿ywaj±cego okre¶lonej specyfiki. > Po drugie czasem (rzadko) chcemy porównaæ to¿samo¶æ obiektów typów > warto¶ciowych dla niskopoziomowych optymalizacji. Rozumiem - ale taka niskopoziomowa optymalizacja powinna byæ operacj± szczególnego rodzaju, byæ dostêpna tylko dla operacji bezpo¶rednio operuj±cych na takim typie (lub specjalnie do tego dozwolonych), a przynajmniej powinna byæ wykonywalna za pomoc± osobnych funkcji porównania. Nie chodzi mi przecie¿ o to, ¿eby ca³kowicie zabroniæ mo¿liwo¶ci sprawdzania to¿samo¶ci obiektów typów warto¶ciowych. Chodzi o to, ¿eby ka¿dy typ posiada³ operator porównania, który porównuje w sposób adekwatny do rodzaju typu. > Po trzecie s± relacje, które - je¶li siê uprzeæ - mo¿na nazwaæ inaczej > ni¿ równo¶æ, ale potocznie s± to jakie¶ odmiany równo¶ci. Na przyk³ad > sprawdzenie, czy dwa ci±gi maj± równe odpowiadaj±ce sobie elementy, bez > sprawdzenia, czy te ci±gi w ogóle s± tego samego typu. Mo¿na, owszem, ale to nie jest porównanie warto¶ci, tylko porównanie zawarto¶ci zbiorników (operacja specyficzna dla zbiornika, bo nie da siê takiej operacji uogólniæ na "po prostu obiekt"). Powinna byæ zatem dozwolona, ale jako specyficzna operacja, a nie porównanie. Dlaczego w C++ zbiorniki nie posiadaj± zdefiniowanego operatora porównania, tylko tego typu porównania wykonuje siê algorytmami equal i mismatch? > Po czwarte tradycyjna równo¶æ zmiennoprzecinkowa nie jest relacj± > równowa¿no¶ci (z powodu NaN) ani nie jest zachowywana przez operacje > arytmetyczne (z powodu -0.0). Jest wiêc powód, ¿eby traktowaæ j± jako > osobn± operacjê ni¿ podstawowa równo¶æ. Nie no równo¶æ warto¶ci zmiennoprzecinkowych to jest ju¿ osobna bajka. Jest to drobny wy³om w systemie typów warto¶ciowych/obiektowych. Problem jest w³a¶nie z tym NaN, bo gdyby nie to, to jeszcze na upartego zachowa³aby siê zasada, ¿e warto¶æ a skopiowana z b jest równa b. Nie wiem w tym momencie, czy typy zmiennoprzecinkowe mo¿na traktowaæ jak warto¶ci. Dla mnie najsensowniejszym rozwi±zaniem by³oby zdefiniowanie jako operatora porównania porównania "wewnêtrznego", czyli z zachowaniem zale¿no¶ci miêdzy przypisaniem a porównaniem. Natomiast osobno do tego nale¿a³oby stworzyæ funkcjê porównuj±c± dwie liczby zmiennoprzecinkowe z zadanym epsilonem. Ci, co wymy¶lili ten numer z NaN, najwyra¼niej nie zdawali sobie sprawy z tego, jakie zamieszanie tym zrobi±. Zastanawiam siê nawet, czy nie by³oby znacznie sensowniejsze uznanie liczb zmiennoprzecinkowych za typy niewarto¶ciowe. To¿samo¶æ przez obiekt lepiej by siê dla nich sprawdza³a. > A to jeszcze nie wszystko. No to co jeszcze? Przecie¿ mo¿na by do tej wyliczanki do³o¿yæ stringa, którego mo¿esz porównywaæ np. bez case'a, z pominiêciem znaków kontrolnych itp. Powtarzam: nie zaprzeczam, ¿e powinny byæ zdefiniowane ró¿ne metody porównywania dostêpne dla danego obiektu, ale powinna byæ zawsze JEDNA operacja najw³a¶ciwszego porównania zdefiniowana dla danego typu. > > > w innym jêzyku obiekt jest klonowany (czym¶ w rodzaju metody Clone). > > > > Tak - pod warunkiem, ¿e pozwala siê na klonowanie obiektów. > Zawsze "siê pozwala", bo nie ma czego zabraniaæ - to jest operacja jak > ka¿da inna, je¶li siê nie oczekuje, ¿e bêdzie automatycznie dostêpna > dla dowolnego typu. Niestety, bzdury opowiadasz. Istnieje co¶ takiego, jak unikalne warto¶ci - warto¶æ jednego pola, która w ka¿dym obiekcie musi byæ inna. Czêsto s± to nawet obiekty generowane na rzecz innych, istniej±cych obiektów. Efekt jest taki, ¿e ¿eby¶ móg³ poprawnie tworzyæ obiekt przez klonowanie, to musia³by¶ podczas klonowania uwzglêdniæ fakt, ¿e warto¶ci niektórych jego pól nie mog± byæ skopiowane, tylko musz± zostaæ wygenerowane na nowo. Czy taki obiekt bêdzie jeszcze klonem? Klonowanie zreszt± to nie jest taka prosta sprawa. Pamiêtam, jak w mudzie by³a funkcja klonuj±ca moba. Trzeba by³o tam uwzglêdniæ mnóstwo rzeczy: je¶li postaæ by³a wierzchowcem, to nowa postaæ by³a "nieosiod³ana". Je¶li postaæ dosiada³a wierzchowca, to nowa postaæ by³a tworzona na ziemi. Je¶li postaæ zajmowa³a mebel, to nowa postaæ musia³a równie¿ staæ obok (tzn. tak by³o po wniesieniu mojej poprawki do buga, bo poprzednio nowa postaæ by³a tworzona na tym samym meblu - autor najwyra¼niej zapomnia³, ¿e meble maj± te¿ swoj± pojemno¶æ i niekoniecznie dwie postacie bêd± mog³y siedzieæ na jednym krze¶le). Kolejnym problemem jest to, czy klonowanie postaci powinno poci±gaæ za sob± klonowanie posiadanych przez ni± przedmiotów, czy te¿ nowa postaæ ma byæ stworzona "na golasa" (nie pamiêtam ju¿, jak to rozwi±zano). Gdyby poci±gaæ za sob± tworzenie przedmiotów, to dodatkowo niektóre mudy maj± wprowadzon± ekonomiê - czyli takie sklonowanie poci±ga za sob± dodatkowo deflacjê. I tak mo¿na by wyliczaæ bez koñca. Co wiêcej, czêsto ¼ród³em danych dla tworzenia nowego obiektu s± jakie¶ specyficzne dane, które trzeba odpowiednio pobraæ (byæ mo¿e zarejestrowaæ, skojarzyæ z czym¶). W takim przypadku nie da siê stworzyæ obiektu na podstawie danych z innego obiektu, bo dane, które posiada ten hipotetyczny obiekt ¼ród³owy s± przygotowane tylko i wy³±cznie dla niego. Jak ty sobie wyobra¿asz np. sklonowanie obiektu oznaczaj±cego plik, gniazdo, sesjê, czy zbiornik w³a¶cicielski (zbiornik z dynamicznie tworzonymi obiektami, które zbiornik posiada na w³asno¶æ, tzn. usuwa je razem ze sob±)? Wiêc co oznacza "zawsze siê pozwala"? Nie mówi±c o tym, ¿e w dalszej czê¶ci zdania twierdzisz, ¿e mo¿na zabroniæ, wiêc nie rozumiem... > > > b) Typowy przyk³ad: liczba. > > > > > Zmienna wskazuje na niezmienialny obiekt innego jêzyka reprezentuj±cy > > > bie¿±cy stan obiektu C++. Metodom C++, które zmienia³y stan obiektu, > > > odpowiadaj± operacje zwracaj±ce nowy obiekt, który jest przypisywany > > > z powrotem tej zmiennej. > > > > Pod warunkiem, ¿e mamy mo¿liwo¶æ "zakodowania" przypisania do zmiennej > > trzymaj±cej ten niezmienialny obiekt. > Jasne; mia³em na my¶li imperatywn±, przypisywaln± zmienn±. S³owo > "zmienna" jest niestety wieloznaczne i czê¶æ jêzyków programowania, > tak jak matematyka, u¿ywa go w znaczeniu lokalnej nazwy jakiej¶ > warto¶ci, niekoniecznie zmieniaj±cej siê w czasie. Wiem, o co chodzi ze zmienn± w obu przypadkach. Problem tylko w tym, czy jêzyk pozwala zrobiæ jaki¶ trik, który zakoduje operacjê modyfikuj±c± obiekt tak, ¿eby wygl±da³a jak modyfikuj±ca, a w rzeczywisto¶ci bêdzie tworzyæ now± kopiê obiektu. > > > Tam, gdzie w C++ obiekt jest przekazywany przez warto¶æ, w innym > > > jêzyku przekazywana jest bie¿±ca warto¶æ zmiennej. Tam, gdzie > > > w C++ obiekt jest przekazywany przez referencjê, w innym jêzyku > > > przekazywana jest referencja na zmienn±. > > > > A co z porównywaniem? > Nie rozumiem pytania. Dla obiektów tej kategorii porównanie jest do¶æ > podstawow± operacj±, zdefiniowan± zale¿nie od typu. No i normalnie jest > oferowane, najczê¶ciej w formie wspólnego interfejsu dla ró¿nych typów. No w³a¶nie. A co z implementacj±? > > Nie, Qrczak. String to nie jest tablica znaków - jak ju¿ siê czepiamy > > skrzywionego my¶lenia, to i ja siê poczepiam: twoje my¶lenie jest skrzywione > > przez jêzyki, w których string jest reprezentowany przez listê znaków (jak np. > > Haskell). > Etam. W C string te¿ jest w zasadzie tablic± znaków, Ale Haskel, w odró¿nieniu od C, nie jest jêzykiem niskopoziomowym, z siermiê¿nymi w³a¶ciwo¶ciami umo¿liwiaj±cymi ledwie co zrobienie struktur, ¿eby jako¶ operowaæ w³asnymi typami. > a w C++ ma³o do > tego brakuje. Nawet je¶li mo¿na trochê ponaci±gaæ fakty, ¿eby to stwierdziæ, to nie zmienia faktu, ¿e jednak zrobiono do tego osobne typy. > Szablon basic_string jest nawet parametryzowany typem > znaku. Complex te¿ jest parametryzowany typem warto¶ci zmiennoprzecinkowej, i co z tego? > Ten typ ma trochê wiêcej wymagañ ni¿ typ elementu wektora, ale > poza tym ró¿nica jest ma³a. Ró¿nica jest zasadnicza. Gdyby nie to, nikt by siê nie sili³ na robienie osobnego typu dla stringa i vectora. Popatrz na jêzyk D - tam nie ma osobnego typu dla stringa, a string jest jednocze¶nie tablic± znaków (czyli, inaczej mówi±c, tablica znaków posiada ca³± funkcjonalno¶æ potrzebn± dla stringa). > W Kogucie, podobnie jak w Pythonie i Perlu, w ogóle nie ma osobnego > typu znakowego. Kiedy znak jest materializowany w programie, jest > reprezentowany przez string d³ugo¶ci 1. W Tcl-u te¿ tak jest, wiêc to chyba nic niezwyk³ego jak na jêzyk skryptowy. > Na pewno wiêc string jako > tablica znaków nie jest moim skrzywieniem. Rozumiem, ¿e musisz siê jako¶ broniæ ;). Ale na powa¿nie - fakt, ¿e w wielu jêzykach string jest to¿samy z tablic± znaków, uwa¿am za pomy³kê. Tablica znaków jest czym¶ koncepcyjnie innym od stringa, a je¶li co¶ jest koncepcyjnie inne, to system typów powinien pozwalaæ na wyra¿enie tego osobnym typem. Jêzyk, który tego nie ma, ma "nalecia³o¶ci asemblerowe". > > > Przyk³ady jêzyków, które maj± wy³±cznie zmienialne stringi mimo > > > paradygmatu, który do tego nie pasuje: Lisp, Scheme, OCaml, Ruby > > > (czasem s± zmienialne ³±cznie ze zmian± d³ugo¶ci, a czasem nie). > > > > Tzn. jak? Musisz jawnie skopiowaæ string, je¶li chcesz, ¿eby ¼ród³owy siê nie > > zmieni³? > Tak. Nie jest to a¿ tak b³êdogenne, jak mog³oby siê wydawaæ, je¶li siê > stosuje konwencjê, ¿e zmienia siê tylko te stringi, które siê przed > chwil± utworzy³o. Ale¿ jaja sobie robisz. Nie jest to a¿ tak b³êdogenne, je¶li siê pamiêta. Nie zapominaj, ¿e bardzo czêsto u¿ywasz tego argumentu przeciwko C++. > Czyli string jest w zasadzie traktowany jako typ > niezmienialny, imperatywne jest tylko jego tworzenie. Bardzo dobrze - ale niech w takim razie jêzyk sam zadba o to, ¿eby tego stringa nie da³o siê zmieniæ po jego utworzeniu. -- // _ ___ 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"
Message-ID:
<et4gmk$9ru$1@kujawiak.man.lodz.pl>
Path:
polish.pugleaf.net!archive.newsdeef.eu!mbox2nntp-pl.comp.objects.mbox.gz!number1.nntp.dca.giganews.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed00.sul.t-online.de!t-online.de!news.nask.pl!news.nask.org.pl!newsfeed.pionier.net.pl!news.man.lodz.pl!not-for-mail
References:
<pl-comp-objects-faq-1-1166202604@ict.pwr.wroc.pl> <esd1k1$9bp$1@bandai.magma-net.pl> <esemb6$2r3$1@kujawiak.man.lodz.pl> <eses6u$8fm$1@inews.gazeta.pl> <esf3am$r52$1@bandai.magma-net.pl> <esfg25$b2m$1@kujawiak.man.lodz.pl> <1173137761.17765.52.camel@qrnik> <esmtmk$ii1$1@kujawiak.man.lodz.pl> <1173310324.15622.77.camel@qrnik> <esuufm$jfv$1@kujawiak.man.lodz.pl> <1173568302.9234.25.camel@qrnik> <et178b$f2o$1@kujawiak.man.lodz.pl> <1173651323.19503.18.camel@qrnik>