hilpers


  hilpers > comp.lang.* > comp.lang.c

 #16  
27.06.2008, 19:03
Seweryn Habdank-Wojewódzki
Witam

> Odpowiedź jest prosta. Po prostu się nie da. Trudno mi sobie
> nawet takie coś wyobrazić.


E tam. Że odrazu sie nie da. Kwestia ceny.

virtual boost::any do_foo (boost::any);

lub pobierajac DynamicAny i zwracajac rowniez.

virtual DynamicAny do_foo (DynamicAny);

To jest totalna wolna amerykanka. Oczywiscie uznaje to jako pewna
luke w projekcie, ale są pewne wyjatki. Np. jakis parser moze zwracac
dialbli wiedza co. I tam mozna zaimplementowac kontekstowe wolanie

type value = cast<type>(foo()); Szczegolnie to dotyczy typow
prostych,
ktorych liczba jest ograniczona jednak sa na tyle roznorakie,
ze zrobienie dla nich klasy bazowej nie jest eleganckie.

>Każde nowe "zrób ogólne foo()"
> wymagałoby zmiany we wszystkich klasach pochodnych. To to
> już całkowicie łamie zasadę open-close.


Tak.

Pozdrawiam,
Seweryn Habdank-Wojewódzki.
 #17  
28.06.2008, 22:08
Bronek Kozicki
Krzysiek Kowaliczek <this> wrote:
> void foo ()
> {
> const Expression& e = getExpression ();
> switch ( e )
> {
> case BinaryExpression x:
> break;
> case UnaryExpression x:
> break;
> case NumberExpression x:
> break;
> };
> }


const Expression& e = getExpression ();

const std::typeinfo& te = typeid(e);
if (te == typeid(BinaryExpression))
;
else if (te == typeid(UnaryExpression))
;
else if (te == typeid(NumberExpression))
;

nieeleganckie, ale glównie dlatego ze tu powinno sie zastosowac zwykly
polimorfizm.


B.
 #18  
28.06.2008, 22:47
A.L.
On Thu, 26 Jun 2008 23:54:01 -0700 (PDT), Seweryn Habdank-Wojewódzki
<habdank> wrote:

[..]
>DynamicAny any("42");
>int i = any; // i == 42
>any = 65536;
>std::string s = any; // s == "65536"
>
>// mozna tez dodac jeszcze takie cos:
>char c = any; // too big, throws RangeException
>
>Tego powyzej nie umiem napisac w Pythonie jak ktos potrafi to prosze o
>uzupelnienie.


Co swiadczy dobrze o Pythonie

A.L.
 #19  
30.06.2008, 06:58
Artur M. Piwko
In the darkest hour on Fri, 27 Jun 2008 10:47:07 -0700 (PDT),
Seweryn Habdank-Wojewódzki <habdank> screamed:
>
>> > c = chr(any) // rowniez sypnie wyjatkiem
>> >>> c = unichr(any)
>> >>> c

>>
>> u'\uffff'

>
> Tak. Ale to, ze tamto powyzej sypie wyjatkiem jest bardzo dobre.
> Python ma sypnac bledem, bo glupio robie.
>


To też wcale tak nie twierdziłem. ;)
 #20  
30.06.2008, 08:31
Krzysiek Kowaliczek
Bronek Kozicki wrote:
> const Expression& e = getExpression ();
>
> const std::typeinfo& te = typeid(e);
> if (te == typeid(BinaryExpression))
> ;
> else if (te == typeid(UnaryExpression))
> ;
> else if (te == typeid(NumberExpression))
> ;
>


No wlaśnie, to tylko pólśrodki. Chcialbym dostac ostrzezenie
lub bląd jezeli dodam nową podklase Expression.
Przykladowo, mam taki oto kod w ocamlu:

type expression =
| BinaryExpression
| UnaryExpression
| NumberExpression

let process expr =
match expr with
| BinaryExpression-> 1
| UnaryExpression-> 2
| NumberExpression-> 2

let _ =
print_int ( process BinaryExpression )

Jezeli rozbuduje typ expression o powiedzmy StringExpression
to przy kompilacji dostane ostrzezenie:
File "test.ml", line 8, characters 2-94:
Warning P: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
StringExpression

Najbardziej podoba mi sie wersja dla Scali:
http://www.scala-lang.org/node/107

Podsumowywując: bylem ciekaw jak sobie radzicie w podobnych
przypadkach. Ja chetnie zobaczylbym konstrukcje znane z
jezyków funkcjonalnych, w C++. Obecnie bardziej sklaniam sie
ku rozwiązaniu jakie zaproponowal Witek ( plus ewentualna
statyczna asercja ), zamiast wzorca wizytor.

Pozdrawiam
KK
 #21  
30.06.2008, 21:49
Seweryn Habdank-Wojewódzki
Witam

> >// mozna tez dodac jeszcze takie cos:
> >char c = any; // too big, throws RangeException

>
> >Tego powyzej nie umiem napisac w Pythonie jak ktos potrafi to prosze o
> >uzupelnienie.

>
> Co swiadczy dobrze o Pythonie


Drogi Panie A.L. spóźnił się, Pan, bo już pojawił się mój post z
uzupełnieniem.
Nie wiem, co dobrze świadczy o pythonie, ale to coś już zniknęło,
jeżeli
wynikało tylko z faktu, że przez 15 minut nie umiałem tego napisać.
To już sie stało. Przykro mi. Już nie ma tego czegoś co dobrze
świadczy o Pythonie.

Są inne rzeczy, ale nie ta,

Pozdrawiam,
Seweryn Habdank-Wojewódzki.
 #22  
01.07.2008, 08:32
Seweryn Habdank-Wojewódzki
Witam

> No właśnie, to tylko półśrodki. Chciałbym dostać ostrzeżenie
> lub błąd jeżeli dodam nową podklasę Expression.


Czemu nie uzyc dynamic_cast?
dynamic_cast jak sobie nie radzi rzuca wyjatek.

> Najbardziej podoba mi się wersja dla Scali:[..]


A tak a propos Scali. Jaka jest jej wartosc dodana tego jezyka
wzgledem Pythona?

Pozdrawiam,
Seweryn Habdank-Wojewodzki.
 #23  
01.07.2008, 09:24
Krzysiek Kowaliczek
Seweryn Habdank-Wojewódzki wrote:

> Czemu nie uzyc dynamic_cast?
> dynamic_cast jak sobie nie radzi rzuca wyjatek.


Nie przeczytałeś dokładnie: chcę mieć taką informację w
trakcie kompilacji. Skoro mam język statycznie typizowany,
to chciałbym w pełni to wykorzystać.

> A tak a propos Scali. Jaka jest jej wartosc dodana tego jezyka
> wzgledem Pythona?
>


Scala to nie jest Python inaczej. Scala jest statycznie
typizowana, więc nie ma sensu bezpośrednio ich porównywać.

Pozdrawiam
KK
 #24  
01.07.2008, 15:56
Seweryn Habdank-Wojewódzki
Witam

> Nie przeczytałeś dokładnie: chcę mieć taką informację w
> trakcie kompilacji. Skoro mam język statycznie typizowany,
> to chciałbym w pełni to wykorzystać.


Hmm... no to static_cast? Ewentualnie w brzydkiej wersji
reinterpret_cast jesli jestes pewien, ze to co rzutujesz to jest
to co chcesz miec.

> > A tak a propos Scali. Jaka jest jej wartosc dodana tego jezyka
> > wzgledem Pythona?

>
> Scala to nie jest Python inaczej.


Skadnia jest jakby rrznieta z Pythona.

> Scala jest statycznie
> typizowana, więc nie ma sensu bezpośrednio ich porównywać.


Hmm... na tej grupie sa spece od porownywania:
C++ i Lispa, C++ i Pythona, C++ i VB itd.

Wiec czemu mielibysmy oszczedzic Scale? :-)

A poza statyczna typizacja czy jest cos super?

Pozdrawiam,
Seweryn Habdank-Wojewodzki.
 #25  
01.07.2008, 17:04
Marcin ‘Qrczak’ Kowalczyk
On 1 Lip, 16:56, Seweryn Habdank-Wojewódzki <habd> wrote:

> > Nie przeczytałeś dokładnie: chcę mieć taką informację w
> > trakcie kompilacji. Skoro mam język statycznie typizowany,
> > to chciałbym w pełni to wykorzystać.

>
> Hmm... no to static_cast? Ewentualnie w brzydkiej wersji
> reinterpret_cast jesli jestes pewien, ze to co rzutujesz to jest
> to co chcesz miec.


Informację w czasie kompilacji, czyli komunikat kompilatora, jeśli nie
wszystkie przypadki zostały obsłużone. static_cast w niczym tu nie
pomoże, a tym bardziej reinterpret_cast (który w ogóle nie zadziała
przy wielodziedziczeniu, a i przy pojedynczym dziedziczeniu nie chce
mi się sprawdzać, czy musi).
 #26  
01.07.2008, 18:30
Seweryn Habdank-Wojewódzki
Witam

> Nie przeczytałeś dokładnie: chcę mieć taką informację w
> trakcie kompilacji. Skoro mam język statycznie typizowany,
> to chciałbym w pełni to wykorzystać.


Ponizej zamieszczam pewien kod. Zawsze klasa dziedzicona z base
musi miec metode do_get_class_id. A zatem jak tego nie napiszesz
kompilator
obrzuci Cie błotem. Co wiecej klasa Derived_3 jest celowo
zakomentowana.
Bo tez sie nie kompiluje -- specjalnie nadalem jej ID, ktore pokrywa
sie z 2.
Wchodzac do switcha mozesz wziac ID klasy, jest ono unikalne dzieki
spomnianemu ficzerowi, bo nie unikalne ID nie kompiluje sie.

Jesli to nie jest to o co Ci chodzi to nie rozumiem o co w ogole
chodzi :-).

Pozdrawiam,
Seweryn Habdank-Wojewodzki.

#include <iostream>
#include <memory>

using namespace std;

template <int id>
class Class_ID {
public:
enum {ID = id};
};

class Base {
public:
typedef Class_ID<0> CID;
Base() {}

virtual ~Base(){}

int const get_class_id() const {
return do_get_class_id();
}

private:
virtual int const do_get_class_id () const {
return CID::ID;
}
};

class Derived_1 : public Base {
public:
typedef Class_ID<1> CID;
Derived_1() {}
virtual ~Derived_1(){}

private:
virtual int const do_get_class_id () const {
return CID::ID;
}
};

class Derived_2 : public Base {
public:
typedef Class_ID<2> CID;
Derived_2() {}
virtual ~Derived_2(){}

private:
virtual int const do_get_class_id () const {
return CID::ID;
}
};

/*class Derived_3 : public Base {
public:
typedef Class_ID<2> CID;
Derived_3() {}
virtual ~Derived_3(){}

private:
virtual int const do_get_class_id () const {
return CID::ID;
}
};*/

void fun (Base & b)
{
switch(b.get_class_id())
{
case Base::CID::ID:
cout << "0\n"; break;
case Derived_1::CID::ID:
cout << "1\n"; break;
case Derived_2::CID::ID:
cout << "2\n"; break;
//case Derived_3::CID::ID:
//cout << "3\n"; break; }
}

int main()
{
typedef auto_ptr <Base> Base_ptr;
Base_ptr p (new Base);
fun (*p);
p = Base_ptr (new Derived_1);
fun (*p);
p = Base_ptr (new Derived_2);
fun (*p);
}
 #27  
02.07.2008, 08:40
Krzysiek Kowaliczek
Seweryn Habdank-Wojewódzki wrote:
> Ponizej zamieszczam pewien kod. Zawsze klasa dziedzicona z base
> musi miec metode do_get_class_id. A zatem jak tego nie napiszesz
> kompilator
> obrzuci Cie błotem. Co wiecej klasa Derived_3 jest celowo
> zakomentowana.
> Bo tez sie nie kompiluje -- specjalnie nadalem jej ID, ktore pokrywa
> sie z 2.
> Wchodzac do switcha mozesz wziac ID klasy, jest ono unikalne dzieki
> spomnianemu ficzerowi, bo nie unikalne ID nie kompiluje sie.
>


Ech, Qrczak Ci przecież już napisał. Nie chodzi mi o
możliwość nadawania unikalnego identyfikatora bo i po co.
Chodzi mi o to, że jak dodam Derived_3, ale nie obsłużę jej
w kodzie to chciałbym dostać błąd:
// dodałem nową klasę
class Derived_3 : public Base
....

dalej w kodzie mam:
void fun (Base & b)
{
switch(b.get_class_id())
{
case Derived_1:
cout << "1\n"; break;
case Derived_2:
cout << "2\n"; break;
// <-- tutaj powinno być case Derived_3:
}
}
// dalej jeszcza x podobnych przypadków jak w fun

I właśnie w funkcji fun chciałbym, aby kompilator
poczęstował mnie błędem.
Podobnie jak Maciek (*) zastanawiałem się jak obsłużyć takie
przypadki. I wyszło mi, że najlepszy byłby sposób znany np.
z ocaml ( chociaż tam dopasowanie do wzorca ma dużo, dużo
większe możliwości niż prosty switch z c++ ). Zastanawiałem
się czy inni grupowicze, odczuwali potrzebę takiej
konstrukcji w C++. Ewentualnie ktoś coś może słyszał, że
były takie propozycje w przyszłej wersji standardu. Ale
wychodzi na to, że swich + enum, ewentualnie wzorzec wizytor
wszystkim wystarcza :), ponieważ nie było żadnych głosów
poparcia.

(*) http://www.inspirel.com/articles/Visitor_Revisited.html

Pozdrawiam
KK
 #28  
02.07.2008, 08:49
Krzysiek Kowaliczek
Seweryn Habdank-Wojewódzki wrote:
> Hmm... no to static_cast? Ewentualnie w brzydkiej wersji
> reinterpret_cast jesli jestes pewien, ze to co rzutujesz to jest
> to co chcesz miec.
>


Patrz odpowiedź Qrczaka.

> Skadnia jest jakby rrznieta z Pythona.
>


Żarty chyba sobie stroisz. Ja tam podobieństwa nie widzę.

> Hmm... na tej grupie sa spece od porownywania:
> C++ i Lispa, C++ i Pythona, C++ i VB itd.
>
> Wiec czemu mielibysmy oszczedzic Scale? :-)



Z tego co napisałeś, zrozumiałem, że Scala to klon Pythona.
Tak jak już pisałem Scala to nie jest Python zrobiony
lepiej, więc w ten sposób nie ma sensu ich porównywać.

>
> A poza statyczna typizacja czy jest cos super?
>


Scala to scyzoryk szwajcarski. Każdy znajdzie tutaj coś dla
siebie, łączy zalety programowania obiektowego i
funkcjonalnego (
). Poza tym to jedyny sensowny język na JavaVM ;).

Pozdrawiam
KK
 #29  
02.07.2008, 19:36
Seweryn Habdank-Wojewodzki
Witam

> Żarty chyba sobie stroisz. Ja tam podobieństwa nie widzę.


Kwestia miary :-).

> Z tego co napisałeś, zrozumiałem, że Scala to klon Pythona.


Klon, to nie, ale idea jest mocno zaczerpnięta z Pythona.

> Tak jak już pisałem Scala to nie jest Python zrobiony
> lepiej, więc w ten sposób nie ma sensu ich porównywać.


Hmm... a ja myślałem, że można, tak samo jak można porownywać
C++ do Ocalma.

> Scala to scyzoryk szwajcarski.


Nie widze tego tak rozowo. Jakby tak było nikt by nie pisal
ani w Javie ani w J(P)ythonie. Oczywiscie nie zabraniam nikomu sie
bawic w pisanie jakiegokolwiek jezyka. Moze nawet Scala bedzie
miala wiecej userow niz kazdy dedykowany jezyk, ale osobiscie
nie widze, aby byl lepszy od Pythona. Nawet jesli jest taki sam,
pomijając typizację, to naprawdę nie widze silnej przewagi.

Rozumiem, że Scala probuje naprawic bledy w Javie
jako takiej, ale to IMHO za malo. Tym bardziej, żę kod z Pythona
przenosi się na Jythona, a zatem jest mocno nie zalezy zarowno
od systemu jak i od VM. Scala, coz, tylko JVM.

> Poza tym to jedyny sensowny język na JavaVM ;).


Kiedys uczestniczylem w dyskusji, w ktorej to samo mowiono
o Groovym. Groovy ma skladnie rowniez podobna do Pythona.
Jest dynamiczny. Groovy jest u mnie w rankingu jeszcze dalej
niz scala.

Pozdrawiam,
Seweryn Habdank-Wojewódzki.
 #30  
02.07.2008, 19:37
Seweryn Habdank-Wojewodzki
Witam

> Chodzi mi o to, że jak dodam Derived_3, ale nie obsłużę jej
> w kodzie to chciałbym dostać błąd:
> // dodałem nową klasę
> class Derived_3 : public Base


Nie bardzo widze, aby to miało globalny sens.

Pomyśl. Jest aplikacja i masz jakąś klasę bazową A.
Ludzie obługują tylko A, B i C w 1000 miejscach w kodzie.
B i C dziedziczą po A. Teraz dopisuję klasę D w jakimś
odległym miejscu. I co? Są problemy.

1. Skąd kompilator ma wiedzieć ze w jakims moim headerze
niekoniecznie inkludowanym jest klasa D.

2. Nawet jesli includuje klasę D, to dlaczego projekt
ma sie nie kompilowac w 1000 miejscach, bo ja sobie
napisalem klasę D.

Pomysl tak:
masz 10 koderow kazdy co tydzien dziedziczy jakas klase z jakiejs
innej (takiej powodujacej błędy).
Sama obecnosc nowej klasy bedzie wywalac kompilacje.
Tego nigdy nie naprawisz. Musisz miec mozliwosc, aby
one były obecne w kodzie ale nie dzialajace.
Co wiecej masz wersję release
w ktorej za nic w swiecie nie chcesz wlaczac klas nowych.
One moga byc tylko w wersji debug lub test.
Zatem potrzebujesz miec mechanizm rejestracji klas uzytkowych w zaleznosci
od wersji. Poza tym wcale nie jest powiedziane, ze w kazdym z
1000 miejsc, w ktorych masz "switch", jest tak naprawdę gotowy przyjac nowa
klase.
Czasami chcesz obsłuzyc tylko te, ktore sa wymienione zadne inne.
Więc taki automat raczej by mi szkodzil niz pomagał.

3. Jesli zatem musisz klase rejestrowac w czasie kompilacji, to czemu
nie uzyc, tego co język OFERUJE, np. listy typów,
szerzej o tym w kontekście wizytatora pisze Alexandrescu.
Moze jego rozwiazanie nie jest idealne, ale
jak ktos bedzie mial dokladna specyfikacje o co mu chodzi,
to moze sobie to podejscie poprawic na swoja modle.

W każdym razie ja jestem przeciwny wprowdzania automatow,
ktore moga mi szkodzic.
Jesli bede chcial miec blad to poprosze o to, ale nie domyslnie.

> dalej w kodzie mam:

...
> case Derived_2:
> cout << "2\n"; break;
> // <-- tutaj powinno być case Derived_3:


Po co? Skąd wiesz, że ja w ogole chcę obsłużyć w tym miesjcu nową klasę.
Może nie jestem gotowy. Może NIGDY tego nie zrobię.

Pomyśl masz wzorzec strategia zawierający jakies algorytmy. Ale one są w
ogólnej bibliotece. A ja chcę miec tylko 2 znich (np. z 10). Dlaczego mam
produkować 8 pustych case takich:

case Derived_3:
break;
case Derived_4:
break;
case Derived_4:
break;
case Derived_5:
break;
...
case Derived_8:
break;

Hmm? Nie widzę sensu.

> I właśnie w funkcji fun chciałbym, aby kompilator
> poczęstował mnie błędem.


Jeszcze raz mówię, pomyśl globalnie.
10 koderów, każdy tydzień nowa klasa (to jest i tak bardzo wolno).
Ale powiedzmy, że raz na tydzień masz klasę dziedziczoną z takiego
cuda, co powoduje niekompilowanie się kodu.
Teraz dorzucasz wersję debug, test i release, gdzie w release
nie masz niczego co naprawdę nie sprawdziłeś.
I po ostatnie. Masz miejsca gdzie celowo obsługujsze tylko dwie klasy.

Jak to zrobisz?

> Podobnie jak Maciek (*) zastanawiałem się jak obsłużyć takie
> przypadki. I wyszło mi, że najlepszy byłby sposób znany np.
> z ocaml


Może. Mnie ten język iteresuje hobbistycznie do 100 lini kodu --
nie widzę problemów o których piszę. Dynamicznie rozwijajacego sie
kodu powyzej 100 000 lini nie widziałem w ocamlu. Oczywiscie
w kontekscietego, ze raz na tydzien z powodu jakiejs klasy
musze w 1000 miejscach poprawaic kod. Czyli nie wychodze
przez tydzien z pracy do domu, bo Xiński napisał klasę,
a ja weekend mam zamknąc wersją ktora się kompiluje.

> się czy inni grupowicze, odczuwali potrzebę takiej
> konstrukcji w C++.


Wszelakie automaty bardzo automatyczne są do bani.
A propozycja nie kompilowania sie kodu, bo Xiński coś
dodał i wszystko trzeba rzucać, w kąt, bo w 1000 miejscach kod się
nie kompiluje, bo switch rzuca błędy, to ja dziękuję.

> Ewentualnie ktoś coś może słyszał, że
> były takie propozycje w przyszłej wersji standardu.


Oby nie.

> wychodzi na to, że swich + enum, ewentualnie wzorzec wizytor
> wszystkim wystarcza :)


Nie wystarcza, tylko nie stwarza mnóstwa problemów,
ktore póki co widzę w Twoim wymaganiu.
Wole to napisac zapomoca listy typow i iterowac
ponich, wtedy, tylko tam gdzie prosze sie o guza
dostane po glowie a nie wszedzie.

Założenie jeden. Klasa która jest nieużywana,
ale istnieje w kodzie powinna być poprawna syntaktycznie,
ale nie powinna wywalać kompilacji.
To jest IMHO karygodne.

Pozdrawiam,
Seweryn Habdank-Wojewódzki.

Podobne wątki
Ciekawostka przyrodnicza

Dziś zostałam uraczona chłodnikiem "litewskim" z... krewetkami, w zastępstwie raków, chyba. Hmmm... :/

Ciekawostka przyrodnicza

Regulamin Promocji "Rachunek dyskretny" # Usługa pozwala Abonentowi na rozszerzenie zakresu zachowania w poufności informacji o połączeniach wykonywanych z numeru...

ciekawostka przyrodnicza

> NH4(+) = NH3(+) + H ze niby wodor atomowy powstaje?? dziwne...

ciekawostka przyrodnicza

Jestem dumnym posiadaczem dosyć wiekowego ale do tej pory spisującego się bez zarzutów kompa. Mój zestaw to Plyta główna Acorp 6bx67 z chipsetem 440BX Procesor Celeron 333,...

Ciekawostka przyrodnicza

Co wam to przypomina? (reklama z Gadu-gadu - 17 KB) [..]


Czasy w strefie GMT. Teraz jest 18:59. | Privacy Policy