Fork me on GitHub
#clojure
<
2017-03-17
>
seancorfield00:03:30

@facundo If you are interested in Expectations, we have an #expectations channel here...

samcf00:03:40

Any recommended resources for error handling best practices? Vague question I know, just testing the waters

qqq00:03:51

what is the point of datascript/datomic's query lanauge? I feel that given a :find .... :where .... with n clauses, I can convert it into a for loop with n clauses -- so there must be some additional power of the datalog query langauge that I'm missing

qqq00:03:50

user=> (split "Some words to split" #"\s+")
["Some" "words" "to" "split"]
suppose I wanted not only the words, but also the spaces between the words, (in case words are separated by more than one space) -- is there a way to get this also?

tbaldridge01:03:36

@qqq yes, you can basically convert a datalog into nested for loops, however, it's often slower since Datomic's datalog is set-based, meaning it can remove duplicate results ending in less joins required by subsequent clauses. Also, recursive queries are almost impossible to do with nested loops.

hiredman02:03:35

Speaking of datomic, datalog, and sets, I came across http://aosabook.org/en/500L/an-archaeology-inspired-database.html the other day

seancorfield02:03:05

@qqq You can use lookbehind:

boot.user=> (str/split "These are some words" #"(?<=\s+)")
["These " "are " "some " “words”]

seancorfield02:03:29

Not sure if that’s quite what you want but I suspect a combination of that and lookahead should work...

mars0i02:03:46

@qqq just use #"\b"

seancorfield02:03:17

Oh, nice!! I hadn’t run across that before.

mars0i02:03:23

which matches world boundaries

seancorfield02:03:00

Ah, and it matches both beginning and end… very useful!

mars0i02:03:13

Oh, @qqq I'm assuming you wanted the spaces as separate elements, rather than what @seancorfield did.

seancorfield02:03:52

And here’s me aiming for something complicated like this:

boot.user=> (str/split "These are some words" #"(?<=\s+)|(?=\s+)")
["These" " " "are" " " "some" " " “words”]

mars0i02:03:57

(split "Some words to split" #"\b") ;=> ["Some" " " "words" " " "to" " " "split"]

seancorfield02:03:56

Mine would break out each space as a separate match:

boot.user=> (str/split "These are   some    words" #"(?<=\s+)|(?=\s+)")
["These" " " "are" " " " " " " "some" " " " " " " " " "words"]

mars0i02:03:30

A variation for every need!

seancorfield02:03:48

“I have a problem… I think I’ll use a regex” … and now you have two problems!

mars0i02:03:45

I wasn't aware of the lookahead, lookbehind operators.

mars0i02:03:07

How does that regex capture the spaces?

mars0i02:03:53

Is it becasue it matches things that have zero or more spaces before or after them, and the spaces have that, i.e. at least zero spaces surrounding them?

netsu06:03:25

Is there in Clojure any way to get access to bindings from parent scope? E.g. like

(let [a 1]
  (let [a 2]
    (print (super a)))) ;; => 1

seancorfield06:03:51

(let [a 1]
  (let [a' a
        a 2]
    (print a'))) ;; => 1

seancorfield06:03:39

(I guess the question is really: what is the situation where you are shadowing a binding but still need access to the previous binding?)

netsu06:03:51

actually my knowledge where clojure use dynamic and where lexical scopes not full yet, so, yes, question about access to lexical parent scope (I guess, we can't deal with shadowed dynamic value, right?)

netsu06:03:21

analog to nonlocal in python.

netsu07:03:20

so we can't access directly to bindings in parent scopes from nested?

noisesmith07:03:08

you can access the value from a parent scope, as long as you have not shadowed it

noisesmith07:03:50

if you shadowed it, and don't have an alias in scope, there's no sane way to access the parent scope directly

netsu07:03:16

thanks. Here another example which not clear for me:

user=> (let [p 1] (eval '(print p)))

CompilerException java.lang.RuntimeException: Unable to resolve symbol: p in this context, compiling:(/tmp/form-init5764583318142605948.clj:1:19) 
so we can't eval lexical scoped symbols?

noisesmith07:03:56

eval doesn't use your lexical scope

noisesmith07:03:09

it's easy to work around by using a function and passing an arg

noisesmith07:03:40

(that is, if you actually need eval, generate a function, and pass in the lexical bound value)

netsu07:03:19

oh, I see, here macros useful

(let [p 1] (eval `(print ~p)))

noisesmith07:03:33

there's no macro there

noisesmith07:03:41

that's just a quasiquote

noisesmith07:03:50

(but yeah, quasiquote can help too)

noisesmith07:03:59

+user=> (let [a 0] ((eval '(fn [x] (println x))) a))
0

noisesmith07:03:44

but quasiquote is just a sugar for building up a list that happens to have your local value in it

noisesmith07:03:23

+user=> `(foo bar baz 22)
(user/foo user/bar user/baz 22)

netsu07:03:42

thank you, it's interesting to use fn as a symbol

armed09:03:57

Hi, folks How to call function from another namespace at application launch? For example, I want to make registry of record constructors, then find constructor by key:

; namespace A
(ns A)

(def registry (atom {}))

(defn register [key creator-fn]
  (swap! registry assoc key creator-fn))

; namespace B
(ns B
  (require '[A :refer [register]]))

(defrecord MyRecord [a b c])

(register :my-key #(->MyRecord %1 %2 %3))
When I load my program using repl registry in A is empty. It populates only when I re-evaluate B file in repl.

Lambda/Sierra13:03:01

@armed You can use ((resolve 'some.namespace/some-symbol) argument) to invoke a function after loading its namespace.

armed13:03:01

@stuartsierra thanks, I'll try

qqq13:03:44

is there a wrapper where I just provie the [result input] form, and it creates a tranducer for me automaticlaly, with ([] (xf)) ([result] (xf result))

bronsa13:03:25

completing

qqq13:03:52

https://github.com/clojure/clojure/blob/010864f8ed828f8d261807b7345f1a539c5b20df/src/clj/clojure/core.clj#L6575 seems different from what I want

(defn make-fn [f]
  (fn [xf]
    (fn
      ([] (xf))
      ([result] (xf result))
      ([result input] (f xf result input)))))
is there anything similar to the make-fn ?

qqq15:03:41

transducer returning one item is: (xf result item) returnint 2 items is

(-> result
  (xf item1)
  (xf item2))
now, supposed I need to return a list of items, is it (reduce xf result lst) this just seems like a weird use of reduce

bronsa15:03:06

that's what cat does

ghadi15:03:52

(let [ 🐈 cat] (into [] 🐈 seq-of-colls))

ghadi15:03:52

i'm sure there's some unicode codepoint out there

noisesmith15:03:16

there's unicode, parameterized by mood

qqq15:03:47

interesting, how about (apply concat (for [ ... ] .... )) is there a way to simplicy this? I know about mapcat but I want to use for instead of map

noisesmith15:03:37

@qqq most of the time you can avoid the concat with for

bronsa15:03:44

unless your f is producing the sequence rather than the colll you're iterating over

noisesmith15:03:48

oh weird, it macroexpanded my '

bronsa15:03:30

but then I guess you can do (for [el coll x (f el)] x) rather than (apply concat (for [el coll] (f el)))

spei15:03:33

@qqq Is there a particular reason you want to use for over mapcat?

timgilbert16:03:14

Say, is there any way to get a list of vars out of a namespace in the order they were defined in the file? (Looking for something similar to (ns-interns) but maybe returning a sorted map)

wotbrew16:03:56

@timgilbert you can use the :line metadata of each var

timgilbert16:03:34

Oh, good idea, thanks!

qqq16:03:00

@spei: yeah, often times, the function doesn't ahve a name, and is multiline, and I want to write it inline, instead of defining it elsewhere

qqq16:03:25

@spei: so it's genrally (map/for, where list = very short expr function = multi line so for just tends to look better than map, atleast to me

noisesmith16:03:43

but for can do what mapcat does, just by adding a clause in its binding block

qqq16:03:28

yeah, I think it can

wotbrew16:03:34

@timgilbert be careful about using a sorted map (or set) because you can in principal have 2 vars share the same line e.g (do (def foo) (def bar)) or (declare baz qux)

wotbrew16:03:16

I guess this also means if you want order of definition it is ambiguous in these cases from the metadata 😞

wotbrew16:03:46

:column to the rescue?

timgilbert16:03:12

I'll keep it in mind, thanks @danstone. For my use-case it shouldn't be a problem; I'm making kind of a mini DSL based on defns, and it's code we're writing ourselves, so I can use pull request mockery and shaming to ensure we have at most one defn per line

timgilbert16:03:05

Ha, but yeah, good point about :column

spei16:03:09

@qqq you can write a fairly cannonical looking multiline map by

(map
  (fn [x]
     (f x))
  coll) 

qqq16:03:43

perahsp just personal prefere, I like:

(for [x lst]
  ....
)
`

nidu16:03:16

Hello. Does anyone know why uberjar may be built successfully without aot but throw java.lang.ClassNotFoundException with aot (3rd party dependency)?

spei16:03:24

fair enough

hiredman16:03:51

aot is the devil

hiredman16:03:48

as always, I recommend not aot compiling

nidu17:03:55

@hiredman is there noticable performance loss or aot may be neglected?

hiredman17:03:10

aot has no effect on performance

hiredman17:03:36

the compiler generates the same jvm bytecode regardless, aot just saves it to disk

nidu17:03:46

@hiredman i thought there's a startup penalty without aot to make what aot actually does

nidu17:03:28

well if only startup performance differs it isn't worth it for me. Thanks!

nooga17:03:03

am I imagining things or clojure 1.9 compiler is slightly faster than 1.8?

seancorfield17:03:41

I think you’re imagining things… I can’t think of any changes between 1.8 and 1.9 that would affect that? I haven’t noticed any speedups (although we moved to 1.9 a long time ago so my memory may be hazy).

Lone Ranger17:03:13

Hey everyone. Just wanted to say thanks for being awesome!

Alex Miller (Clojure team)18:03:43

@nooga @seancorfield there were some minor changes to seq & destructuring and update-in perf - it’s possible these would have a little boost. And CLJ-1423 does have some nice benefits for apply.

Alex Miller (Clojure team)18:03:13

but it seems unlikely any of that would be very noticeable in compilation

nooga18:03:54

@alexmiller @seancorfield yeah, I must have imagined this :(

mobileink18:03:06

is there any way to get the ns of a namespaced map? or, is there an online 1.9 repl i can use to experiment?

noisesmith18:03:37

+user=> {:foo/bar 1}
#:foo{:bar 1}
+user=> {:foo/bar 1 :foo/baz 2}
#:foo{:bar 1, :baz 2}
+user=> {:foo/bar 1 :foo/baz 2 :quux/morp 3}
{:foo/bar 1, :foo/baz 2, :quux/morp 3}
@mobileink a namespaced map is just a convenient read/print syntax, it isn't a type

mobileink18:03:36

right, my use case is, it would be Nice if i could use the map's ns to drive processing.

noisesmith18:03:55

but the map doesn't have an ns - the reader form for a map can...

noisesmith18:03:07

@mobileink I guess as a hack you could check pr-str and see if it starts with #:...{ and extract the ... if so - but it's not a property of the map itself

hiredman18:03:50

maps don't have a namespace though

hiredman18:03:03

so you can't use a maps namespace to drive processing

hiredman18:03:38

"namespaced map" is sort of unfortunate misnomer

hiredman18:03:12

if you want to attach some kind of type tag to a map, do that

bja18:03:46

you chould do something like (apply = (map (comp namespace first) some-map)) to determine if every key in a map has the same namespace

bja18:03:50

I suppose

hiredman18:03:10

the "namespaced map" feature doesn't even mean all the keys have the same namespace

noisesmith18:03:18

bja but the keys don't have to be things that can have namespaces

mobileink18:03:52

yes, this will inevitably lead to confusion, i suppose. but it doesn't really matter if a namespaced map is a map with a namespace or not. we can in fact use #:foo to namespace the keys of a map. it would be easy enuff to iterate over the keys to discover a common ns, if there is one, but i was hoping clojure had an op that would save me the trouble.

bja18:03:57

in the general case they don't, but I'm assuming that in the case of the person who wants to drive processing off the namespace of keys in a map, they are keywords with namespaces

bja18:03:32

although I'd probably enforce such processing via schema

hiredman18:03:21

or stick a :namespace key in the map

mobileink19:03:59

@bja: fyi the idea (just an idea at this point) is that the user can use #:foo{...} to select the foo implementation that interprets the map. all keys are kws, which may be different for different nss.

mobileink19:03:11

i'm not sure how spec could police this; all keys are optional.

bja19:03:12

@mobileink you could pretty easily do this via a multimethod with the dispatch function being (fn [m] (when-let [namespaces (map (comp namespace first) m)] (when (apply = namespaces) (first namespaces)))

bja19:03:56

but hiredman is right, you really should just include a :namespace key in your map

mobileink19:03:22

i'm just getting started with spec. is there a way to specify that all keys in this map must be namespaced either :foo or :bar?

mobileink19:03:46

yeah, that would work, but it seems unaesthetic to me.

mobileink19:03:41

looks like sth like your proposed fn is the say to go.

bja19:03:51

your dispatch might also check that the key is a keyword before calling namespace on it

mobileink19:03:07

but maybe (map namespace (keys m))?

bja19:03:40

I meant that before you call namespace, check that namespace won't throw

bja19:03:55

or wrap it in a try/catch

bja19:03:09

in case your map has non-keywords as keys

mobileink19:03:09

(after checking that all keys are kws simple_smile )

bja19:03:21

but yeah

mobileink19:03:55

sounds gud enuff, thanks all!

bja19:03:59

I'd probably write it such that I validated a schema of {s/Keyword s/Any}, but you can do the same thing with spec (I just don't know how to use spec yet)

mobileink19:03:27

yeah. spec is awesome.

mars0i19:03:51

@mobileink How about (symbol (subs (first (clojure.string/split (str :foo/bar) #"/")) 1))?

mars0i19:03:56

I"m sure there's a more elegant way.

mars0i19:03:45

oh never mind. missed the mention of namespace.

a2_himmel22:03:44

anyone use the cursive ide here? after an intellij update i can't type in the REPL input windowpane any more--the tooltip says "This window is read-only". Any ideas?

shaun-mahood22:03:20

@a2_himmel There's a #cursive channel that's pretty active - I can follow up with you there

a2_himmel22:03:57

@shaun-mahood yeah, just found that and moved the question there

erichmond22:03:34

Dumb question Fridays. Is there a simple way to start a REPL into an existing java process? Meaning, we are running sth like

java -classpath blah.jar blah.core
, now is there a way to connect a REPL to that running process?

hiredman22:03:21

short answer is no

tanzoniteblack22:03:36

@erichmond you have to do something to explicitly have clojure start a repl either through using the system property (read on start up) https://clojure.org/reference/repl_and_main#_launching_a_socket_server or calling the function https://clojure.github.io/clojure/clojure.core-api.html#clojure.core.server/repl

hiredman22:03:50

longer answer is no, but if you happen to have debugging enabled, you might be able to do it

erichmond22:03:17

hiredman / tanzoniteblack Thanks guys! for some reason I thought I had done this in the past (3+ years ago), but it must have been a fever dream

hiredman22:03:21

https://github.com/wirde/swank-inject is an older swank project that uses the java debugging interface to inject a repl

hiredman22:03:01

I am not sure if a modern project to do it exists, but a similar approach would work to start the socket repl

erichmond22:03:25

Do you guys know off the top of your head if there is any appreciable performance hit to spawning a REPL from the process as tanzoniteblack suggested above?

hiredman22:03:11

actually, it sounds like after java 5 the java debuging interface is always enabled, so something like swank-inject could just work

hiredman22:03:43

performance hit how?

tanzoniteblack22:03:00

at my last company, we tended to have any running servers start a repl that was only connectable from the local machine (i.e. through port forwarding) as part of their normal process. Never seemed to have any effect on performance (ignoring the effect on performance you might cause by running code in that repl)

tanzoniteblack22:03:24

but was incredibly useful when we did happen to need to debug a production issue

tanzoniteblack22:03:39

obviously such things should be treated with incredible caution in production 🙂

erichmond22:03:45

yeah, the use case is that our datomic servers are only accessible from our back-end servers, and our back-end servers don’t currently have REPL access. Our backend servers have lots of nice sugar for interacting with datomic.

erichmond22:03:51

I may just keep a third box around just for REPL access

erichmond22:03:03

so we don’t accidentally trash a running app server

erichmond22:03:08

thanks for the insights guys