This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-03-25
Channels
- # beginners (152)
- # boot (4)
- # bristol-clojurians (1)
- # cider (1)
- # cljs-dev (176)
- # clojure (104)
- # clojure-china (2)
- # clojure-uk (6)
- # clojurescript (6)
- # core-async (23)
- # cursive (4)
- # datomic (3)
- # devops (1)
- # duct (32)
- # events (1)
- # fulcro (9)
- # hoplon (2)
- # jobs-discuss (9)
- # lein-figwheel (2)
- # leiningen (3)
- # off-topic (19)
- # pedestal (2)
- # portkey (14)
- # re-frame (20)
- # reagent (41)
- # rum (4)
- # shadow-cljs (26)
- # tools-deps (1)
- # unrepl (5)
Should predicate functions ending with ?
only return true or false, or does it make sense to return the input unaltered or false...can this still be considered a predicate function with ?
?
I'm guessing not. This seems to be like some
vs not-any?
Correct me if I'm wrong 🙂
All core predicates have returned true
or false
, except a couple of recent ones in spec; this causes lots of commotion 🙂
If you are curious: 91 votes for this ticket https://dev.clojure.org/jira/browse/CLJ-2141
I see. That makes sense. I suppose this function I'm writing is doing validation, and so should pass input through as a noop or return false, so probably isn't a "predicate"
I just got a new laptop (it uses Windows 10) and I'm trying to download leiningen and gorilla repl. I used to have a mac and I remember it being really easy to get these downloaded on that. I keep getting an error when I download leiningen that says "Exception calling "DownloadFile" with "2" argument(s): "The request was aborted: Could not create SSL/TLS secure channel." How can I get this to work?
@marwe22t Off the top of my head - make sure that you are using an elevated cmd prompt instead of PowerShell. Then you can set the "cert ignore" shell evn vars that the lein.bat script suggests - provided you have curl or wget installed (you can use choco to install https://chocolatey.org/install).
Is a function's parameter vector accessible within its body?
not directly, I think, but you can probably use destructuring for what you are trying to achieve https://clojure.org/guides/destructuring#_sequential_destructuring
I was using (-> url a b c d)
, but url
could be nil
, and functions a
b
c
and d
could have returned nil
too. If any of them return nil
, i would like to break the chain and return different error messages. What's the most idiomatic way to do this? Exceptions?
you could use cond->
https://clojuredocs.org/clojure.core/cond-%3E
some->
does that https://clojuredocs.org/clojure.core/some-%3E
however...if you want to return different error messages, cond->
or exceptions may be more useful...`some->` is better for shortcutting and returning nil
@mfiano if you define your function thusly (defn afn [& params] ...
then params will essentially be a sequence of the contents of your argument vector
Similar question to the one I had yesterday: Is it good practice to make ?
predicate functions return false as the falsey value instead of nil? Often this involves another branch via if
and therefor more instructions.
I don't know if the perf consequences in Clojure are important or not. Oftentimes in ClojureScript, if it is absolutely critical, the return value of a predicate is additionally annotated with (ClojureScript-specific) ^boolean
meta to avoid a checked if. More on that meta is here http://blog.fikesfarm.com/posts/2015-12-04-boolean-type-hints-in-clojurescript.html
way less important in clojure since there's no way to return primitive booleans from functions
Interesting. Yeah I have no prior experience with JVM or JS so I don't know how it is at generating code. My experience just says that branching in a tight loop is bad
@mfiano: you can make a boolean without if using the boolean
function btw, and if your concern is performance, the price of mapping nil /false to boolean and everything else to true seems very low
it would be overshadowed by things like hash lookups and even those are cheap
This is what I have, but it will be called in a tight loop. How to make it better?
(defn room-overlaps?
[room1 room2]
(if (or (> (:x1 room1) (:x2 room2))
(> (:x1 room2) (:x2 room1))
(< (:y1 room1) (:y2 room2))
(< (:y1 room2) (:y2 room1)))
false
true))
also consider that in normal clojure code every function you call is being looked up on each invocation (because we allow redefinitions) and that's definitely more expensive than boolean
@mfiano: that code can't ever return nil
or returns false for fall-through, and > is boolean
I know. false or true
what I'm saying is that if can be replaced by not
I see. I didn't know that. I'm much too used to Common Lisp with nil standing in for false.
but, in clojure.core there re some predicates that return nil instead of false already -- edit: not anymore
are there? I can’t think of an example, curious if you had something in mind
I'm curious, in ClojureScript, all of the stuff in room-overlaps?
disappears and you end up with JavaScript involving native >
, <
, and ||
. I suspect Clojue ends up generating similarly optimal bytecode in that case.
@mfikes Interesting, but considering I don't even know Java, I'm not sure how much that will help me 🙂
I bet you would grok it, coming from a native background. It is just another kind of assembly
jvm bytecode is super easy to understand if you have some familiarity with stack languages
My only experience prior to this week is Common Lisp
There are good Java profilers that can help see the big picture of where your code is spending its time.
Right now I'm just noting possible areas for later optimization as I learn the language.
One easy way to save hassle is to set *warn-on-reflection*
at the top of each namespace. Reflection can be ridiculously expensive.
Hmm I don't even know what they are.
No, reflection.
Thanks
Anyway, I just figured out how I can change the above code to not use if
or even not
Here is the Criterium tool, that is really useful for ensuring code has good perf, without having to break out a full-fledged profiler: https://github.com/hugoduncan/criterium
It makes it rather easy to see if a speculative change to a function will make it run faster for a given input.
(defn room-overlaps?
[room1 room2]
(and
(> (:x2 room1) (:x1 room2))
(< (:x1 room1) (:x2 room2))
(> (:y2 room1) (:y1 room2))
(< (:y1 room1) (:y2 room2))))
This is equivalent if I'm not mistaken.Oh great, thanks
I don't think so, because there are 8 scalars
I mean, the x and y of each rectangle are independent in calculating intersection
hi all, i'm trying to build my clojurescript project - works in figwheel but when i build it and load the output js in browser, nothing happens
i'm sure i've read somethign about this in the quickstart before, but i can't find it now
(I ask because that introduces the potential to break things, relative to the :none
which is used at the REPL.)
More info here https://clojurescript.org/reference/advanced-compilation#fixing-advanced-compilation-issues
Why does clojure do biased rounding?
Rounding on most languages such as Common Lisp or Python, rounds half towards even to prevent biasing. On Clojure (or maybe Java) however, the rounding is biased and always rounds half up: Common Lisp, Python, etc 1.5 = 2 2.5 = 2 3.5 = 4 4.5 = 4 Clojure 1.5 = 2 2.5 = 3 3.5 = 4 4.5 = 5
is there a function to do unbiased rounding?
That's what I tested with. It's biased
Unbiased rounding is important for statistics and accurate mathematics
Otherwise the average of X samples will be artificially shifted upwards
This is why most languages do not just round half upwards
user=> (binding [*math-context* MathContext/DECIMAL64]
(Math/round 1.5))
2
user=> (binding [*math-context* MathContext/DECIMAL64]
(Math/round 2.5))
3
That's supposed to be half-even... perhaps it is not *math-context*
which controls it...
user=> MathContext/DECIMAL64
#object[java.math.MathContext 0x7216fb24 "precision=16 roundingMode=HALF_EVEN"]
Yeah that's not half-even
@mfikes I found out how
(map #(Math/rint %) (range 0.5 5)) ; => (0.0 2.0 2.0 4.0 4.0)
What is the proper way to iterate until an arbitrary condition is met, collecting the results of the body function call into a list/vector?
I tried loop, but i don't know what i'm doing wrong. i always get a list of 1 item
sure one min
The last function is where I'm trying to collect into a list
What I'm ultimately trying to do is return a new stage hashmap which has all of the rooms stored under a new key
Honestly, I don't know enough clojure yet to know what I should be doing
going from the name of the function, add rooms, presumably you have a list of rooms somewhere and you want to add something?
add-rooms is generating a bunch of rooms (rectangles) of varying sizes, and placing them randomly on a stage (2d grid), skipping ones that overlap
ah. so your make-room function makes a random room and returns nil or the room if it doesn't overlap
I want to store the list of successful rooms in the stage hashmap
Perhaps one place to start is to include stage
as one of the bindings in the loop
/ recur
? (So you can keep adding to it.)
so i would make create-room not take the stage. you can always ask for a new room. and then you can loop or recur and add it optionally as you go
and just a small nitpick, but shadowing core functions is a really subtle pain point. you call something max
. if you refactor later that can really be a pain
Yeah that was on my list of things to change.
The key idea to fix this up is to make the functions return values that you use. (They can't mutate the values passed to them.)
How should make-room not take stage? i'm not sure how i would check overlap then
you're putting two things into one function. give me a room and check if it overlaps
Right but a room size depends on properties of the stage hashmap
(loop [stage whatever
tries 0]
(if (< tries max-tries)
(let [new-room (make-room)]
(recur (if (overlaps stage new-room)
stage
(add-room-to-stage stage room))
(inc tries)))
stage))
The key idea ^ is that an if
is used, and either the unmodified stage
is returned by the if
, or a modified new stage
I see. Thanks. Let me play around with that idea for a few
Hmm so what would add-room-to-stage look like?
it seems like its just an update. your stage is just a map with a rooms key. so (update stage :rooms conj new-room)
or whatever data structure that :rooms
contains
Ok I'm not familiar with that function yet. I got some reading to do. Thanks
i'm not too familiar with games but is it risky to put a non-deterministic room building algo in there?
there's a chance that this thing just loops and never satisfies what you need, right?
Everything is non-deterministic about this. It's a procedural random world builder. Everything depends on the seed of the RNG
right. but i meant the function takes a stage and looks at the existing rooms and bulids a room that will fit, rather than looping and making a random one and hoping it fits
Yes, it will loop until either the estimated rooms count is met, or an upper bound to stop at
(Eventually)
I'm following a particular algorithm I already ported to 2 other languages.
If you're curious, it will look like this when finished: https://www.michaelfiano.com/projects/gamebox-dgen/
It is probably a bad thing to do as my first Clojure application, as it's very undertministic and everything depends on the mutability of the RNG seed
I'm having fun though