Hi,
I'm writing a turn-based game and one of the biggest functions is the one
which handles player moves. It receives the current game state (a map) and
the index of the cell that the player clicked on (an integer).
It has to make a couple of decisions based on the game state. So far I just
used -> and cond->. The code looks more or less like this, I removed a
bunch of function calls for brevity.
(-> game-state
; This stuff happens on each move.
(reveal-cell cell-index)
; And this stuff happens only under certain conditions.
(cond->
(zero? (:surrounding-power cell))
(reveal-safe-cells cell-index)))
The code looks clear IMHO. But then I wanted to add another feature which
requires me to make decisions based on the updated value of game-state (the
one that is being threaded inside cond->).
I thought about cond-> a bit and came to the conclusion that the reason you
can't access the currently threaded value is to keep you from writing
order-dependent statements. But in my case, I sometimes do want to write
order-dependent code. For example, I want to give player exp for killing a
monster and then if the exp is above certain threshold, I want to level up
his character.
So the problem is that I have to check the current value being threaded,
but cond-> doesn't allow me to do that.
As I understand, I can solve it in two different ways. For both of them I
have a couple of questions as I'm fairly new to Clojure.
1. Use a custom macro like condas->
<https://juxt.pro/blog/posts/condas.html> which let's you access the
current value. In fact, there have been several threads about such macros
on this group (example
<https://groups.google.com/d/msg/clojure/0VXc57SFa0s/vR_4NJD4BwAJ>).
My problem with this solution is that I'm going to depend in my code on a
new macro. If somebody else looks at this code, they'll first have to
understand condas-> and perhaps the reason it was brought to the project. I
think that a brand new macro for such a simple problem is a bit too much. *Is
it usual within the Clojure community to resort to custom macros so early?*
2. Remove cond-> and use functions which check a predicate on game-state:
if it's false, the function returns the current game-state, if it's true
the function updates the game state.
The main body will look like this:
(-> game-state
(reveal-cell cell-index)
(reveal-safe-cells cell-index))
Here I have two problems:
a) All predicate-checking functions in the main body will have to be
rewritten to the following form:
(if pred
(update-state game-state)
game-state)
That's the best case scenario, because I guess some of the more complicated
functions may look like this:
(if-let [foo (:bar game-state)]
(if (and
(baz? foo)
(fizz? foo))
(update-state game-state foo)
game-state)
game-state)
Now this is not a dealbreaker. I can certainly cope with that. *Maybe there
are better ways to express that? *I don't know. But, the second problem is
a bit more complex for me.
b) The functions will have to be renamed.
Let's look at reveal-safe-cells. The function does what the name says. The (
zero? (:surrounding-power cell)) predicate could be put into a function
called safe-cell?. Now I would really like to have two separate functions –
one that checks if it's okay to do the thing and one that does the thing. *How
do I call the function which combines the two?*
If you look at the main body, by removing cond-> I just hid the fact that
certain actions will be performed only under certain conditions.
reveal-safe-cells needs to combine the action and the predicate, so it'd be
good if its name revealed the intention.
That's it. Since I'm still learning Clojure, I'd like to get some feedback
on what things are okay or not for other Clojure developers. I'm looking
forward to the "Elements of Clojure" release, as it already answered many
of my questions.
--
Cheers,
Rafał
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.