Thanks! I've glanced at Land of Lisp, actually, some while back.  I might 
even have a copy.  

To be clear, it isn't LISP that's giving me problems.  I've been dabbling 
with LISP on-and-off since the '80's, and I've read a couple of Paul 
Graham's books.  I understand code-as-data, and lambdas, and I even grok 
macros.  It's specifically Clojure's functional programming model that I 
need to wrap my head around. 

On Friday, March 30, 2018 at 5:41:27 AM UTC-7, Tim Visher wrote:
>
> http://landoflisp.com/ is specifically about coding games in Lisp, in 
> case you're into books. :)
>
> On Thu, Mar 29, 2018 at 6:45 PM, Will Duquette <wi...@wjduquette.com 
> <javascript:>> wrote:
>
>> I'm an experienced programmer, but a Clojure newbie; as a beginner 
>> project, I'm looking into how one would idiomatically write a text 
>> adventure of sorts in Clojure.  I'm less interested in producing a playable 
>> game than I am in learning how to do such a thing in a proper functional 
>> style.
>>
>> Suppose in this game I have a room whose description changes based on a 
>> global flag.  For example, there's something in the Fancy Room that you 
>> won't notice until you've reached the major plot point.
>>
>> The world map is (for the sake of argument) a hash-map whose keys are the 
>> room IDs and whose values are room records, where each record is a hash-map.
>>
>> (def world {:fancy-room {:name "Fancy Room" :description "This is a fancy 
>> room." ...}})
>>
>> I'm aware that I could use a (defstruct) or (defrecord); I'm keeping it 
>> simple for now.  Then, the flags are saved in a ref; the intent is that 
>> mutable set is segregated, so that it can more easily be written to a save 
>> file.
>>
>> ;; Global set of flags
>> (def flags (ref #{})
>>
>> (defn flag-set [flag]
>>    (dosync (alter flags conj flag))
>>
>> ;; When the major plot point is reached
>> (flag-set :major-plot-point-reached)
>>  
>> Normally, to describe a room you just return its :description.
>>
>> (defn describe [room] (:description (world get room)))
>>
>> But for the :fancy-room, the returned description depends on the global 
>> flag, and it will be specific to :fancy-room.  I could add this logic 
>> directly to the (describe) function's body, but that would be ugly.  What 
>> I'd like to do is attach a lambda to the :fancy-room in some way.  The 
>> (describe) function looks for a :describer, and if it's there it calls it; 
>> and if not it just returns the :description:
>>
>> (defn describe [entity]
>>     (if (:describer entity) 
>>       ((:describer entity) entity)
>>       (:description entity)))
>>
>> *Question 1*: this works, but it looks ugly to me; I figure there's a 
>> better, more idiomatic way to do this kind of thing that's probably obvious 
>> to anyone with any real experience.  Multimethods, maybe?  Define a Room 
>> protocol, then let most rooms be NormalRoom records, but let :fancy-room be 
>> a FancyRoom record?
>>
>> *Question 2*: Whatever code actually computes the description, it will 
>> need access to the :major-plot-point-reached flag.  What's the cleanest way 
>> to give the description code access to the flags ref?  It could simply 
>> access "@flags" directly:
>>
>> (if (:major-plot-point-reached @flags) 
>>   "This is a fancy room.  Hey, that light sconce looks movable!"
>>   "This is a fancy room.")
>>
>> But that doesn't seem properly functional.  Would it be better to pass 
>> the game state into each method?
>>
>> (defn describe [entity state]
>>   (if (:describer entity)
>>      ((:describer entity) entity state)
>>      (:description entity)))
>>
>> Any ideas?
>>
>> -- 
>> You received this message because you are subscribed to the Google
>> Groups "Clojure" group.
>> To post to this group, send email to clo...@googlegroups.com 
>> <javascript:>
>> Note that posts from new members are moderated - please be patient with 
>> your first post.
>> To unsubscribe from this group, send email to
>> clojure+u...@googlegroups.com <javascript:>
>> 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+u...@googlegroups.com <javascript:>.
>> 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.

Reply via email to