This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-10-16
Channels
- # 100-days-of-code (1)
- # announcements (1)
- # beginners (93)
- # boot (46)
- # cider (40)
- # cljdoc (4)
- # cljs-dev (7)
- # clojure (78)
- # clojure-conj (12)
- # clojure-dev (17)
- # clojure-italy (5)
- # clojure-nl (10)
- # clojure-spec (34)
- # clojure-uk (36)
- # clojurescript (56)
- # code-reviews (6)
- # core-async (31)
- # cursive (12)
- # datascript (9)
- # datomic (19)
- # devops (2)
- # editors (3)
- # emacs (6)
- # events (2)
- # figwheel (1)
- # figwheel-main (11)
- # fulcro (59)
- # graphql (10)
- # hyperfiddle (3)
- # keechma (5)
- # leiningen (26)
- # luminus (1)
- # nrepl (5)
- # re-frame (5)
- # reitit (10)
- # shadow-cljs (64)
- # spacemacs (29)
- # tools-deps (6)
- # uncomplicate (8)
- # vim (2)
- # yada (4)
So I was experimenting with writing the following function into a transducer. The function takes in a collection of geographic points then returns a collection where each point is guaranteed to be x distance away from any other point. The input collection is larger than the output collection because I get rid of any points that are too close together. First I create the RTree, then put a point into the tree. On the next points, I check to see whether it's near any of the points already in the tree. If it is far enough away I put it into the tree, if not I discard it. Through function composition, I also want to do other transformations on the points in addition to spacing them out.
(defn space
([distance]
(fn [rf]
(let [treev (volatile! (RTree/create))]
(fn
([] (rf))
([result] (rf result))
([result input]
(let [point (seed->point input)]
(if (nearby-point? point @treev distance)
result
(do (vswap! treev .add nil point)
(rf result input)))))))))
([distance seeds]
(loop [tree (RTree/create)
seeds seeds
spaced-seeds []]
(if (not (empty? seeds))
(let [seed (first seeds)
point (seed->point seed)]
(if (nearby-point? point tree distance)
(recur tree (rest seeds) spaced-seeds)
(recur (.add tree nil point)
(rest seeds)
(conj spaced-seeds seed))))
spaced-seeds))))
What I thought was really interesting was the idea of focusing on the transformations in terms of an individual element of the collection. And in order to know whether to keep or point or not I need to maintain a state, kind of like how distinct or dedupe work.
so the transducer here doesn't pass on the structured tree, it is merely a filter for items that fit in the tree
also, I don't think you strictly need a collection here (despite your usage of the term in the description), but the main point of transducers is not relying on the existence of some collection - making that an implementation detail you don't need to care about
Right I'm using the RTree as a means to filter things. I don't want to store and retrieve from the RTree. I see what you're saying in the second comment.
I don't think that has any relevance to your design / the code as written, just a note about the description
I wonder how hard it would be to rewrite the transducer in terms of the filter transducer, with a function that does the tree check / update as appropriate? I don't know if the point here was to go through the exercise of making a transducer, but just using filter might be simpler.
also the loop in the non-transducing case would be simpler as a reduce - you can use a hash-map or even a vector to represent a multi-part state in reduce
another interesting exercise would be making the lazy version - it would look a lot like the loop version
I guess it is similar to filter because I have a predicate that determines what to pass along, but I need the additional code to maintain the state of the RTree.
right, but the state of the RTree is already a side effect, it can fit in a filtering function
the hard part would be if the output should / could contain a false
or nil
value, then basing it on filter would break
basing it on filter would also be a simple (but less instructive) way to make the lazy version - don't use filter to do the lazy version, as doing the RTree as a side effect with a volatile would break assumptions about lazy-seqs
but luckily laziness via recursion is straightforward, and allows using the RTree functionally as the gods intend
Oh I see, those are interesting things to think about (admittedly still trying to wrap my head around some of what you're saying). But I will definitely give making a lazy version a shot, and trying the reduce suggestion.
I definitely agree with that last comment lol
Oh I see how some other functions like remove use filter to build a transducer.
That is pretty neat
Hi, guys! 👋 I'm developing an SPA on reagent+re-frame, with reactive data flow, event-driven plus TDD http://dev.brawl.haus It's meant to be a platform for multiplayer games, challenges etc - some fun stuff There are two games yet though and those are more a tech demo of what can be done I thought on going live in 20 minutes, 12 am GMT at Twitch: https://www.twitch.tv/elvis_prevsley Would love to have people around to talk along the way!
Heys. That sounds fun, but it looks like I've missed it. I hope you had fun. Could you enable "Store past broadcasts" (they get saved for 14 days)? https://www.twitch.tv/elvis_prevsley/dashboard/settings
cool, I've been meaning to get started with twitch so I followed so I can hopefully catch you next time
see you on next rounds, guys.:)
I'm having trouble reading a value from a map using a string key supplied as a function parameter. Does this make sense?
(defn parse-command
[commands input]
(let [split (s/split input #" " 1)]
[first split [0]]
[second (fnil split [1] "")]
(partial (get commands first fallback-command) second)))
The following test always retrieves my fallback:
(deftest parses-command-and-args
(testing "Returns a command with its arguments supplied when it is in the command map"
(let [commands {:dummy-command (fn [a _] {:dummy a})}
parsed (parse-command commands "dummy-command 5")
result (parsed {})]
(is (= {:dummy 5} result)))))
EDIT:
For anyone interested, the following fixes were needed:
1. I made a mistake in my first function, it should read
(defn parse-command
[commands input]
(let [split (s/split input #" " 2)
first (nth split 0)
second (nth split 1 "")]
(partial (get commands first fallback-command) second)))
Secondly, you need to use string keys when you're feeding in a string:
(deftest parses-command-and-args
(testing "Returns a command with its arguments supplied when it is in the command map"
(let [commands {"dummy-command" (fn [a _] {:dummy a})}
parsed (parse-command commands "dummy-command 5")
result (parsed {})]
(println parsed)
(is (= {:dummy "5"} result)))))
Hi. Here are two alternative implementations of your parse-command
.
You could use the built in first
and second
functions.
(defn parse-command
[commands input]
(let [split (s/split input #" " 2)]
(partial (get commands (first split) fallback-command) (-> split second str))))
Or you could use destructuring.
(defn parse-command
[commands input]
(let [[comm args] (s/split input #" " 2)]
(partial (get commands comm fallback-command) (str args))))
Thanks, that destructuring version looks much simpler 🙂
Is anyone here familiar with the gloss
library for parsing binary formats?
As my first bit of Clojure code, I'm attempting to use it to parse the FLAC audio format. In the docs, it mentions the use of repeated
, but I can't figure out how to terminate on a frame's field value of what it reads. Here is my code, and line 47 shouldn't be a hard-coded stream-info block, but it should repeat until the :last?
field of the header it reads is 1
: https://gist.github.com/mfiano/04117773cc90e24845854aa32b9e2301 I'd appreciate any help. As I mentioned, I am extremely new to Clojure, and the docs for that library are a little lacking. I'm unsure if it lacks support to pull this off or not.
Edit: wrong link and line number
Hi! I have a trouble with my spacemacs cider plugin. It prints unreadable error log.
But this program works fine with vscode clojure plugin.. So my REPL is fine)
I bet vscode is picking a 1.8 jvm and cider is trying to use a newer one, based on the error messages
either that is vscode doesn't trigger the problems that cider hits with your vm
many of the common convenience tools break with newer jvms
Thanks, I’ll try to dig in this direction)!
@UCRM55BKM If its not the JVM or something in your .lein/profiles.clj
, it could be sayid
debugger causing a problem. If you are using Spacemacs develop
there was an issue, now fixed. Sayid and clj-refactor are now optional in Spacemacs develop
, although can be easily added back
https://practicalli.github.io/spacemacs/install-spacemacs/enhance-clojure-experience.html
Feel free to ask for more help in the #spacemacs channel
@U0BEJGE9Y thank you, for your attention! I manually installed sayid
now. but this error still exists.
This error occurres when I run cider-jack-in
in REPL buffers from the beginning
what about lein repl
in a terminal directly in the project?
it works fine
@mfiano I’m not familiar with the library, but is take-while
by any chance what you are looking for?
@rakyi I'm not either, and I'm not really sure if the forms inside the defcodec macro are evaluated to do so. This is more of a declarative approach
Given:
(defn score-command
[args game]
(let [[name score] (s/split args #" " 2)]
;; If we don't have a valid player and score, do not change the game state and print an error message
(if (or (nil? name) (nil? score) (not (integer? (read-string score))))
((println "Valid score command not supplied") game)
(let [parsed-score (read-string score)
name-as-keyword (keyword name)
highscore (max (get-in game [:players name-as-keyword :highscore] 0) parsed-score)
update { :name name
:score parsed-score
:highscore highscore}]
(assoc-in game [:players name-as-keyword] update)))))
This simple test
(deftest score-command
(testing "Inserts a user score into an empty map")
(let [result (score-command "Sam 5" {})]
(println result)))
Throws the error "No value supplied for key: true". I understand this is due to having mistmatched keys in the map assignment, but I'm not sure where as they look matched to me. In fact, removing the map assignment altogether doesn't get rid of the error, so I'm really not sure what the source is. Is it apparent to anyone else?You can't have nil in operator position
How do I print and return for an error check then? i.e. (if (guard) (print-and-return) (do-my-stuff))
"No value supplied for key: true" would happen when creating a map, which you aren't really doing there, so I suspect the error is happening somewhere else
As in, I literally have an identifier called "true" bound somewhere?
something like (ns foo (:require [:foo] true))
maybe (hard to reproduce if you have a clojure version that uses spec you get a different error)
My ns is just:
(ns game.lib
(require [clojure.string :as s
clojure.edn :refer read-string]))
Oops, so it should
the ns macro does very little validation of its inputs, new clojure versions atleast have spec checking the inputs
I'm perfectly happy to, I just use whatever lein
gave me. Do I just up my dependency on org.clojure
?
Exception in thread "main" clojure.lang.ExceptionInfo: Call to clojure.core/ns did not conform to spec:
In: [1] val: ((:require [clojure.string :as s clojure.edn :refer [read-string]])) fails spec: :clojure.core.specs.alpha/ns-form at: [:args] predicate: (cat :docstring (? string?) :attr-map (? map?) :clauses :clojure.core.specs.alpha/ns-clauses), Extra input
#:clojure.spec.alpha{:problems [{:path [:args], :reason "Extra input", :pred (clojure.spec.alpha/cat :docstring (clojure.spec.alpha/? clojure.core/string?) :attr-map (clojure.spec.alpha/? clojure.core/map?) :clauses :clojure.core.specs.alpha/ns-clauses), :val
((:require [clojure.string :as s clojure.edn :refer [read-string]])), :via [:clojure.core.specs.alpha/ns-form], :in [1]}], :spec #object[clojure.spec.alpha$regex_spec_impl$reify__2436 0xf80945f "clojure.spec.alpha$regex_spec_impl$reify__2436@f80945f"], :value (
game.lib (:require [clojure.string :as s clojure.edn :refer [read-string]])), :args (game.lib (:require [clojure.string :as s clojure.edn :refer [read-string]]))}, compiling:(game/lib.clj:1:1)
And now we know 😛Aaaaaaand the actual code works :rolling_on_the_floor_laughing: Thanks very much for your time and expertise!
I very certainly do 😛
>>> user=> (load-file "bad.clj") Syntax error macroexpanding clojure.core/ns at (/home/dan/projects/clojure/throwaway/bad.clj:1:1). ((require [clojure.string :as s clojure.edn :refer read-string])) - failed: Extra input spec: :clojure.core.specs.alpha/ns-form
I don't mind the onslaught so much, more that the pre 1.9 error messages are just java stack traces for a bunch of files I've never seen, which tell me nothing
^^ fyi, this particular case (which really many of the ns clause failures fall into) is one we’ve been discussing. here there are * clauses, and each one of which is 1 of N options. rather than telling you that it expected one of the N options, it says that it didn’t match anything and found “extra input”, which is true but not helpful. There is a ticket (well, maybe more than one) that fall into this case and it’s a case where we can do better.
and the error here is require
instead of :require
(the first error 🙂 )
ah, yes :)
The last few 1.10 builds are much, much better in terms of error reporting -- a big thank you for the work done so far!
I hadn’t read all the backchat
It can be difficult to give semantically useful answers to all human-generated errors, as humans are so devious 🙂
my biggest takeaway from spec’ing ns, is that if we had spec when ns was written, we would have used a different dsl for it b/c it sucks
writing specs for macros often makes that clear very quickly
(ns2 ...)
🙂
jinx!