Fork me on GitHub
Michael Fiano00:03:32

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 ??

Michael Fiano00:03:41

I'm guessing not. This seems to be like some vs not-any?

Michael Fiano00:03:48

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 🙂


With "predicate" being a function ending in ?


If you are curious: 91 votes for this ticket

Michael Fiano00:03:59

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

Michael Fiano11:03:06

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


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?


and check for nil in each test clause


oh, yeah, some-> is even more directly what you're asking for


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


some-> and fnil are probably friends 🙂

Michael Fiano16:03:56

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


way less important in clojure since there's no way to return primitive booleans from functions

Michael Fiano17:03:16

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

Michael Fiano17:03:41

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)))


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

Michael Fiano17:03:55

I know. false or true


drop the if and wrap the or in a not


what I'm saying is that if can be replaced by not

Michael Fiano17:03:01

I see. I didn't know that. I'm much too used to Common Lisp with nil standing in for false.


note that

user=> (not nil)


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.


not in clojure


You end up with calls to a runtime or or somesuch?


no, no calls to or


By the way @mfiano if you need to know, you can look at the bytecode


we just expand the or to nested ifs

Michael Fiano17:03:46

@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


(Not really Java at that level.)


jvm bytecode is super easy to understand if you have some familiarity with stack languages


Also, without going to that level, Criterium is awesome for perf questions

Michael Fiano17:03:29

My only experience prior to this week is Common Lisp


Are you writing a game or something where perf is critical?


There are good Java profilers that can help see the big picture of where your code is spending its time.


(They work at the bytecode level and work fine with Clojure.)

Michael Fiano17:03:47

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.

Michael Fiano17:03:51

Hmm I don't even know what they are.



Michael Fiano17:03:44

No, reflection.

Michael Fiano17:03:00

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:


It makes it rather easy to see if a speculative change to a function will make it run faster for a given input.

Michael Fiano17:03:40

(defn room-overlaps?
  [room1 room2]
    (> (:x2 room1) (:x1 room2))
    (< (:x1 room1) (:x2 room2))
    (> (:y2 room1) (:y1 room2))
    (< (:y1 room1) (:y2 room2))))
This is equivalent if I'm not mistaken.

Michael Fiano17:03:45

Oh great, thanks


I wonder if you can put a lot of that into one big <

Michael Fiano17:03:29

I don't think so, because there are 8 scalars

Michael Fiano17:03:56

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


any ideas where to start debugging?


When you build it are you adding :advanced optimizations to the mix?


(I ask because that introduces the potential to break things, relative to the :none which is used at the REPL.)


yes, looks like the figwheel template adds those


i'll try disabling


Check your JavaScript console to see if it is saying anything.


yeah - annoyingly it's not saying anything, makes me think nothign is being executed


ah got some errors with optimizations disabled though - so that's helpful 🙂


so with optimizations off, i'm getting 404 for goog/base.js and goog/deps.js

Michael Fiano18:03:14

Why does clojure do biased rounding?

Michael Fiano18:03:29

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

Michael Fiano18:03:02

is there a function to do unbiased rounding?



Michael Fiano18:03:02

That's what I tested with. It's biased


user=> (Math/round 1.8)
user=> (Math/round 1.2)

Michael Fiano18:03:27

Unbiased rounding is important for statistics and accurate mathematics

Michael Fiano18:03:44

Otherwise the average of X samples will be artificially shifted upwards

Michael Fiano18:03:00

This is why most languages do not just round half upwards



user=> (binding [*math-context* MathContext/DECIMAL64] 
  (Math/round 1.5))
user=> (binding [*math-context* MathContext/DECIMAL64] 
  (Math/round 2.5))


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"]

Michael Fiano18:03:05

Yeah that's not half-even


Oh, you need to use BigDecimal..

Michael Fiano18:03:55

(map #(Math/rint %) (range 0.5 5)) ; => (0.0 2.0 2.0 4.0 4.0)

Michael Fiano23:03:00

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?


Reduce and reduced would work. Loop as well

Michael Fiano23:03:57

I tried loop, but i don't know what i'm doing wrong. i always get a list of 1 item


Not sure if you're a loop common lisper or not


Got a gist I can look at?

Michael Fiano23:03:39

The last function is where I'm trying to collect into a list


that appears to always return stage

Michael Fiano23:03:58

What I'm ultimately trying to do is return a new stage hashmap which has all of the rooms stored under a new key


and the call to (make-room stage) isn't captured anywhere. so you'll just recur


it looks to me like you're trying to use clojure as if it had mutability


in particular that place-room function is a very bad code smell for that

Michael Fiano23:03:45

Honestly, I don't know enough clojure yet to know what I should be doing


For example doseq should probably be for, and other things to return stuff


At the bottom is the notion that you can't change a Room instance


going from the name of the function, add rooms, presumably you have a list of rooms somewhere and you want to add something?

Michael Fiano23:03:16

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


and you need a way to keep making rooms until you get a good one?

Michael Fiano23:03:36

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.)


(In addition to tries.)


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

Michael Fiano23:03:59

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.)

Michael Fiano23:03:31

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

Michael Fiano23:03:19

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)
               (add-room-to-stage stage room))
             (inc tries)))


The key idea ^ is that an if is used, and either the unmodified stage is returned by the if, or a modified new stage

Michael Fiano23:03:12

I see. Thanks. Let me play around with that idea for a few


add-room-to-stage would return a modified stage

Michael Fiano23:03:13

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

Michael Fiano23:03:35

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?

Michael Fiano23:03:33

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

Michael Fiano23:03:18

Yes, it will loop until either the estimated rooms count is met, or an upper bound to stop at

Michael Fiano23:03:54

I'm following a particular algorithm I already ported to 2 other languages.


ah. that's why it looked setq-y 🙂

Michael Fiano23:03:02

If you're curious, it will look like this when finished:


super cool!

Michael Fiano23:03:38

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

Michael Fiano23:03:45

I'm having fun though