Fork me on GitHub
#clojure
<
2017-12-14
>
andy.fingerhut01:12:25

OK, probably a deep dark corner of Clojure functionality I haven't seen before, but can anyone explain what ('subset? ...) is doing in this line of code within the Clojure tests? https://github.com/clojure/clojure/blob/master/test/clojure/test_clojure/rt.clj#L97

hiredman01:12:13

map look up

hiredman01:12:26

looking up the symbol 'subset in the map returned by ns-publics

andy.fingerhut01:12:40

I just figured that out from REPL experimentation, which I probably should have done before asking. I knew that worked with a keyword as the first value in the form, but don't think I've ever used it with a symbol as the first value in the form.

hagmonk02:12:15

@andy.fingerhut clojure.lang.Symbol implements clojure.lang.IFn just like clojure.lang.Keyword, and seems to implement it in basically the same way, invoking RT.get on the argument passing itself as the lookup key

andy.fingerhut02:12:07

I will most likely forget this, and not miss the knowledge because I wouldn't want to see this in my code 🙂

hagmonk02:12:42

yeah it's a bit niche isn't it

andy.fingerhut02:12:03

I've only ever written Clojure as a hobby, but a lot of hours have gone by without me seeing this in people's code.

hagmonk02:12:04

would be interesting to mine crossclj for the most rarely used features. I don't think I've ever seen :strs or :syms destructuring in the wild, for instance

hagmonk02:12:40

now I'm kind of sad that there's no clojure.lang.String that also implements IFn. Then we'd have three types you can both destructure and use to look themselves up.

seancorfield02:12:48

@hagmonk We have :strs destructuring in our production code... 🙂

hagmonk02:12:53

secretly I think I have this in my code too ...

hagmonk02:12:17

but it's not "in the wild" so I think I escape on a technicality. ag reveals I actually have used it twice in just this one project I checked 😳

didibus03:12:36

Spec question: If I have a function that takes a destructured map, what's the best way to spec that function, so that the values of the keys in my map are also specced? The best I've got right now is (s/keys :req-un [::a ::b ::c]) given (defn foo [{:keys [a b c]})

didibus03:12:05

But, I'd kind of want the names of the keys for my function to not match the spec name of their value. And I'd rather define the spec for them inline. Any easy way to do that?

didibus03:12:57

Would be nice to have something like (s/map :req [:a int? :b string? :c ::other-spec]) for this scenario

stuartrexking03:12:14

Is there a way to make this point free #(assoc %2 :id %1)

qqq03:12:39

lol, I don't think it'd be shorter in any point free style

stuartrexking03:12:57

I get that. This was a just a challenge based on a discussion we are having internally at my company.

qqq04:12:32

maybe something involving merge, apply, and reverse, and rotating

qqq04:12:17

(apply assoc (reverse (interpose :id %)))

qqq04:12:36

(->> args (interpose :id) reverse (apply assoc)) 🙂

seancorfield04:12:51

That's not point-free...

qqq04:12:26

What is point-free? I thought it merely meant "don't use variable names, and chain together functions"

seancorfield04:12:45

But args and % are variables.

qqq04:12:18

right, so we need to get rid of the "args" field

qqq04:12:37

the line before that was me working out intermediate steps

qqq04:12:05

we need to removeargs from (->> args (interpose :id) reverse (apply assoc)) and then we're good

seancorfield04:12:25

Here's a point-free version: (comp (partial apply assoc) reverse (partial interpose :id) vector)

seancorfield04:12:45

boot.user=> ( (comp (partial apply assoc) reverse (partial interpose :id) vector) 123 {} )
{:id 123}

seancorfield04:12:06

@stuartrexking ^ does that answer the challenge?

xiongtx04:12:10

The clj page on transients says that: > In Clojure 1.6 and earlier, transients would detect any (read or write) use from a thread other than the one that created them and throw an exception. That check was removed in 1.7 to allow for more flexible use in frameworks like core.async go blocks that enforce the single-threaded constraint via other means. Emphasis mine. But under summary it still says: > Thread isolation - enforced I tried the following in clj 1.8:

(dotimes [_ 5]
  (def tv (let [tv (transient [])]
          (future (Thread/sleep (rand-int 3))
                  (conj! tv 1))
          (future (Thread/sleep (rand-int 3))
                  (conj! tv 2))
          tv))
  (Thread/sleep 3)
  (println (persistent! tv)))
;; =>
;; [2 1]
;; [2 1]
;; [2 1]
;; [2 1]
;; [1 2]
So it clearly is possible to modify a transient from different threads. What, then, does "thread-isolation--enforced" mean? https://clojure.org/reference/transients

qqq05:12:38

[just guessing] perhaps it means that with respect to a transient, conj! pop! push! are all atomic -- i.e. if you run them from different threads, its as if they're beintg run from the same thread in some order - they won't 'trample' on each other due to race conditions

qqq05:12:16

also, the above example confuses me, as I thought you were supposed to look at the return value of conj! ... instead of printing the 'original transient'

xiongtx05:12:41

IIUC conj! modifies in place but returns the modified value.

qqq05:12:09

quoting: https://clojuredocs.org/clojure.core/assoc!

;; The key concept to understand here is that transients are 
;; not meant to be `bashed in place`; always use the value 
;; returned by either assoc! or other functions that operate
;; on transients.
not sure if "other functions" includes conj!

tbaldridge06:12:00

There are several cases where conj! May not change the input, and instead may return a new collection

tbaldridge06:12:11

So yes, treat transients like persistent collections.

qqq05:12:13

I'm looking for a clojure DSL that lets me output C code. Is https://github.com/aaronc/c-in-clj (5 years since last commit?) the best we've got ? Pre-emptive: why not just use C?: C's macro system is lacking. I want to use the full power of Clojure amcros for my macro system.

tbaldridge06:12:18

Not that I know of, it’s not really a easy thing to pull off since C lacks almost everything Clojure would need

tbaldridge06:12:41

But writing a AST to C layer wouldn’t be that hard. I know of several projects that do that

mpenet06:12:34

Carp? It transpiles to c so I guess it would fit

mpenet06:12:56

Not sure how mature it is tho

qqq08:12:34

@tbaldridge: I'm not trying to do Clojure -> C . I'm trying to do "Clojure data representing a program -> C".

qqq08:12:30

I have some code which deals with nothing but tensors of floats -- no other data structure, no gc-ing, nothing else and I want to represent this code as 'clojure data', and then generate C from it (which will let me hit both WebAssembly and Cuda afterwards)

gklijs10:12:09

Interesting Idea, but probably needs some time to become doable. For example if? in the future Kotlin can compile to web-assembly it will become easier.

qqq11:12:52

@U26FJ5FDM: I think we are discussing different problems. What problem do you think I am trying to solve?

gklijs11:12:07

You want some way to go from clojure to WebAssembly right?

Empperi12:12:26

or to CUDA which kinda makes it invalid approach to go for Kotlin

gklijs12:12:07

Can you run CUDA in the browser?

Empperi14:12:00

Who did say anything about running stuff explicitly in browser? o_O

Empperi14:12:16

This is #clojure not #clojurescript

Empperi14:12:03

and besides, CUDA was specifically mentioned as a potential target

gklijs16:12:59

True, but qqq clearly asked for a way to go both to cuda and webassembly.

qqq19:12:44

I'm not asking for "Clojure -> Cuda" or "Clojure -> WebAssembly" I want "very restricted DSL -> Cuda" and "very restricted DSL -> WebAssembly" this "very restricted DSL", expressed as Clojure Data, is NOT FULL CLOJURE -- in particular, I do NOT want to emscriptsen the entire JVM I want a very restricted DSL for describing manipulations on tensors of floats -- and compiling this DSL to WebAssembly / CUDA the main relation to CLojure is that I want to implement this very-restricted-dsl via clojure data

wei08:12:08

if I'm dealing with a java class that extends a HashMap, is there an easy way to cast a map into it?

public class RowData extends HashMap<String, Object> {
}

wei08:12:28

would love to do (cast RowData (java.util.HashMap. {:a 1})) but that raises a ClassCastException

souenzzo11:12:51

(into (new RowData) my-map)? Into uses conj

wei00:12:19

thanks, that results in

ClassCastException hex.genmodel.easy.RowData cannot be cast to clojure.lang.IPersistentCollection  clojure.core/conj--5112 (core.clj:82)

wei00:12:45

ended up with this, suboptimal but works:

(defn ->row-data [m]
  (let [row (RowData.)]
    (doseq [[k v] m]
      (. row put k v))
    row))

fbielejec10:12:57

I'm playing with function specs and I wondered if one could use it to emulate type checking, during compile time, something like this:

(s/fdef divide
        :args (s/cat :x integer? :y integer?)
        :ret number?)

(defn divide [x y] (/ x y))

;; should throw when compiled?
(defmacro divide-by-foo []
  (eval `(divide 6 :foo)))
yet this namespace doesn't throw, why?

didibus22:12:30

This is exactly what spectrum does: https://github.com/arohner/spectrum

didibus22:12:43

Still in early alpha. Show your support if you like it.

abdullahibra10:12:00

why this work in second case and not work in the first

benzap11:12:12

@fbielejec you need to have instrumentation enabled to have it throw

benzap11:12:34

@fbielejec by default, clojure spec doesn't circumvent evaluation to perform spec analysis, you need to tell it to check your specs

fbielejec11:12:37

so just (:require [clojure.spec.test.alpha :as st]) and (st/instrument 'divide) ?

benzap11:12:11

you'll have to read over the docs, and mess around with it

benzap11:12:43

think it's after you define your specs, but before you evaluate your function that you want spec analysis for

benzap11:12:55

your defmacro is never going to throw a spec error until it's been evaluated

benzap11:12:46

note that instrumentation was turned on after the specs have been introduced and evaluated

benzap11:12:04

I could have put it at line 7 or 9

benzap11:12:47

the divide-by-foo case should probably fail, none of this has been tested

fbielejec11:12:28

this is my problem - I don't understand why at compile-time the macro doesn't become (eval (/ 6 :foo)), which should still throw. The divide-by-foo will fail for sure (with an exception or spec validation error depending on whether instrumentation is turned on), like you say.

didibus22:12:25

I think eval runs in its own environment, which means within eval, you have not instrumented the divide function. That's my guess at least.

didibus22:12:01

Try:

(defmacro divide-by-foo []
  (divide 6 :foo))
Instead, after having instrumented divide. This will make a call to divide at macro-expansion time which should fail validation of the spec by instrument.

chrisblom11:12:45

if i want to display some quick charts from the repl, is incanter the best option?

chrisblom11:12:15

i just want to quickly visualize some line charts, no fancy processing is needed

qqq11:12:27

Does either "lein repl" or "boot repl" have a web interface? I want something like "boot web-repl" or "lein web-repl" to 1. open up a webserver on port 8081 2. I can go to <localhost://8081> and interact with the repl 3. have certain forms of output render nicely into HTML tables / SVG diagrams / ...

tbaldridge14:12:06

Do it with a socket repl and it'd be pretty easy

matan09:12:24

Could be nice 🙂

Prakash11:12:30

@qqq gorilla repl can do that

pasi12:12:24

is there a tool for formatting end files?

pasi12:12:52

.. why did I not just try running cljfmt on it earlier. I keep running it on my .clj files

pasi12:12:54

thanks 🙂

matan13:12:00

Hi, I am transducing over a lazy sequence that reads from a file (hurray). However I am having some trouble figuring efficient ways to debug or any plausible way to debug at all. Maybe you can comment? Here's code:

(ns cleanser.dictionary-test
  (:require
     [clojure.pprint :refer [pprint]]
     [puget.printer :refer [cprint]]
     [clojure.inspector :as inspect :refer [inspect-tree]]
     [cleanser.dictionary-search :refer :all]
     [ :as io]
     [clojure.set :refer :all]
     [clojure.math.combinatorics :refer [cartesian-product]]
     [clojure.test :refer :all]
     [ :as io]
     [clojure.string :refer [split]]))

(defn text-file-reader [filepath reader]
   " return a lazy sequence for streaming through the file contents "
   (with-open
      [file-reader (reader filepath)]
      (line-seq file-reader)))


(deftest names-dictionary
  (let
    [text (slurp "resources/names/hebrew-wikipedia-content.txt")

     names-dump-filter  (remove #(re-matches #"# < > \[ \] \{ \} / @ \*" %)) 
     names-dump-breaker (mapcat #(split % #"\|"))                            

     names
       (sequence
         (comp names-dump-breaker names-dump-filter)
         (text-file-reader "resources/names/user-names-unique.txt" ))

     dictionary (build-dictionary names)]

     (println (search text dictionary))
     (println (type names) ; a lazy stream
     (println names))))   ; java.io.IOException: Stream closed
printing names seems futile, the stream has been expended by then. Any suggestion for a better design for stream-processing file contents with transducers? Any best practice for debugging within the transduction itself is very welcome as well Many thanks!

fmind13:12:17

@matan you could use trace to monitor the input/output of your transducer functions https://github.com/clojure/tools.trace

matan13:12:36

actually, I am not very sure how I'd trace very elegantly in transducing code like above

fmind14:12:12

@matan I though it would be easy with trace, but it doesn't work as expected in my case

fmind14:12:29

instead, you could define your own transducer for logging purpose

fmind14:12:09

(defn xflog []
      (fn [rf]    
       (fn       
       ([] (rf))                          
       ([res] (rf result))                
       ([res input] (println input) (rf res input)))))

fmind14:12:16

(sequence (comp (xflog) (filter odd?) (map inc)) (range 5))

fmind14:12:46

it works as expected, but you could extend it to include a tag (e.g. "before filter odd?")

madstap15:12:31

@matan Or use the debug atom trick. Something like

(defonce a (atom []))

(def dbg-xf (map (fn [x] (swap! a conj x) x)))

(comment
  ;; The atom now contains every value that passed through dbg-xf
  @a
  )

madstap15:12:54

Or just (def logging-xf (map (fn [x] (prn x) x)))

val_waeselynck17:12:35

@matan you can also just use a plain old debugger like the one available in Cursive. You can also use scope-capture as a more powerful version of the debug atom trick, which also supports a form of breakpoint (disclaimer: I'm the author!): https://github.com/vvvvalvalval/scope-capture

mikerod17:12:03

scope-capture is great

mikerod17:12:11

I’m using it a lot nowadays

Desmond21:12:28

I have a system.edn file that needs a database url that I don't want to check in to source control. How can I introduce a variable into an edn data structure?

schmee21:12:31

@captaingrover there are a bunch of config libs for Clojure, here’s some examples:

schmee21:12:03

they all manage secrets, different environments etc

Desmond21:12:52

@schmee those all look like good options. thanks!

joelsanchez21:12:25

cprop is nice!

PB21:12:18

@schmee I've always used environment variables. That way I can have an .env.example file people can copy and modify to their likings and not check it in

the-kenny21:12:13

the environment-variable approach is also great when paired with direnv https://direnv.net/

arohner22:12:34

I’m using jvisualvm to successfully profile my app, locally, on macOS 10.12. It works correctly through several jvm reboots, and jvisualvm suddenly fails to connect with “Failed to create JMX connection to target application.” I wasn’t explicitly creating JMX connections beforehand. Rebooting my mac fixes it, but is there any way to solve it without rebooting?

hiredman22:12:38

are you using the same version of the jvm each time?

arohner22:12:13

I should be. I’m just in the same terminal window and lein repling each time

arohner23:12:47

once it’s hosed, restarting both my clojure jvm and the visualvm process doesn’t fix it

arohner23:12:20

and then after rebooting my mac, it works until I reboot my clojure app ~5 times

arrdem23:12:24

is visualvm forking something off that’s sticking around?

arrdem23:12:32

That’s super spooky

arohner23:12:46

could be, but I’m not finding anything obvious

arohner23:12:53

there are no java processes running

hiredman23:12:05

what version of the jvm?

noisesmith23:12:09

something about port acquisition logic?

arohner23:12:22

$ java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

qqq23:12:26

I feel like this code can be much shorter: I'm trying to tokenize a string via . a list of regexps:

(defn- token-len [t]
  (count (:str t)))

(defn lex [pats s] 
  "lex :: obj.pats -> string -> [obj.token]"
  (let [regexps (mapv pat->regexp pats)] 
    (loop [tokens [] 
           s      s] 
      (if (empty? s)
        tokens 
        (let [token (first (keep #(regexp-match % s) regexps))] 
          (assert token (str "failed to tokenize substring: " s))
          (assert (> (token-len token) 0)
                  (str "empty token: " token " s: " s))
          (recur (conj tokens token)
                 (subs s (token-len token)))))))) 

qqq23:12:20

https://clojuredocs.org/clojure.core/subs <-- does clojure not offer an O(1) time substring ?

arrdem23:12:59

No. Clojure doesn’t have a string type and just uses Java’s strings. If Java’s strings don’t have it Clojure doesn’t have it.

noisesmith23:12:10

you’d think with immutable String you could make an immutable CharSequence that used an indexed range of a string - except of course unicode we can’t have it because unicode

noisesmith23:12:15

since you can’t guarantee that the index of a string by character starts at any given byte

didibus23:12:56

I think you can with UTF-16, which is what java uses no?

noisesmith23:12:21

UTF-16 requires either 16 or 32 bits to encode a character

noisesmith23:12:32

you have to walk the string up to the point of your index to find its byte offset

andy.fingerhut00:12:50

Indexes into Java strings are indexes of 16-bit values, whether they are in the middle of a 32-bit code point or not.

andy.fingerhut00:12:09

so indexing is O(1), but isn't guaranteed to be the index of a full Unicode character.

noisesmith00:12:28

oh - so subs can return garbage?

noisesmith00:12:11

TIL

=> (subs "💩" 1)
"?"

andy.fingerhut00:12:13

There have been bugs related to this in Windows applications, I've heard.

noisesmith00:12:42

I’m not surprised in the least - I would have expected subs to index by character not by pair of bytes

andy.fingerhut00:12:19

There are libraries that can turn Java strings into sequences of Unicode code points, but then there are also complexities in Unicode like modifying graphemes (I think they are called) that can require understanding sequences of multiple Unicode code points, if you want to know how many "graphical things to display"

andy.fingerhut00:12:30

I have heard that Perl for about a decade has strings that are something like UTF-8 in memory, but if you index them by integer, they actually take the variable-number-of-byte encoding into account and give you the index of the i-th Unicode character.

andy.fingerhut00:12:01

I suspect that they might even implement some kind of caching of 'character index' -> 'byte offset' under the hood if you index the same string many times, but haven't looked.

noisesmith23:12:31

(without an O(n) scan that is)

arrdem23:12:36

ztellman has a new immutable strings implementation in his bifrucan library that gives you log(n) substringing I think

hiredman23:12:20

the problem with java's strings is the lack of a tree structure, so you can can't just hold a reference to the parts you need, your substring ends up holding a reference to the whole string

hiredman23:12:23

which was causing enough of a memory issue that they switched from what you propose (substring returning a special string that refers to the other string with offsets) to substring returning a copy

qqq23:12:40

seems like a case of "people cut self with scissors; let's ban all scissors"

qqq23:12:58

I don't see an argument against .substring-ref and .substring-copy

noisesmith23:12:03

but you could make a CharSequence that is cheap to construct from a String and uses a simple tree of some sort - and if code breaks when you use CharSequence instead of String the code is bad

qqq23:12:09

instead of just deciding upfront that all has to be copies

hiredman23:12:41

https://dev.clojure.org/jira/browse/CLJ-112 I opened this issue in assembla before clojure was on jira (after asking rich about it on irc)