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 17:31] – [<expected>] rrichterkennen:include:expected [2024-11-01 20:33] (aktuell) – [Monadische Operationen] rrichter
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 als Methoden definiert+===== Monadische Operationen ===== 
 +> Monad: a monoid in the category of endofunctors 
 +> -- James Iry 
 + 
 +> Once you understand, you lose the ability to explain. 
 +> -- https://news.ycombinator.com/item?id=22417583 
 Diese rufen in Abhängigkeit vom Vorhandensein eines Wertes eine Funktion ''f'' auf. Diese rufen in Abhängigkeit vom Vorhandensein eines Wertes eine Funktion ''f'' auf.
 Im Ergebnis entsteht wiederum ein ''std::expected<_,_>''. Im Ergebnis entsteht wiederum ein ''std::expected<_,_>''.
Zeile 46: Zeile 52:
 | ''transform_error(f)'' | | ''f(error())'' | ''E2'' | | ''transform_error(f)'' | | ''f(error())'' | ''E2'' |
  
-<code> +Mit den monadischen Operationen lassen sich Verarbeitungsschritte und eventuell auftretende Fehler verketten:  
-TODO+ 
 +<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> </code>
  
kennen/include/expected.1730478712.txt.gz · Zuletzt geändert: 2024-11-01 17:31 von rrichter

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki