Fork me on GitHub

I'm trying to get the duration of some mp3 files, anyone around that can point me in the right direction for doing that with clojure?


Yeah thats what I came across as well. Looks like thats what I'll be going with, thanks


There is some static clojure parser, that support reader macros, reader-eval and maybe read some "unreadble" things like #object[...]

Alex Miller (Clojure team)15:05:35

in what way do or tools.reader not satisfy the bill?


(LispReader/read (new PushbackReader (io/reader (.getBytes "[#=(prn :ok)]"))) {})
;; -- expected
;; => [#reader-eval (prn :ok)]
;; -- actual
;; :ok ;; printed
;; => [nil]

Alex Miller (Clojure team)15:05:11

so you want read-eval to not eval?

😬 4
Alex Miller (Clojure team)15:05:42

well then, no that doesn't exist afaik :)


maybe rewrite-clj can read that?


it even preserves comments and whitespace


I will look too. But tools.reader seems to be OK for now


depending on how desperate you are

user=> (require '[ :as r])
user=> (defrecord reader-eval [v])
user=> (with-redefs-fn {#'r/read-eval (fn [rdr _ opts pending-forms] (reader-eval. (#'r/read* rdr true nil opts pending-forms)))} #(r/read-string "[#=(prn 1)]"))
[#user.reader-eval{:v (prn 1)}]

👍 4

(binding [*default-data-reader-fn* (fn [tag value]
                                                          {:tag tag :value value})]
  (with-redefs [ (fn [rdr _ opts pending-forms]
                                                 (#'* rdr true nil opts pending-forms))]
      {:read-cond :preserve}
      "[#=(prn :ok) #[email protected](:clj [1] :cljs [2]) #object[] ::foo]")))
I think that I will use tools.reader


Just need to figure out how to "patch" ::foo/bar to return something like #namespaced-keyword [foo :bar]

Alex Miller (Clojure team)15:05:51

the resolver is pluggable, so you can do that

Alex Miller (Clojure team)15:05:14

well, maybe not that pluggable


not quite sure what a good pluggable mechanism for this would be that avoids exposing the entirety of read-keyword


but I'm open to suggestions

Alex Miller (Clojure team)16:05:50

may I suggest that you don't do that? :)

😂 4
😕 4

I think that I found a bug

  {:read-cond :allow}
  "[#?(:cljs #=(prn :ok) :default 1)]")

Alex Miller (Clojure team)19:05:06

don't you want :read-cond :preserve ?

Alex Miller (Clojure team)19:05:44

well, maybe I'm ahead of you - what do you get and what do you want?


ATM I'm just playing and understanding how works Then I see that reader-eval occur in all reader-cond branches


I'm trying antlr now


I’m looking for design advice on a feature. I’m writing some code which hits a REST API. The interface to that API exposes some abstractions like “tags”, which are strings. I want to my code to hide those strings behind a mapping, so that the caller of my namespace can pass in data (which I could spec) which will be replaced with the correct string before calling the HTTP endpoint. For abstracting over the tags, should I be using … vars? I could write a namespace that just defs each string and have the caller pass those as arguments. Or maybe just normal keywords, instead? Maintaining a mapping of keyword to string for the tags. Do namespaced keywords make sense here?


if tags is an open set of strings then I would just leave them as strings


strings are a very flexible first class data type


the thing is they’re kind of all over the place — they’re tags on some products. So the punctuation and casing and whitespace is inconsistent. I was hoping to design so the caller doesn’t have to know if the “christmas” tag is “Christmas” or “XMAS” or whatever, they can just say tags/christmas or :christmas


plus then if the tag itself changes, which is fairly likely to happen (maybe there is an effort to make them more consistent), I can change the value in one spot instead of searching for all occurrences


I think then that means it’s a closed set from my code’s perspective?


I have timeseries data that is a collection of events. the data is sparse, that is for certain timeframes there are no events. how am I supposed to build on this? do I let the collection with a lot of nil propagate through the system and put nilchecks everywhere? or should I treat the whole timeseries data as a function of time?


maybe a sorted set, sorted by timestamp? that makes grabbing all items between times X and Y cheap


while avoiding any need for keys with nil values


(cmd)user=> (sorted-set-by #(compare (:t %1) (:t %2)) {:t 0 :a 12} {:t 1 :a 3} {:t 4 :a 0} {:t 8 :a 1})
#{{:t 0, :a 12} {:t 1, :a 3} {:t 4, :a 0} {:t 8, :a 1}}
(cmd)user=> (def s *1)
(cmd)user=> (subseq s > {:t 0} < {:t 5})
({:t 1, :a 3} {:t 4, :a 0})

✔️ 12

the first arg to sorted-set-by needs to be a comparator of two events


subseq takes the sorted set, and two comparison functions / compared item pairs (it can also take a single pair)


instead of saying "what's the data at time t" you'd say "what are the known data points between t and t'"


hmmm let me see how this works out.


you can do the same with a sorted-map with timestamps as keys


whatever the representation, you shouldn't have nils laying around


like, in general, if I had a time series of data it would just be a collection of events, and any time period where there were no events, well there just wouldn't be events from that time period in the collection


if you need to reify your notion of time periods, then you have a set of time periods, and each event refers to a timeperiod, so a time period with no events would be added to the set of time periods, but have not events referencing it


To expand about nils, this is just for data, functions returning nil is perfectly fine correct? (As long as it doesn't leak into data)


ini either case no weird nils

✔️ 4