Re: Macro usage within Clojure community and naming functions which perform actions under certain conditions

2016-05-04 Thread Fluid Dynamics
What about:

safe-cell? (as described)
reveal-safe-cells (as existing)

(defn reveal-safe-cells-if-safe-cell [gs]
  (if (safe-cell? gs)
(reveal-safe-cells gs)
gs))

and elsewhere

(-> gs
  ...
  ...
  (reveal-safe-cells-if-safe-cell)
  ...
  ...)

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Macro usage within Clojure community and naming functions which perform actions under certain conditions

2016-04-26 Thread Jason Felice
I wrote packthread to avoid needing threading counterparts of a bunch of
control forms - it rewrites threading through control forms.

https://github.com/maitria/packthread

It doesn't (yet) solve when you need the threaded value in the middle of a
threading form.  I've had some thoughts about threading, monads, and macros
that I need to sort out (I'd rather not do something anaphoric).  But it
does avoid the combinatorial problem you are seeing when you are trying to
combine cond-> with as->.

-Jason



On Tue, Apr 26, 2016 at 3:16 AM, Ray Miller  wrote:

> On 25 April 2016 at 21:03, Rafał Cieślak  wrote:
>
>> 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.
>>
>>
> You don't need a macro for this sort of thing, and can get some way with
> reduce. For example:
>
> (defn apply-conditional-actions
>   [game-state & pred-actions]
>   (reduce (fn [game-state [pred action]]
> (if (pred game-state)
>   (action game-state)
>   game-state))
>   game-state
>   (partition 2 pred-actions)))
>
> Then call this function with the game-state and a list of pred/action
> pairs:
>
> (apply-conditional-actions game-state
>safe-cell? reveal-safe-cells
>monster-killed? inc-exp-points)
>
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> 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 clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Macro usage within Clojure community and naming functions which perform actions under certain conditions

2016-04-26 Thread Ray Miller
On 25 April 2016 at 21:03, Rafał Cieślak  wrote:

> 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.
>
>
You don't need a macro for this sort of thing, and can get some way with
reduce. For example:

(defn apply-conditional-actions
  [game-state & pred-actions]
  (reduce (fn [game-state [pred action]]
(if (pred game-state)
  (action game-state)
  game-state))
  game-state
  (partition 2 pred-actions)))

Then call this function with the game-state and a list of pred/action pairs:

(apply-conditional-actions game-state
   safe-cell? reveal-safe-cells
   monster-killed? inc-exp-points)

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Macro usage within Clojure community and naming functions which perform actions under certain conditions

2016-04-25 Thread Rafał Cieślak
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-> 
 which let's you access the 
current value. In fact, there have been several threads about such macros 
on this group (example 
).

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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.