Reputation: 93
I have a list of I/O functions to run in a game, but need to collect the value from a function somewhere in the middle of the do
(defn setup-steps [game-state]
(do (io/clear-screen)
(print-welcome-message)
(initial-setup) ;; value to be collected
(io/clear-screen)
(io/print-board game-state)))
Is there a smart way to return the value from somewhere in the middle of a do
?
Down the line, I am using the return value of setup-steps
to update an atom, like so:
(defn game-loop [game]
(while (:game-in-progress? @game)
;; Here is where I am using the results
(->> (s-io/setup-steps @game) (state/updater game))
(while (:game-in-progress? @game)
(->> (m-io/turn-steps @game) (state/updater game)))
(->> (eg-io/end-game-steps @game) (state/updater game)))
(eg-io/exit-game))
Where
(defn updater
"Updates the game state.
This is the only place where the game atom is modified."
[game update-params]
(swap! game merge update-params))
I'm sure you could write a macro for this, but I don't really understand macros yet.
And maybe I am thinking about this the wrong way... Is it more idiomatic to dow the swap!
ing inside setup-steps
?
Upvotes: 1
Views: 182
Reputation: 91857
Fundamentally the only way to do this is with let
, as clartaq shows. But if you find this distasteful there are a number of ways you could wrap this up in a macro to make it prettier to look at and also more clear about what you're doing. Here is the simplest one, which I like to call returning
:
(defmacro returning [x & more]
`(let [x# ~x]
(do ~@more)
x#))
(defn foo []
(x)
(y)
(returning (z)
(a)
(b)))
The do
in returning
is of course superfluous, but I think it's still useful to emphasize that more
is evaluated only for side effects.
Upvotes: 3
Reputation: 5372
Any reason you can't assign the result in a let
and return it at the end of the function?
(defn setup-steps [game-state]
(io/clear-screen)
(print-welcome-message)
(let [v (initial-setup)] ;; value to be collected
(io/clear-screen)
(io/print-board game-state)
v))
EDIT: Got rid of the redundant do
that Ryan Asensio mentioned.
Upvotes: 7