|
#1
|
|
|
|
|
Witam
Wszystkim fanom dynamicznego typowania polecam przeczytac krotkie opracowanie [1]. Dosc ciekawa jest dyskusja ponizej, a szczegolnie tematy zwiazane z Poco::DynamicAny [2]. Dla nabrania smaku podaje: # Python any = '42' i = int(x) any = 65535 s = str(x) Podobny kod w C++ 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. Pozdrawiam, [1] http://herbsutter.wordpress.com/2008...ynamic-typing/ [2] http://pocoproject.org/poco/docs/Poco.DynamicAny.html |
|
|
|
#2
|
|
|
|
|
> // mozna tez dodac jeszcze takie cos:
> char c = any; // too big, throws RangeException # Python c = chr(any) // rowniez sypnie wyjatkiem |
|
#3
|
|
|
|
|
In the darkest hour on Fri, 27 Jun 2008 00:24:42 -0700 (PDT),
Seweryn Habdank-Wojewódzki <habdank> screamed: [..] |
|
#4
|
|
|
|
|
Seweryn Habdank-Wojewódzki wrote:
> Wszystkim fanom dynamicznego typowania polecam przeczytac krotkie > opracowanie [1]. Dynamiczne typy w C++ nie byly mi do tej pory potrzebne. Natomiast chetnie zobaczylbym bym coś na ksztalt typów wariantowych, znanych z jezyków funkcjonalnych. Zwlaszcza, ze stanowilyby doskonaly zamiennik dla znienawidzonego, przez mnie, wzorca wizytor. Ponizej przyklad: case class Expression { cases { class BinaryExpression; class UnaryExpression; class NumberExpression; }; }; class BinaryExpression: public Expression {}; class UnaryExpression: public Expression {}; class NumberExpression: public Expression {}; void foo () { const Expression& e = getExpression (); switch ( e ) { case BinaryExpression x: break; case UnaryExpression x: break; case NumberExpression x: break; }; } Co myślicie o przydatności takiej konstrukcji? Moze ktoś wie czy tego typu pomysly byly rozwazane w przyszlej wersji standardu? Pozdrawiam KK |
|
#5
|
|
|
|
|
> ze stanowilyby doskonaly zamiennik dla znienawidzonego, przez mnie, wzorca
> wizytor. Ponizej przyklad: osobiście uzywam metody wirtualnej w klasie bazowej, zwracającej TYP wyrazenia, przeciązonej w klasach wariantowych zeby robic switch po typie. C#: enum ExpressionType { None, Unary, ... }; class Expression { virtual ExpressionType Type; // do rzutowania na typy wariantowe, przydatne w switch ponizej T OfType<T>() { return (T)this; }; } class UnaryExpression { override int Type = ...; } void Foo() { Expression e; switch ( e.Type ) { case ExpressionType.Unary : e.OfType<UnaryExpression>() } } // przez mnie, wzorca wizytor. Ponizej przyklad: prosze o wyjaśnienie co ma do tego wzorzec wizytor. Wiktor Zychla |
|
#6
|
|
|
|
|
> DynamicAny any("42");
> int i = any; // i == 42 > any = 65536; > std::string s = any; // s == "65536" fajne, ale mam pewne pytanie: nie wiem jak to jest zaimplementowane, ale spekuluje, ze "typ" any bedzie zawsze DynamicAny, natomiast w dynamicznym typowaniu chcialoby sie zeby "typ" wyrazenia zmienial sie w zaleznosci od kontekstu i zeby to runtime engine decydowal o tym co robic dalej z efektami zmian typów (a nie kompilator). a wiec: - jesli to "dynamiczne typowanie" polega na poprzeciazaniu operatorów przypisania, to w istocie nie ma tu zbyt wiele dynamizmu, bo dla kazdego operatora przypisania kompilator i tak STATYCZNIE widzi typy elementów po jednej i po drugiej stronie wyrazenia i uzyje odpowiedniej wersji przeciazonego operatora. - natomiast dynamiczne to to typowanie byloby, gdyby typy wyrazen wystepujacych w wyrazeniu przypisania nie byly znane i kompilator w któryms miejscu nie wiedzialby jaki prawdziwy typ ma dane wyrazenie, natomiast ten typ znany bylby w runtime. cos w stylu: class Bar { } DynamicAny Foo1() { if ( warunek ) return 1; else return new Bar(); } DynamicAny Foo2() { if ( warunek ) return 1; else return new Bar(); } void Baz() { Foo1() + Foo2(); // tu kompilator co prawda wie, ze operator sumowania aplikuje sie do // dwóch obiektów typu DynamicAny, ale // w jezykach z dynamicznym typowaniem to zadziala zawsze // - gdy oba Foo() zwróca jedynke (bo dodadza sie do siebie dwie jedynki) // - gdy oba Foo() zwróca Bar() zostanie wywolany operator + na Bar // (+ zostanie rozwiklany w runtime) // w jezyku z dynamicznym typowaniem "udawanym" przez operatory konwersji // to nie przejdzie, bo operator + na DynamicAny na pewno nie potrafi obsluzyc // przypadku gdy dodawane sa obiekty nieznanego mu w czasie kompilacji typu // Bar } Wiktor Zychla |
|
#7
|
|
|
|
|
Wiktor Zychla wrote:
> osobiście uzywam metody wirtualnej w klasie bazowej, zwracającej TYP > wyrazenia, przeciązonej w klasach wariantowych zeby robic switch po typie. > > C#: > > enum ExpressionType { None, Unary, ... }; > [ciach] > Expression e; > switch ( e.Type ) > { > case ExpressionType.Unary : > e.OfType<UnaryExpression>() > } > } > Nie znam C#. Czy wygeneruje on ostrzezenie, jezeli do ExpressionType dodamy nastepny element, a nie uzupelnimy odpowiednich konstrukcji switch? Jezeli tak, to jest to jakieś rozwiązania. W C++ takich mozliwości niestety nie ma. Osobiście w takich przypadkach, w C++, stosuje statyczną asercje: enum ExpressionType { None, Unary, ..., Num }; BOOST_STATIC_ASSERT ( Expression::Num == 10 ) switch ( e.type ()) { /// ... Przynajmniej bede wiedzial gdzie mam zmodyfikowac kod. Niestety wymaga do samodyscypliny i jest uciązliwe. > > prosze o wyjaśnienie co ma do tego wzorzec wizytor. > Szerzej tutaj: http://www.inspirel.com/articles/Visitor_Revisited.html Pozdrawiam KK |
|
#8
|
|
|
|
|
> http://www.inspirel.com/articles/Visitor_Revisited.html
ok, juz widze jak chcialeś do tego uzywac visitora. przyklad jest o tyle wymowny, ze zaproponowana alternatywa to dokladnie coś takiego o czym rozmawiamy. > Nie znam C#. Czy wygeneruje on ostrzezenie, jezeli do niestety :( ja najcześciej stosuje klauzule default, która wyrzuca wyjątek, a o tym, ze czegoś zapomnialem dopisac dowiaduje sie w trakcie testów. Wiktor Zychla |
|
#9
|
|
|
|
|
Krzysiek Kowaliczek w wiadomości <g427fb$1fl$1> pisze:
[..] > case UnaryExpression x: > break; > case NumberExpression x: > break; > }; > } > > Co myślicie o przydatności takiej konstrukcji? Może ktoś wie > czy tego typu pomysły były rozważane w przyszłej wersji > standardu? Dla mnie tego typu konstrukcja (switch po typie) zawsze "brzydko pachnie". Czy tego, co miałoby się wykonywać dla poszczególnych przypadków nie lepiej zawrzeć jako metodę wirtualną wspólnego typu (interfejsu) bazowego? W tym wypadku: "zrób ogólne foo()": class Expression { public: virtual void foo() = 0; }; class BinaryExpression: public Expression { void foo() {foo_as_BinaryExpression();} }; class UnaryExpression: public Expression { void foo() {foo_as_UnaryExpression();} }; class NumberExpression: public Expression { void foo() {foo_as_NumberExpression();} }; i wtedy: void foo() { Expression& e = getExpression (); e.foo(); } czyli w praktyce: getExpression().foo(); Ale może przykład jest zbyt słaby, żeby pokazać, że switch jest niezbędny/prostszy. |
|
#10
|
|
|
|
|
> Ale może przykład jest zbyt słaby, żeby pokazać, że switch jest
> niezbędny/prostszy. wystarczy pomyśleć o tym, co by było, gdyby każda klauzula switch korzystała z pewnego podzbioru zmiennych widzianych przez switch, np. void bar() { // tu mam w polu widzenia x, y, z, t, u, v, itd. RÓZNYCH typów switch ( e.Type ) { case Type.UnaryExpression: zrób coś z x, y i z; case Type.BinaryExpression: zrób coś z u, v; } } gdyby chcieć mieć jedną wirtualną metodę na Expression, to musiałaby ona mieć bliżej nie sprecyzowaną sygnaturę. może możnaby użyć do tego przypadku z powodzeniem refaktoryzacji Introduce Parameter Object, ale w ogólnym przypadku trudno powiedzieć, który wariant jest lepszy. Wiktor Zychla |
|
#11
|
|
|
|
|
Paweł Kierski wrote:
> Dla mnie tego typu konstrukcja (switch po typie) zawsze "brzydko > pachnie". Czy tego, co miałoby się wykonywać dla poszczególnych > przypadków nie lepiej zawrzeć jako metodę wirtualną wspólnego typu > (interfejsu) bazowego? W tym wypadku: "zrób ogólne foo()": > Odpowiedź jest prosta. Po prostu się nie da. Trudno mi sobie nawet takie coś wyobrazić. Każde nowe "zrób ogólne foo()" wymagałoby zmiany we wszystkich klasach pochodnych. To to już całkowicie łamie zasadę open-close. Biorąc pod uwagę, że ilość klas jest mniejsza od ilości algorytmów operujących na nich ( z mojego punktu widzenia ), to już lepszy byłby wzorzec wizytor. Pozdrawiam KK |
|
#12
|
|
|
|
|
Wiktor Zychla w wiadomości <g42sap$6mk$1> pisze:
[..] > zrób coś z x, y i z; > case Type.BinaryExpression: > zrób coś z u, v; > } > } > > gdyby chcieć mieć jedną wirtualną metodę na Expression, to musiałaby ona > mieć bliżej nie sprecyzowaną sygnaturę. może możnaby użyć do tego przypadku > z powodzeniem refaktoryzacji Introduce Parameter Object, ale w ogólnym > przypadku trudno powiedzieć, który wariant jest lepszy. Zgadzam się - w ogólności nie da się powiedzieć, co najlepsze. Przyznam się, że chodziło mi o podkreślenie, że switch po typie dla bardziej "regularnych" przypadków (operacje na podobnych listach argumentów) nie jest najszczęśliwszym rozwiązaniem 8-) |
|
#13
|
|
|
|
|
On 27 Cze, 08:54, Seweryn Habdank-Wojewódzki <habd>
wrote: > [2][..] Następujący fragment jest moim zdaniem głupi (trudno sobie wyobrazić sytuację, w której właśnie takie zachowanie byłoby potrzebne): A string value "false" (not case sensitive) or "0" can be converted to a boolean value false, any other string not being false by the above criteria evaluates to true (e.g: "hi" -> true). |
|
#14
|
|
|
|
|
Witam
> > 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. Pozdrawiam, Seweryn Habdank-Wojewodzki. |
|
#15
|
|
|
|
|
Witam
> A string value "false" (not case sensitive) or "0" can be converted to > a boolean value false, any other string not being false by the above > criteria evaluates to true (e.g: "hi" -> true). Słusznie! To powinno albo działać w drugą stronę czyli 'true' tylko dla true. Reszta to false. Albo w ogóle silno czyli 'true' to true 'false' to false, a reszta to wyjatek bad_cast. 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 14:57. | Privacy Policy
|