Re: Writing a text adventure in Clojure

2018-04-02 Thread Mikhail Gusarov
Hello Will.

You can simplify it further:

1. Define a multimethod always dispatching by room id.
2. Create a :default implementation. It will be called for non-
   fancy rooms.3. Create an implementation for :fancy-room. It will be 
preferred over
   :default for it.
If you ever have a group of rooms with a similar fancy description, use
a hierarchy
(derive :fancy-room1 :fancy-group)
(derive :fancy-room2 :fancy-group)

and create an implementation for :fancy-group.

Regards, Mikhail.

On Mon, 2 Apr 2018, at 19:39, Will Duquette wrote:
> Spent the weekend pondering all of this, and here's the way I think I
> want to do it.> 
> 1. The world-state is stored in an atom, and updated much as Gary
>Johnson suggests.> 
> 2. I define a multi-method, (describe-room [room world-state]), that
>is responsible for computing the current description of the room:
>what it looks like, what items are in it, whatever the player can
>currently see or has just noticed.> 
> 3. The multi-method's dispatch function looks for the :description.> 
> 3a. If it's a string, the dispatch function returns nil; and I get
> the default implementation: it describes the room in the simplest
> possible way.> 
> 3b. If the :description is undefined or nil, the dispatch function
> returns the room's id, e.g., :fancy-room.  The :fancy-room definition
> includes an implementation of the multi-method that's specific to the
> :fancy-room.  I wouldn't expect to use this approach all that often,
> but it should be flexible enough to do anything that comes up.> 
> 3c. If I find that I have a number of standard flavors for how to
> describe a room, I can define the dispatch function accordingly and
> add additional implementations.> 
> There are other ways to skin this cat; but this one seems to give me
> maximum simplicity for the normal case, maximum flexibility for
> special cases, and it lets me keep all of the logic related to a
> single room in one place in the code.> 
> Comments?
> 
> On Thursday, March 29, 2018 at 3:45:02 PM UTC-7, Will Duquette 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?
> 


Re: [?] Adding my own function to clojure.core namespace

2018-02-25 Thread Mikhail Gusarov
Hello Philos,

> For example , I wrote debux ( https://github.com/philoskim/debux ) 
> library. I want to use it only in development, not in production. If I 
> 'require' debux in source code to use it in development, I have to 
> remove it in the source code manually in production.

Do you intend to use this library from REPL or from the code itself?
If former, you can add the library to Leiningen (or whatever) REPL environment.
If latter, how do you enable/disable the debugging code in production? You can
use the same way for requiring/not requiring library.

> I tested your recommendation in REPL and it worked. However could you 
> tell me about how I can implement it in source code form, not in REPL?

There is no difference.

Regards,
Mikhail.

On Sun, 25 Feb 2018, at 13:01, Philos Kim wrote:
> Thanks both of you!
> 
> I know it is not desirable but it is sometimes needed, especially in my case.
> 
> For example , I wrote debux ( https://github.com/philoskim/debux ) 
> library. I want to use it only in development, not in production. If I 
> 'require' debux in source code to use it in development, I have to 
> remove it in the source code manually in production.
> 
> I tested your recommendation in REPL and it worked. However could you 
> tell me about how I can implement it in source code form, not in REPL?
> 
> -- 
> 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: [?] Adding my own function to clojure.core namespace

2018-02-24 Thread Mikhail Gusarov
Hello Philos,

It's no different to adding a function to any other namespace:

% clj
Clojure 1.9.0
user=> (ns clojure.core)
nil
clojure.core=> (defn foobar [x] (str "foobar " x))
#'clojure.core/foobar
clojure.core=> (ns user)
nil
user=> (foobar "12")
"foobar 12"
user=> foobar
#object[clojure.core$foobar 0x43b6123e "clojure.core$foobar@43b6123e"]
user=>

However is it truly a good idea?

On Sun, 25 Feb 2018, at 07:08, Philos Kim wrote:
> Is there any way to add my own function to clojure.core namespace? 
> Because I want to use that function globally without 'require' or 'use'. 
> 
> Thanks in advance.
> 
> -- 
> 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: If Clojure is to blame for the majority of the startup time, why doesn't ClojureScript proportionally slow down the JavaScript startup time also?

2018-01-25 Thread Mikhail Gusarov
cljs vars are not reified.

On Thu, 25 Jan 2018, at 18:24, Didier wrote:
> Based on the profiling performed here 
> http://clojure-goes-fast.com/blog/clojures-slow-start/ on 1.9,
> 
> It looks like clojure/core__init.load is the slowest bit with load and 
> requiring spending the most time on, as well as loadClass, followed by 
> clojure/lang/Var.invoke.
> 
> Wouldn't ClojureScript also need to initialize all Vars and execute top 
> level forms? You'd think that part would be slower in JavaScript no?
> 
> -- 
> 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: Understanding remove-ns and require

2017-12-22 Thread Mikhail Gusarov


On Fri, 22 Dec 2017, at 18:41, Stuart Sierra wrote:
> Also be aware that AOT-compilation[1] causes all sorts of havoc with
> namespace reloading, because AOT-compiled .class files get read by a
> different ClassLoader.> 

Is there any place explaining how exactly Clojure compiles and loads the
code? It always feels like magic (especially when it does not work).
Names of source code files work too.

Links:

  1. https://clojure.org/reference/compilation

-- 
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: Unexpected behaviour of transient map

2017-11-25 Thread Mikhail Gusarov
Hello.

The reader of any particular docstring cannot be expected to magically
know that there is another, better, piece of documentation.
Regards, Mikhail

On Sat, 25 Nov 2017, at 02:10, Timothy Baldridge wrote:
> But this behavior is already documented in the official transients
> overview at http://clojure.org/transients> 
> On Fri, Nov 24, 2017 at 5:46 PM Matching Socks
>  wrote:>> I would go so far as to (light-heartedly) 
> call the "assoc!" docstring
>> booby-trapped.>> 
>> There is an open issue in Jira for it.  Go vote:
>> https://dev.clojure.org/jira/browse/CLJ-1385>> 
>> 


>> --
>>  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[1]
>>  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.
> -- 
> “One of the main causes of the fall of the Roman Empire was
> that–lacking zero–they had no way to indicate successful termination
> of their C programs.”> (Robert Firth)
> 


> --
>  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.


Links:

  1. mailto:clojure%2bunsubscr...@googlegroups.com

-- 
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: Doc strings for complex cases?

2017-11-09 Thread Mikhail Gusarov
Hello.

> Should any breaking changes occur in Clojure core,

Why should they?

Regards,
Mikhail.

-- 
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: Clojure.spec, maps, restrict valid keywords, easier way?

2017-02-02 Thread Mikhail Gusarov

Hello Alex,

The idea is (as I understand it) that every function should accept any
map and pick keys which it understands. If some keys are critical, then
they should be marked as such in the spec.

Function might iterate over keys and raise an error if there are keys
which belong to the namespace function cares about, but the names are
not known, but it is outside of spec's functionality and ought to be
done manually.

Best regards,
Mikhail.

On 2 Feb 2017, at 18:27, Dave Tenny wrote:


On Thursday, February 2, 2017 at 10:07:31 AM UTC-5, Alex Miller wrote:


We don't encourage you to do this, but I don't have an easier 
solution

than this.



Yes, and from the general standpoint of map handling I understand 
that.


From the standpoint of functions that take options and don't pass 
option
maps through to other functions, I disagree with the clojure 
philosophy
here.  So many bugs could be caught if we flagged unexpected map keys 
when
they're used as options to functions.  Of course use and validation 
via

clojure.spec helps too, but from a general bug catching standpoint I
believe there's a huge value to flagging inputs to functions that 
aren't

recognized by the functions.

--
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.