namespace cpp {}

C++ lernen, kennen, anwenden

Benutzer-Werkzeuge

Webseiten-Werkzeuge


kennen:include:expected

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
kennen:include:expected [2024-11-01 16:14] – [Methoden] rrichterkennen:include:expected [2024-11-01 20:33] (aktuell) – [Monadische Operationen] rrichter
Zeile 1: Zeile 1:
 ====== <expected> ====== ====== <expected> ======
  
-Ein ''std::expected<Result,Error>'' enthält entweder das Ergebnis einer Berechnung oder eine Angabe, warum die Berechnung scheiterte:+Ein ''std::expected<R,E>'' enthält entweder das Ergebnis einer Berechnung (''R'' = Resultat) oder eine Angabe, warum die Berechnung scheiterte (''E'' = Error):
  
 <code cpp expected.cpp> <code cpp expected.cpp>
Zeile 19: Zeile 19:
   {   {
     auto answer = question(6*n);     auto answer = question(6*n);
-    if (answer.has_value())+    if (answer.has_value())        // oder: if(answer)
       std::println("Die richtige Antwort ist {}", answer.value());       std::println("Die richtige Antwort ist {}", answer.value());
     else     else
Zeile 35: Zeile 35:
 | ''error_or(e)''  | Alternative, falls erwarteter Wert vorhanden | | ''error_or(e)''  | Alternative, falls erwarteter Wert vorhanden |
  
-Außerdem sind "monadische" Operationen definiert, die nachfolgend eine Funktion ''f'' ausführen:+===== Monadische Operationen ===== 
 +> Monada monoid in the category of endofunctors 
 +> -- James Iry
  
-| ''and_then(f)'' berechnet ''f(value())'', ''f'' liefert wiederum ein ''std::expected''+> Once you understand, you lose the ability to explain. 
-| ''transform(f)''  berechnet ''f(value()'', reicht unerwarteten Wert weiter +> -- https://news.ycombinator.com/item?id=22417583 
-| ''or_else(f)''  |  |+ 
 +Diese rufen in Abhängigkeit vom Vorhandensein eines Wertes eine Funktion ''f'' auf. 
 +Im Ergebnis entsteht wiederum ein ''std::expected<_,_>''
 +Dabei werden die Typen ''R'' und ''E'' entsprechend angepasst. 
 + 
 +^ Wert vorhanden? ^ ja ^ nein ^Rückgabetyp von ''f''
 +| ''and_then(f)''  | ''f(value())'' | | ''std::expected<R2,E>'' 
 +| ''or_else(f)'' |  | ''f(error())''''std::expected<R,E2>''
 +| ''transform(f)'' | ''f(value())'' | | ''R2'' 
 +| ''transform_error(f)'' | | ''f(error())'' | ''E2''
 + 
 +Mit den monadischen Operationen lassen sich Verarbeitungsschritte und eventuell auftretende Fehler verketten:  
 + 
 +<code cpp name_of_weekday.cpp> 
 +#include <expected> 
 +#include <iostream> 
 +#include <print> 
 +#include <string> 
 + 
 +struct Date { int y, m, d; }; 
 + 
 +auto leapyear(int y)  
 +
 +  return (y % 4 == 0 && !(y % 100 == 0)) || y % 400 == 0; 
 +  
 + 
 +auto day_of_week(Date date) // Zellers Kongruenz, Gregorianisch: y > 1582   
 +
 +  auto [y,m,d] = date; 
 +  if (m < 3) { m += 12; --y; }  
 +  auto C = y / 100; 
 +  auto D = y % 100; 
 +  return (d + 13*(m+1)/5 + D + D/4 + C/4 + 5*C) % 7;  
 +
 + 
 +auto name_of_weekday(int w) 
 +
 +  std::string const name[] = { "Sa", "So", "Mo", "Di", "Mi", "Do", "Fr" }; 
 +  return name[w]; 
 +
 + 
 +std::expected<Date, std::string> input() 
 +
 +  Date date; 
 +  char sep; 
 + 
 +  std::cout << "Datum (y-m-d): "; 
 +   
 +  if (std::cin >> date.y >> sep >> date.m >> sep >> date.d && sep == '-')  
 +    return date; 
 +  else  
 +    return std::unexpected{"falsche Eingabe"}; 
 +
 + 
 +std::expected<Date, std::string> valid(Date date) 
 +
 +  if (date.m < 1 || date.m > 12) return std::unexpected{"ungültiger Monat"}; 
 +  if (date.d < 1 || date.d > 31) return std::unexpected{"ungültiger Tag"}; 
 + 
 +  for (auto m : { 4, 6, 9, 11 }) 
 +  { 
 +    if (m == date.m && date.d == 31) 
 +      return std::unexpected{"April, Juni, September und Oktober haben keinen 31. Tag"}; 
 +  } 
 +  if (date.m == 2 && date.d > 28 + leapyear(date.y))  
 +  { 
 +    return std::unexpected{"Diesen Tag gibt es im Februar nicht"}; 
 +  } 
 +  return date; 
 +
 + 
 +int main() 
 +
 +  auto result = input() 
 +    .and_then(valid) 
 +    .transform(day_of_week)  
 +    .transform(name_of_weekday) 
 +    .transform_error([](std::string s) { return "Fehler: " + s; }) 
 +    .or_else([](const std::string& error) { 
 +      std::println(std::cerr, "Eintrag {}", error); 
 +      return std::expected<std::string, std::string>{std::unexpected{error}}; 
 +    }); 
 +  
 +  if (result) std::println("{}", result.value()); 
 +  else std::println("{}", result.error()); 
 +
 +</code>
  
 Siehe auch: [[optional]], [[variant]] Siehe auch: [[optional]], [[variant]]
  
  
kennen/include/expected.1730474047.txt.gz · Zuletzt geändert: 2024-11-01 16:14 von rrichter

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki