Skip to content

Commit

Permalink
Add Examples / Unit Tests for Exceptions (effekt-lang#775)
Browse files Browse the repository at this point in the history
## Motivation
Resolves effekt-lang#480
This module demonstrates exception handling combinators in Effekt using
a simple, focused example. By showcasing custom exception handling
(`TestException`) with different strategies (default handling, ignoring,
reporting, finalizing), it provides a practical guide for understanding
these features.

## Changes
- Introduced `TestException` as a custom exception type, independent of
other exceptions like `OutOfBounds`.
- Added `generalOperation`, which raises a `TestException` for invalid
input or returns a string.
- Included tests for handling exceptions with:
  - Default behavior
  - Ignoring exceptions
  - Reporting exceptions
  - Finalization hooks
  - "Reifying" with Results

## Testing
The examples are self-contained in the `main` function, covering all
provided exception-handling strategies. Each approach is tested and
outputs expected results for validation (`combinators.check`).
  • Loading branch information
JakubSchwenkbeck authored and EveEme committed Jan 20, 2025
1 parent 061473a commit cbc3e8c
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
11 changes: 11 additions & 0 deletions examples/stdlib/exception/combinators.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Test: Default Handling
hello
hello
Error: Invalid index (0)
Error: Invalid index (-1)
hello
Test: Finalizer
hello
Test: Finalizer
Error: Invalid index (0)
Success: hello
73 changes: 73 additions & 0 deletions examples/stdlib/exception/combinators.effekt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
module examples/pos/exception/combinators

import exception
import result


/// Used as a type for `Exception` purely for independent testing
record TestException()


/// Returns the string if index > 0; otherwise raises a TestException.
def generalOperation(str: String, index: Int): String / Exception[TestException] = {
if (index <= 0)
do raise(TestException(), "Error: Invalid index (" ++ show(index) ++ ")")
else
str
}

def main() = {
val str: String = "hello"

// Test for default handling of TestException
def defaultTestException { p: => String / Exception[TestException] }: Unit = {
with on[TestException].default { println("Test: Default Handling") }
println(p().show)
}

defaultTestException { str.generalOperation(0) } // Test: Default Handling
defaultTestException { str.generalOperation(1) } // hello

// Test for ignoring TestException
def ignoreTestException { p: => String / Exception[TestException] }: Unit = {
with on[TestException].ignore();
println(p().show)
}

ignoreTestException { str.generalOperation(0) } // *ignores the TestException*
ignoreTestException { str.generalOperation(1) } // hello

// Test for reporting TestException
def reportTestException { p: => String / Exception[TestException] }: Unit = {
with on[TestException].report();
println(p().show)
}

reportTestException { str.generalOperation(0) } // Error: Invalid index (0)
reportTestException { str.generalOperation(-1) }// Error: Invalid index (-1)
reportTestException { str.generalOperation(1) } // hello

// Test for finalizing TestException
def finalizeTestException { p: => String / Exception[TestException] }: Unit = {
try {
with on[TestException].finalize { println("Test: Finalizer") }
println(p().show)
} with Exception[TestException] { def raise(exception, msg) = () }
}

finalizeTestException { str.generalOperation(0) } // Test: Finalizer
finalizeTestException { str.generalOperation(1) } // Test: Finalizer hello

// Test for "reifying" an Exception using Result
def resultTestException { p: => String / Exception[TestException] }: Unit = {
val res = result[String, TestException] { p() }
res match {
case Success(msg) => println("Success: " ++ msg)
case Error(exc, msg) => println(msg)
}
}

resultTestException { str.generalOperation(0) } // Error: Invalid index (0)
resultTestException { str.generalOperation(1) } // Success: hello

}

0 comments on commit cbc3e8c

Please sign in to comment.