Re: Writing a text adventure in Clojure
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
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
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?
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
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
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?
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?
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.