This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-08
Channels
- # 100-days-of-code (1)
- # announcements (7)
- # beginners (63)
- # cljs-dev (39)
- # clojure (78)
- # clojure-dev (40)
- # clojure-italy (4)
- # clojure-nl (22)
- # clojure-russia (5)
- # clojure-spec (5)
- # clojurescript (60)
- # cursive (8)
- # datomic (6)
- # emacs (1)
- # figwheel-main (53)
- # fulcro (19)
- # jobs-discuss (11)
- # mount (1)
- # off-topic (3)
- # om (1)
- # pedestal (9)
- # philosophy (1)
- # re-frame (19)
- # reagent (4)
- # reitit (5)
- # shadow-cljs (66)
- # tools-deps (64)
What’s an easy way to read-in the contents of an edn-file with a hash-map, keeping the order?
The best I have currently, is to read it as a string, and replace the {
and }
with [
and ]
… which is not pretty
Hashmaps aren’t ordered, so directly read-string
’ing it will only work up to a certain size, and even that is only luck, and might change with Clojure 1.x.
something like this works (into (sorted-map) (clojure.edn/read-string (slurp "test.edn")))
But (clojure.edn/read-string (slurp "test.edn"))
will be evaluated first, and at that point you have no guarantee of the order?
grav, you want to keep the order from the file, right?
you should have read mavbozo's example a bit more carefully 😉
ah ok, so if the content of your file is this {:a 1, :c 3, :b 2}
then the result is [[:a 1] [:c 3] [:b 2]]
?
I guess what I need is something that parses the edn file as a structure and not a hashmap, so that I can extract the order
you could just replace {}
with []
and then call partition 2
on the vectors
hopefully you don't have any vectors in there you don't want to partition
@grav for me this is interesting problem. what problem domain are you working on that requires you to maintain the order of the hash-map in the edn file? I'm assuming you don't have any control on the edn file creation
@timo.freiberg It does contain vectors, but only replacing the first {
and last }
ought to solve that.
@mavbozo I often run into hashmaps (either in code or in edn files) where the order was thought to matter by whoever created the map (by accident), so easily extracting the order would be pretty nice. I guess the best solution is, as @timo.freiberg suggests, to perceive it as a string and then “fix” the data-structure.
i hope this isn't an XY problem 🙂
Thinking of it again, I guess there is a less specific problem hidden in there, namely parsing a string as a list of symbols. I’m wondering if there’s anything in Clojure that will help me there.
I am experimenting with the prepl
and since there is not a prepl channel I’ll ask here
I know I can replace pr-str
with another function but want to avoid - if possible - writing a whole bunch of code if there is already a simple, known solution 🙂
in other words, rather than replacing pr-str
with my own code, is there something that exists to save me the work? Yes I’m lazy!
@grav 'rewrite-clj' parses files as individual tokens (as well as whitespace), here's what I managed to get:
(ns test-rewrite
(:require [rewrite-clj.parser :as p]
[rewrite-clj.node :as n]
[rewrite-clj.zip :as z]))
(def pp (p/parse-string "{:a 1 :c 2 :b 3 :e [1 2 3]}"))
pp
;; #rewrite_clj.node.seq.SeqNode{ ... }
(n/child-sexprs pp)
;; (:a 1 :c 2 :b 3 :e [1 2 3])
(map vec (partition 2 (n/child-sexprs pp)))
;; ([:a 1] [:c 2] [:b 3] [:e [1 2 3]])
(vec (map vec (partition 2 (n/child-sexprs pp))))
;; [[:a 1] [:c 2] [:b 3] [:e [1 2 3]]]
There's probably an easier way to read tokens with a normal edn reader instead, though
@spacemods Ah, very nice! I actually went ahead and wrote one that just mangles strings: https://gist.github.com/grav/a89bef351683ce4ded2b36615548ca30 But handling tokens seems more sane, at least in the general case 🙂
Interesting question from a C# friend of mine about game dev: In Clojure, how do you handle multiple, seperate enemies which all have the same default variables without OOP/inheritance?
just a base map and a merge @coinedtalk?
(def game-state (atom {})) ?
and enemies {}
is that what you mean?
mm no no
(def common-traits
{:height 100
:strength 200})
(def gen-traits
[custom]
(merge common-traits custom))
hmm, and something like this would make sense?
{:type "Monster" {:type "Plant-based" {:type "Green"}}}
lets say I have established a monster template with your code, how do I spawn one? Create a protocol for handling movement,etc? or
if these things are orthogonal probably
{:types [:monster :plant-based :green]}
and well it depends on what you are doing, here we were just talking about how to set some attributes to a monster
the actual game logic depend on what are you programming for, but the idea is that you should leave the side effects as much as possible out of the way
so avoid thinking about atoms too much
many thanks, I'm mainly wondering what the next step would be to spawning unique monsters and running movement methods on them. looking at defprotocol... defmethod etc
defmulti
and the corresponding defmethod
sounds like a good choice
but keep in mind that it's nothing magic, you could the same dispatching with a map that you write yourself
(def action {:monster (fn [_] (attack!))...)
hmm, how would that work if there's multiple monsters
that's just an example of dispatching a function based on a keyword
it wasn't really realistic code
got it, I'll go with defmulti and defmethod 🙂
First hit in Google search for "clojure syntax-rules" shows this Github repo: https://github.com/qbg/syntax-rules I haven't used it, and don't know whether it is considered complete or mostly-bug-free.
thank you, @andy.fingerhut , i'm aware of this project, but it seems to be quite different from scheme's syntax-rules (i have not really dug into it)
Not sure which aspect you are looking for, but with clojure.spec created after that lib was, one aspect of Clojure macros that is (arguably) improved is better specification and checking of the syntax of macros.
It doesn't change how macros are implemented, though.
I agree that spec can help with macros, but i really like the conciseness of syntax-rules
and it would make some crazy scheme easier to port (like http://okmij.org/ftp/Scheme/macros.html#ck-macros)
Are refs prefered when building a queue? I need to make sure 2x items are not getting into the same batch.
i am currently using an agent since I want to do things when items are added to the vector (using add-watch)
I have a solution using that one. I would use this solution if I didn't have to be able to cancel and remove items from the queue.
Im leaning more towards a core.async solution right now