Fork me on GitHub
#clojure
<
2020-08-06
>
Lukas09:08:29

A question about the syntax in :require in the ns function: Is :require a function (looks like it because of the parentheses) and if yes, what does this function do, called with the requirements vector as an argument?

jsn09:08:49

That's probably a question more suitable for #beginners . :require is not a function (and neither is ns , actually -- it's a macro), perhaps clojuredocs can help: https://clojuredocs.org/clojure.core/ns

👍 3
Lukas09:08:41

Thanks for pointing me in the right direction!

noisesmith15:08:30

it's not as weird as you might think though, ns literally turns a :require clause into a call to the require function - the only difference is whether symbols are evaluated

Lukas09:08:34

(ns project.core
  (:require [clojure.tools.logging :as log]))

shivekkhurana09:08:14

Why does (true? []) returns false but (when [] :execute) returns :execute?

shivekkhurana10:08:02

I was surprised by this output and tried to find an answer in the docs, but wasn't able to. Here's the output from a REPL:

Clojure 1.8.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_91-b14
=> (true? [])
=> false   
=> (when [] :execute)
=> :execute
I expected when to return nil because [] is falsy. What is happening here?

jsn10:08:44

The doc says "Returns true if x is the value true, false otherwise."

jsn10:08:10

It means "if x is the value true ", not "if x is some true-y value"

Lars Kristian Maron Telle10:08:54

Which values are true-y, btw? All values except nil and false?

👍 9
jsn10:08:04

Yes, IIRC, that is correct

👍 9
shivekkhurana10:08:07

hmm, I missed that. Thanks Dmitry !

jsn11:08:04

Yeah, I also misunderstood that one initially

jonathanj10:08:08

If I’ve done (require '(some.ns :as foo)) and I’m handed a qualified keyword like :foo/bar, how would I expand that qualified keyword to it’s canonical namespace? i.e. :some.ns/bar

jonathanj10:08:54

I poked around the ns-* functions but I seem to be missing something obvious about how to do this.

jonathanj10:08:05

Oh, I need to use ::foo/bar . Oops, sorry for the silly question.

nikolavojicic12:08:01

Is it possible to terminate IReduceInit, e.g.

(transduce
 xform
 (fn foo
   ([_ v] (if (side-effect! v)
            (println "ok")
            (println "terminated"
                     (terminate reducible))))
   ([_]   (println "done")))
 nil reducible)

Alex Miller (Clojure team)12:08:54

Yes, wrap the return in ‘reduced‘

❤️ 6
Ben Sless19:08:17

Bringing this question here, why is the following implementation of update-in slightly slower than the core implementation? The difference is very minor, about 5ns slower per key, but it's still there.

(defn- up
  [m ks f args]
  (let [[k & ks] ks]
    (if ks
      (assoc m k (up (get m k) ks f args))
      (assoc m k (apply f (get m k) args)))))

(defn update-in
  ([m ks f & args]
   (up m ks f args)))

noisesmith19:08:57

based on the source of the original, if I'm reading correctly, it must be the var lookup of up inside the recursive call

noisesmith19:08:19

where the let binding is used in place without need for runtime lookup

noisesmith19:08:27

I'm not seeing other differences

Ben Sless19:08:33

Shouldn't that be eliminated if we use direct linking? the Clojure jar itself is directly linked, no?

noisesmith19:08:58

I wouldn't be surprised if that were the case

Ben Sless19:08:49

Seems like it does. Cheated by adding ^:const to up and got the same performance as update-in

noisesmith19:08:32

I didn't think const was supposed to do that...

Ben Sless19:08:43

Could be wrong

noisesmith19:08:48

my understanding is const tells the compiler it's allowed to inline, but I didn't think it would do so for data that couldn't directly be compiled into the bytecode

Ben Sless19:08:57

Any way, while an ugly hack, this also reaches the same performance:

(let [up (fn up
           [m ks f args]
           (let [[k & ks] ks]
             (if ks
               (assoc m k (up (get m k) ks f args))
               (assoc m k (apply f (get m k) args)))))]
  (defn update-in
    ([m ks f & args]
     (up m ks f args))))
I still don't understand why it's not slightly faster as it's supposed to do less allocations

noisesmith19:08:12

I guess the reference to the function could be compiled into bytecode (vs. the var which is then looked up)

Alex Miller (Clojure team)19:08:46

the right answer here is to compare the bytecode, not guess

noisesmith19:08:17

once again my curiosity must overcome my laziness

Alex Miller (Clojure team)19:08:49

my guess is that the difference is really something related to jvm inlining scope and the jit

Alex Miller (Clojure team)19:08:47

with a var with direct linking you've split the code into two methods and that may result in different characteristics than what happens when created in the let (harder for inlining to "see" all of it or something like that). this can also be very jvm version sensitive as that stuff is improved all the time

Alex Miller (Clojure team)19:08:50

there are a bunch of jvm flags that allow you to see the inlniing work and I've found those can be pretty interesting to watch for stuff like this (presuming that guess to the difference is correct)

noisesmith19:08:46

oh yeah, I vaguely recall a talk by a guy from the JRuby team about "mechanical sympathy" that covered this in some depth

Alex Miller (Clojure team)19:08:23

we occasionally have had issues in CLJ where the addition of error message code blew the inlining budget and made things much slower

Ben Sless19:08:10

with const vs. without

Alex Miller (Clojure team)19:08:15

I know people like to make fun of the whole perf over error msgs thing but it's an actual tradeoff

Alex Miller (Clojure team)19:08:16

@ben.sless are you direct linking the core version?

noisesmith19:08:22

@ben.sless then you have avoided a var lookup

Ben Sless19:08:24

direct linking everything

Alex Miller (Clojure team)19:08:31

would kind of like to see the actual bytecode too

Ben Sless20:08:23

Can still send you the jar or source if you'd like

Ben Sless19:08:45

-Dclojure.compiler.direct-linking=true

Ben Sless19:08:50

I can upload the jar if you'd like

Alex Miller (Clojure team)19:08:51

the bytecode is typically not actually representable in Java

hiredman19:08:11

(please stop using ^:const)

Ben Sless19:08:41

Just playing around, don't worry 🙂

Alex Miller (Clojure team)19:08:34

yeah, the ^:const thing is just wrong

hiredman20:08:24

I have never seen anyone asking a question and :const came up where it was being used correctly. Never

Alex Miller (Clojure team)20:08:52

the people that understand how it works don't ask questions about it :)

hiredman20:08:15

that is kind of the thing, I mean people asking other questions where it just sort of comes up that they are using const

dpsutton20:08:14

to that point, deftype is a bit like that:

Note well that mutable fields are extremely difficult to use
  correctly, and are present only to facilitate the building of higher
  level constructs, such as Clojure's reference types, in Clojure
  itself. They are for experts only - if the semantics and
  implications of :volatile-mutable or :unsynchronized-mutable are not
  immediately apparent to you, you should not be using them.
There be dragons but its not clear how you could learn about how to tame them. I suppose the same for ^:const. If you're not already an expert, how do you become one

noisesmith20:08:47

for starters, when do you need those features?

noisesmith20:08:46

there's a good book which you could consider the rest of deftype 's doc string, elided for brevity and to avoid plagiarism, Java Concurrency In Practice

dpsutton20:08:02

i don't at the moment. forgot when i was playing around with it.

dpsutton20:08:17

i need to add that to my list

noisesmith20:08:41

I've noticed a funny drawback to learning by "following your nose" (something I do a lot), where the amount of documentation needed to describe a narrow and mostly unneeded feature accurately increases your chance of trying it, because it takes up so many pages of the docs you are skimming

noisesmith20:08:17

given that effect (something that I hope has a name), keeping your references to things most people shouldn't use as terse as possible is a good practice

noisesmith20:08:06

(reading code instead of docs helps too :D)

dpsutton20:08:12

100% agreed

Ty21:08:36

Hey, folks. I have a podcast about Software Engineering called The Virtual World. I'm uploading my interview with Eric Normand today and was wondering if you folks had any ideas for other guests that could be on the podcast. Is anyone in contact with David Nolen? I would love to have him on to talk about Clojurescript.

mruzekw23:08:18

I see David Nolen all the time in #clojurescript or you could DM him @dnolen

Ian Davies22:08:15

Hey I’m looking for recommendations for building a cross platform desktop app. The app requirements are interaction with a custom hardware driver and charting ability for Windows and Linux mainly with MacOS a nice to have but not required. If anybody has experience I would love to hear about it!

Alex Miller (Clojure team)23:08:22

I think your big options are Swing (seesaw is a Clojure lib), JavaFX (couple clojure libs out there and some big projects hav succeeded with that), and Electron which would be ClojureScript I believe, not sure if there are good flagship examples there

Ian Davies01:08:54

I was leaning towards electron as i have ClojureScript experience but I should check out what JavaFX has to offer before I reject it. Thanks @U064X3EF3 for the suggestions.

valerauko03:08:25

this is my electron + cljs (+ rust) project for reference https://github.com/valerauko/gitegylet

Alex Miller (Clojure team)23:08:09

or less well-known, something like Vaadin (Datomic console is one example I know of)

👍 6
Ian Davies01:08:08

Oh that’s a new one to me thanks.

mruzekw23:08:25

There’s some headway in the native space on mac with react-native-macos. Though I don’t think it’s anywhere near complete in terms of library support.

Alex Miller (Clojure team)23:08:48

for JavaFX, I'd suggest looking at Defold, which is a game editor created by King that is written in Clojure and has been open sourced