Changeset 9411cf0

Ignore:
Timestamp:
Sep 24, 2021, 12:09:38 PM (14 months ago)
Branches:
Children:
f93c50a
Parents:
814f87d
Message:

Andrew MMath: Maybe the last changes to the thesis.

Location:
doc/theses/andrew_beach_MMath
Files:
2 edited

Legend:

Unmodified
 r814f87d it returns control to that function. \begin{center} \input{termination} \medskip %\input{termination} % %\medskip \input{termhandle.pstex_t} % I hate these diagrams, but I can't access xfig to fix them and they are % better than the alternative. \end{center} \todo*{Can I make the new diagrams fit the old style?} Resumption exception handling searches the stack for a handler and then calls that preformed the raise, usually starting after the raise. \begin{center} \input{resumption} \medskip %\input{resumption} % %\medskip \input{resumhandle.pstex_t} % The other one. \end{center} through multiple functions before it is addressed. Here is an example of the pattern in Bash, where commands can only  return" numbers and most output is done through streams of text. \begin{lstlisting}[language=bash,escapechar={}] # Immediately after running a command: case \$? in 0) # Success ;; 1) # Error Code 1 ;; 2|3) # Error Code 2 or Error Code 3 ;; # Add more cases as needed. asac \end{lstlisting} \item\emph{Special Return with Global Store}: Similar to the error codes pattern but the function itself only returns This approach avoids the multiple results issue encountered with straight error codes but otherwise has the same disadvantages and more. error codes as only a single error value has to be returned, but otherwise has the same disadvantages and more. Every function that reads or writes to the global store must agree on all possible errors and managing it becomes more complex with concurrency. This example shows some of what has to be done to robustly handle a C standard library function that reports errors this way. \begin{lstlisting}[language=C] // Make sure to clear the store. errno = 0; // Now a library function can set the error. int handle = open(path_name, flags); if (-1 == handle) { switch (errno) { case ENAMETOOLONG: // path_name is a bad argument. break; case ENFILE: // A system resource has been exausted. break; // And many more... } } \end{lstlisting} % cite open man page? \item\emph{Return Union}: % Rust's \code{rust}{Result} This is a simple example of examining the result of a failing function in Haskell, using its \code{haskell}{Either} type. Examining \code{haskell}{error} further would likely involve more matching, but the type of \code{haskell}{error} is user defined so there are no general cases. \begin{lstlisting}[language=haskell] case failingFunction argA argB of Right value -> -- Use the successful computed value. Left error -> -- Handle the produced error. \end{lstlisting} Return unions as monads will result in the same code, but can hide most of the work to propagate errors in simple cases. The code to actually handle the errors, or to interact with other monads (a common case in these languages) still has to be written by hand. If \code{haskell}{failingFunction} is implemented with two helpers that use the same error type, then it can be implemented with a \code{haskell}{do} block. \begin{lstlisting}[language=haskell] failingFunction x y = do z <- helperOne x helperTwo y z \end{lstlisting} \item\emph{Handler Functions}: function calls, but cheaper (constant time) to call, they are more suited to more frequent (less exceptional) situations. Although, in \Cpp and other languages that do not have checked exceptions, they can actually be enforced by the type system be more reliable. This is a more local example in \Cpp, using a function to provide a default value for a mapping. \begin{lstlisting}[language=C++] ValueT Map::key_or_default(KeyT key, ValueT(*make_default)(KeyT)) { ValueT * value = find_value(key); if (nullptr != value) { return *value; } else { return make_default(key); } } \end{lstlisting} \end{itemize}