Silne typowanie oparte na semantyce

0

Ostatnio, przypadkowo natrafiłem na wykład Stroustrupa, dotyczący wybranych zmian wprowadzanych przez nowy standard C++. Moją uwagę przykuło zagadnienie, nazywane przez prelegenta, jako type-rich programming. W skrócie chodzi o definiowanie możliwie, jak najsilniej typowanego interfejsu. Stroustrup rozumie przez to przygotowanie, takiego interfejsu, który pociąga za sobą semantykę. Interfejs ma jednoznacznie wskazywać z jakim rodzajem obiektu mamy do czynienia.
Antyprzykładem może być np. abstrakcyjna deklaracje funkcji rysujących prostokąt:

bool DrawRectangle(const double x1, const double y1,  const double x2, const double y2);
bool DrawRectangle(const double x1, const double y1, const double diagonal);

Stroustrup powiedziałby, że typ

const double

nie identyfikuje, jednoznacznie z jakiego rodzaju danymi mamy do czynienia. Musimy domyslać, się co onaczają poszczególne argumenty tych funkcji. (Okey, można by nadać argumentom lepsze nazwy, ale to nadal nie dotyka nie dotyczy istoty problemu).
Pomysł na rozwiązanie problemu, według Stroustrupa polaga na użyciu np. szablonów, bądź przeładowania operatora

operator ""

Poniżej wycinek kodu z prezentacji Stroustupa (nie testowałem, czy to w ogóle działa)

template<int M, int K, int S> struct Unit
{
    enum {m = M, k = K, s = S };
};

template<typename Unit>
struct Value {
    double val;
    explicit Value(double d) : val(d) { }
};

using Second = Unit<0, 0, 1>;
using Meter = Unit<1, 0, 0>;
using Speed = Unit<1, 0, 1>;
constexpr Value<Second> operator"" s(long double _s) { return Value<Second>(_s); }
constexpr Value<Meter> operator"" m(long double _m) { return Value<Meter>(_m); }
Speed currentSpeed = 100m / 9.81s;

Przechodząc już do pytania. Czy ktoś z Was kiedykolwiek stosował, aż tak silne typowanie? Czy Waszym zdaniem jest w ogóle miejsce na takie tworzenie interfejsów? Moim zdaniem, jeśli aplikacja działa na zbiorze danych silnie zróżnicowanym pod względem typu, takie działanie byłoby strzeleniem sobie samobója już na starcie.
Linki:
Wykład
Prezentacja

0

Zasadniczo jest to chyba zgodne z takim pomysłem żeby nie używać w ogóle bezpośrednio prymitywnych typów. I ma to czasem pewne zastosowana. Sam popełniłem kiedyś coś co w efekcie finalnym wyglądało mniej wiecej tak (java)
Map<String,Map<Integer,Map<Integer,Map<Integer,Integer>>>>
(i to nie wyolbrzymienie, to tak wyglądało :P)
I miało to całkowity sens, tylko że wymagało ultra komentarza który wyjaśniał to mapowanie. A mogłoby się okazać że dużo lepiej to wygląda jako:
Map<Timeslot,Map<Vertex, Map<Vertex,Map<Topic,Frequency>>>>
bo od razu widać co w tej mapie siedzi i co te mapingi oznaczają :)

0
Shalom napisał(a):

I miało to całkowity sens, tylko że wymagało ultra komentarza który wyjaśniał to mapowanie. A mogłoby się okazać że dużo lepiej to wygląda jako:
Map<Timeslot,Map<Vertex, Map<Vertex,Map<Topic,Frequency>>>>
bo od razu widać co w tej mapie siedzi i co te mapingi oznaczają :)
No tak, jednak o ile na java'ie się nie znam więc nie wiem czy tam jest taki mechanizm jednak przeciętny programista c++'a (powiedzmy c++03) myślę, że w twoim wypadku @Shalom w pierwszej kolejności zastanowiłby się nad typedef'em, a nie obudowywaniem typów i tworzeniem własnych literałów jak to czyni Stroustrup. Oczywiście jego kod jest dobry, przemyślany ... ale czy nie jest to aby lekkie przegięcie w tą drugą stronę? Kto tak szczerze na co dzień pisze? Może i miło czytałoby mi się taki kod - bez niedomówień ale patrząc na codzienne realia marzy mi się aby programiści których kody niemal co dziennie muszę analizować postarali się świadomie napisać chociaż w 10% kod zrozumiały dla kogoś innego poza nimi samymi ;p Skoro mam takie marzenia, to wizja Stroustrup'a tym bardziej wydaje mi się tylko piękną powieścią fantastyczną kończącą się happyend'em. Płynie z niej nauka oraz "moc" tylko nie jestem do końca przekonany czy podejście typu "nie używaj podstawowych typów wprost" nie będzie w wielu przypadkach przerostem formy nad treścią czy też inaczej lukrem składniowym ?

0

Witam,
Nie do końca rozumiem kod, który został przedstawiony przez Stroustupa. Prawdę powiedziawszy to prawie w ogóle. Nie wiem czy jest to zagadnienie dla początkujących. Wiem co to szablony, struktury, co znaczy explicit. Nie rozumiem using oraz constexpr.

0

@xoac i co w związku z tym? Nie jest to zagadnienie dla początkujących. A jeśli nie rozumiesz elementów składni to doczytaj sobie co oznaczają i tyle.

0

idea tak silnego typowania podoba mi się, bo utrudnia pomyłki w obliczeniach – kompilator robi za nas analizę wymiarową.

w praktyce tego jeszcze nie widziałem, ani nie pisałem niczego w ten sposób. obawiam się że może być to uciążliwe.

using Speed = Unit<1, 0, 1>;

Jeśli dobrze rozumiem ideę, to powinno być Unit<1, 0, -1>.

1

Dziwny ten kod w C++. Nie bardzo jest oczywiste, jakim cudem dla tych klas jest zdefiniowany operator dzielenia, który jeszcze przy okazji zmienia jednostkę. Może to nie jest kompletny kod?

Ale generalnie takie podejście jest w porządku, choć to z tym Unitem trochę zamotane.

Podobny przykład w Scali:

case class Seconds(value: Double) extends AnyVal
case class Speed(value: Double) extends AnyVal
case class Meters(value: Double) extends AnyVal { 
  def / (time: Seconds) = Speed(value / time.value) 
}

implicit class UnitConversions(value: Double) {  
  def m = Meters(value) 
  def s = Seconds(value) 
}

Użycie:

scala> 10.m / 5.s
res2: Speed = Speed(2.0)
1

Kod jest dziwny, bo jest w nim wiele elementów, których jeszcze nie ma w standardzie. (a może już są?)

Dzielenie powinno być w klasie Unit. Wartość jest dzielona normalnie, a wykładniki (parametry szablonu) odejmowane. W ten sposób raz zdefiniowany operator zadziała dla każdych jednostek.

0

@Krolik - kod nie jest kompletny, należałoby teraz w strukturze Unit zdefiniować operatory +, -, /, *, ==, !=, >, <, >=, <=. Przykładowo, tak jak tutaj: http://learningcppisfun.blogs[...]ensions-with-c-templates.html
Odnośnie samego problemu jednostek to boost oferuje osobną bibliotekę to tego: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_units.html

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0