-
Notifications
You must be signed in to change notification settings - Fork 4
Description
Currently, Jeeves uses do
blocks after update_state
.
This is flexible, as it allows you to use multiple statements after updating the state.
The README gives some examples.
Using the "full" do
block:
defmodule Fib do
# ...
def fib(n) do
case cache[n] do
nil ->
fib_n = fib(n-2, cache) + fib(n-1, cache)
update_state(Map.put(cache, n, fib_n)) do
fib_n
end
cached_result ->
cached_result
end
end
end
Using the "abbreviated" do
block:
defmodule FibCache do
# ...
def put(n, fib_n) do
state
|> Map.put(n, fib_n)
|> update_state(do: fib_n)
end
end
This doesn't read very well to me, and it's not clear at a first glance what is a state update and what is a return value. However, if you really want to have multiple statements after updating the state, then maybe there are no alternatives.
But how often does one want multiple statements in practice?
If we don't need multiple statements, then we can drop the block and use a more descriptive keyword, like :returning
.
This would give use more "user-friendly" versions:
defmodule Fib do
# ...
def fib(n) do
case cache[n] do
nil ->
fib_n = fib(n-2, cache) + fib(n-1, cache)
# Changed line:
update_state Map.put(cache, n, fib_n), returning: fib_n
cached_result ->
cached_result
end
end
end
defmodule FibCache do
# ...
def put(n, fib_n) do
state
|> Map.put(n, fib_n)
# Changed line:
|> update_state(returning: fib_n)
end
end
Note that now only the keyword form is supported, and everything is made uniform.
An alternative approach would be to flip things around and have a macro (or function, depending on the way Jeeves is implemented) like return
that takes a value to return and a :with_new_state
keyword that allows you to write:
defmodule Fib do
# ...
def fib(n) do
case cache[n] do
nil ->
fib_n = fib(n-2, cache) + fib(n-1, cache)
return fib_n, with_new_state: Map.put(cache, n, fib_n)
cached_result ->
cached_result
end
end
end
Unlike the update_state
form, in which the new state is fundamental and the return value feels like an afterthought, in the return
form, the return value is fundamental and the new state is the afterthought.
I prefer the update_state
form, but that's very subjective.
These are mostly cosmetic changes to the API, and maybe they are a little irrelevant, but in my opinion they might enhance readability. Losing the ability to use do blocks doesn't feel like a big deal.