diff -r 9c5e8460df05 -r ee9785abbcd6 src/Doc/Implementation/ML.thy --- a/src/Doc/Implementation/ML.thy Sat Apr 22 10:22:41 2023 +0200 +++ b/src/Doc/Implementation/ML.thy Sat Apr 22 20:55:05 2023 +0200 @@ -1495,12 +1495,52 @@ @{define_ML the_list: "'a option -> 'a list"} \\ @{define_ML the_default: "'a -> 'a option -> 'a"} \\ \end{mldecls} + + \begin{matharray}{rcl} + @{ML_antiquotation_def "if_none"} & : & \ML_antiquotation\ \\ + \end{matharray} + + \<^rail>\@@{ML_antiquotation if_none} embedded\ \ text \ Apart from \<^ML>\Option.map\ most other operations defined in structure \<^ML_structure>\Option\ are alien to Isabelle/ML and never used. The operations shown above are defined in \<^file>\~~/src/Pure/General/basics.ML\. + + Note that the function \<^ML>\the_default\ is strict in all of its + arguments, the default value is evaluated beforehand, even if not required + later. In contrast, the antiquotation @{ML_antiquotation "if_none"} is + non-strict: the given expression is only evaluated for an application to + \<^ML>\NONE\. This allows to work with exceptions like this: +\ + +ML \ + fun div_total x y = + \<^try>\x div y\ |> the_default 0; + + fun div_error x y = + \<^try>\x div y\ |> \<^if_none>\error "Division by zero"\; +\ + +text \ + Of course, it is also possible to handle exceptions directly, without an + intermediate option construction: +\ + +ML \ + fun div_total x y = + x div y handle Div => 0; + + fun div_error x y = + x div y handle Div => error "Division by zero"; +\ + +text \ + The first form works better in longer chains of functional composition, with + combinators like \<^ML>\|>\ or \<^ML>\#>\ or \<^ML>\o\. The second form is more + adequate in elementary expressions: there is no need to pretend that + Isabelle/ML is actually a version of Haskell. \