Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweak fiber docs #185

Merged
merged 3 commits into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions content/docs/fibers/dynamic_bindings.mdz
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
There are situations where the programmer would like to thread a parameter
through multiple function calls, without passing that argument to every function
explicitly. This can make code more concise, easier to read, and easier to
extend. Dynamic bindings are a mechanism that provide this in a safe and easy to
extend. Dynamic bindings are a mechanism that provides this in a safe and easy to
use way. This is in contrast to lexically-scoped bindings, which are usually
superior to dynamically-scoped bindings in terms of clarity, composability, and
performance. However, dynamic scoping can be used to great effect for implicit
Expand Down Expand Up @@ -54,38 +54,39 @@ print function @code`pp`.
(def curr-env (fiber/getenv (fiber/current)))

# The dynamic bindings we want to use
(def my-env {:pretty-format "Inside myblock: %.20P"})
(def my-env @{:pretty-format "Inside myblock: %.20P"})

# Set up a new fiber
(def f (fiber/new myblock))
(fiber/setenv f (table/setproto my-env curr-env))

# Run the code
(pp [1 2 3]) # prints "[1 2 3]"
(resume f) # prints "Inside myblock: [1 2 3]"
(pp [1 2 3]) # prints "[1 2 3]"
(pp [1 2 3]) # prints "(1 2 3)"
(resume f) # prints "Inside myblock: (1 2 3)"
(pp [1 2 3]) # prints "(1 2 3)"
```

This is verbose so the core library provides a macro, @code`with-dyns`, that
makes it much clearer in the common case.

@codeblock[janet]```
(pp [1 2 3]) # prints "[1 2 3]"
# prints "Inside with-dyns: [1 2 3]"
(pp [1 2 3]) # prints "(1 2 3)"
# prints "Inside with-dyns: (1 2 3)"
(with-dyns [:pretty-format "Inside with-dyns: %.20P"]
(pp [1 2 3]))
(pp [1 2 3]) # prints "[1 2 3]"
(pp [1 2 3]) # prints "(1 2 3)"
```

## When to use dynamic bindings

Dynamic bindings should be used when you want to pass around an implicit, global
context, especially when you want to automatically reset the context if an error
is raised. Since a dynamic binding is tied to the current fiber, when a fiber
exits the context is automatically unset. This is much easier and often more
efficient than manually trying to detect errors and unset context. Consider the
following example code, written once with a global var and once with a dynamic
binding.
Dynamic bindings should be used when you want to pass around an
implicit, global context, especially when you want to automatically
reset the context if an error is raised. Since a dynamic binding is
tied to the current fiber, when a fiber exits the context is
automatically unset. This is much easier and often more efficient than
manually trying to detect errors and unset the context. Consider the
following example code, written once with a global var and once with a
dynamic binding.

### Using a global var

Expand Down
10 changes: 5 additions & 5 deletions content/docs/fibers/error_handling.mdz
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ its second clause.

@codeblock[janet]```
(try
(do
(print "inside block...")
(error "oops")
(print "will never get here"))
([err] (print "caught error: " err)))
(do
(print "inside block...")
(error "oops")
(print "will never get here"))
([err] (print "caught error: " err)))
```

### @code`protect`
Expand Down
17 changes: 9 additions & 8 deletions content/docs/fibers/index.mdz
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ fiber yields or throws an error, control is returned to the calling fiber. The
parent fiber must then check what kind of state the fiber is in to differentiate
errors from return values from user-defined signals.

To create a fiber, user the @code[fiber/new] function. The fiber constructor
take one or two arguments. The first, necessary argument is the function that
the fiber will execute. This function must accept an arity of zero. The next
optional argument is a collection of flags checking what kinds of signals to
trap and return via @code[resume]. This is useful so the programmer does not
need to handle all different kinds of signals from a fiber. Any un-trapped
signals are simply propagated to the previous calling fiber.
To create a fiber, use the @code[fiber/new] function. The fiber
constructor takes one or two arguments. The first argument (required)
is the function that the fiber will execute. This function must accept
an arity of zero. The next argument (optional) is a collection of
flags checking what kinds of signals to trap and return via
@code[resume]. This is useful so the programmer does not need to
handle all of the different kinds of signals from a fiber. Any
untrapped signals are simply propagated to the previous calling fiber.

@codeblock[janet](```
(def f (fiber/new (fn []
Expand All @@ -55,7 +56,7 @@ signals are simply propagated to the previous calling fiber.
## Using fibers to capture errors

Besides being used as coroutines, fibers can be used to implement error handling
(ie: exceptions).
(i.e. exceptions).

@codeblock[janet](```
(defn my-function-that-errors []
Expand Down
Loading