Fork me on GitHub
#clojure
<
2017-04-16
>
tclamb00:04:12

Have you tried using the pseudoselectors in the garden.selectors namespace? Something like: [:tbody [:tr [(garden.selectors/& (garden.selectors/nth-child :odd)) {:background-color""#ff33c""}] [(garden.selectors/& (garden.selectors/nth-child :even)) {:background-color""#e495e4"}]]] based on https://github.com/noprompt/garden/issues/90

qqq01:04:55

https://github.com/noprompt/garden/search?utf8=%E2%9C%93&amp;q=nth-child&amp;type= <-- is there an example of how to use nth-child pseudo selector? 🙂

jimmy01:04:28

@qqq @tclamb posted a good one. It was my question a year a go xD

qqq01:04:48

@tclamb : ah, thanks! for some reason, I did not see your response until now

qqq02:04:51

I have two lists, lhs and rhs; and I want to find the first index i where (get lhs i) != (get rhs i)

qqq02:04:59

right now, I am thinking of using first, filter, and range

qqq02:04:28

but I feel like there should be a builtin / cleaner solution than (first (filter (fn [i] (not= (get lhs i) (get rhs i))) (range (count rhs))))

qqq03:04:12

got that aresolved via count take-while (map =

tagore03:04:36

Btw, Postgres 10 will change the name of its write-ahead-log andc transaction becuase people kept deleting them.

tagore03:04:00

Apparently if you put the word 'log' in a filename peeps will just come along and clean them up.

tagore04:04:31

So people were just willy-nilly deleting files named things like pg_xact_log

tagore04:04:47

Seems legit.

stardiviner05:04:31

How to solve this problem?

stardiviner05:04:40

WARNING: seqable? already refers to: #'clojure.core/seqable? in namespace: clojure.core.incubator, being replaced by: #'clojure.core.incubator/seqable?
WARNING: seqable? already refers to: #'clojure.core/seqable? in namespace: somnium.congomongo.coerce, being replaced by: #'clojure.core.incubator/seqable?
WARNING: update already refers to: #'clojure.core/update in namespace: useful.map, being replaced by: #'useful.map/update
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/stardiviner/.m2/repository/ch/qos/logback/logback-classic/1.1.3/logback-classic-1.1.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/stardiviner/.m2/repository/org/slf4j/slf4j-nop/1.7.7/slf4j-nop-1.7.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/stardiviner/.m2/repository/org/slf4j/slf4j-log4j12/1.6.5/slf4j-log4j12-1.6.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See  for an explanation.
Exception in thread "main" java.io.FileNotFoundException: Could not locate ring/core/protocols__init.class or ring/core/protocols.clj on classpath., compiling:(ring/util/servlet.clj:1:1)

seancorfield05:04:09

@stardiviner What command did you use that produced that exception? And what's in your project.clj or build.boot file?

stardiviner05:04:57

@seancorfield I added some libraries to Leiningen profile.clj

stardiviner05:04:15

My profile.clj is big.

stardiviner05:04:23

paste it here:

qqq06:04:13

how do I define a new exception type in a *.cljc file ?

seancorfield06:04:26

@stardiviner Good grief!!! Wow... Presumably this worked before you added the last set of libraries?

seancorfield06:04:30

If so... Well, you're going to need to remove libraries a few at a time and see when the exception goes away and then add the last few back one at a time to see which library is triggering the problem...

seancorfield06:04:24

SDH -- Stuart Halloway?

seancorfield06:04:32

And, yeah, RH is Rich.

javahippie12:04:13

Is anybody here with experience on overtone/at-at?

javahippie12:04:15

I have a problem with my code working when directly called, but not if scheduled by at-at. I think it has something to do with threads, but I am not able to find the error right now

javahippie13:04:03

I can see in my traces, that 'upsert-objects' is being called, but not 'upsert-object'. The collection 'objects' contains 23 entries.

leonoel13:04:26

looks like a laziness issue to me

leonoel13:04:43

there is nothing to realize the sequence returned by upsert-objects

javahippie13:04:05

I just realized it works, if I change map to pmap in line 31 of persist.clj

javahippie13:04:37

Shouldn't "(map #(...) seq)" realize a sequence?

leonoel13:04:52

no, map is lazy

leonoel13:04:16

and pmap is not totally eager so you should not rely on that either

leonoel13:04:05

use map for purely computational stuff

javahippie13:04:13

Ah, now I get it.

leonoel13:04:33

for side effects, use run!/reduce/doseq/dorun/doall

javahippie13:04:38

I did not plan to use pmap as it makes no sense here, was just toying around. But thank you for your answer. I think I actually had this error once or twice, but maybe I will finally remember it now 😄

noisesmith15:04:48

use doall if you need to use the return value but you also need it to be calculated right now; use dorun if you don't need the return value ever but you also need to call a lazy function; use run! if you don't need the return value and you were using map with exactly two args; use doseq if you were using for.

javahippie13:04:06

doall works like a charm, thanks!

kwladyka14:04:11

one thing what i don’t understand from this example https://clojure.org/reference/transducers is (def xf (comp (filter odd?) (map inc))) - it is first filter and later inc vs ((comp str +) 1 2 3 4) is first + and later str it is insane 🙂

kwladyka14:04:26

How is that?

qqq14:04:37

becuse it's apssing functions around and they all get inverted

matan14:04:18

does anything in codox or other api docs generation tool for clojure, turn comments about expected arguments structure/meaning into documentation strings about the arguments of a function?

kwladyka14:04:22

@qqq thx, going watch!

qqq14:04:25

I should start charging @tbaldridge marketing fees. His youtube videos are excellent for explaining transducers.

qqq14:04:50

@kwladyka : it's totally worth the $3.99/month if you can watch all the vids in 1 month 🙂

kwladyka14:04:39

oh, it is first time when i see youtube channel with option to pay

matan14:04:42

my question aside, where do you go for those videos? do you mean this: https://www.youtube.com/channel/UC6yONKYeoE2P3bsahDtsimg

kwladyka14:04:46

interesting

qqq14:04:14

@matan: yes, that's the @tbaldridge channel I was referring to

qqq14:04:21

the logic programming ones are excelltn

qqq14:04:47

the rest I ahven't paid as much attention to; worked through the transducer ones only because, for some reason, he uses transducers instead of moands

kwladyka14:04:09

How is it working? It is payment channel but still i can see videos hmm..

qqq14:04:19

some videos are free, some are subscriber only

qqq14:04:30

it's like drug dealers, first video of series = free, rest = paid

kwladyka14:04:46

Is it possible to see what is after pay?

kwladyka14:04:04

*what content

matan14:04:53

the guy looks a bit angry

qqq14:04:47

We should probably also move to #off-topic if there are other questions.

kwladyka14:04:40

but on the other hand… maybe other people will use it too 🙂

matan14:04:29

does anything in codox or other api docs generation tool for clojure, turn comments about expected arguments structure/meaning into documentation strings about the arguments of a function? conversely is there anything in clojure allowing documentation strings per function argument?

qqq14:04:11

so you want to attach meta data to function arguments and read them out later ?

matan14:04:20

@qqq if an automated doc generation tool would grab them..

matan14:04:58

conceptually this is borderline to clojure.spec which deals with argument verification. documentation is another means to alleviate user confusion.

kwladyka14:04:24

Do you know any module to help transform XML data into another structure? I don’t. I am writing my own.

kwladyka14:04:31

But maybe i miss something?

kwladyka14:04:58

and i am talking not about parsing XML, but about convert it to more proper data like {:products [{:name “foo” :price 1}{:name “bar” :price 2}] etc.

qqq14:04:33

if you have two tree formats, clojure.walk should make one easily convertable into the other

kwladyka14:04:13

i already did some part of work, but now i have to add :attrs dependency and few other things. But i want be sure somebody else didn’t do this before me 🙂

kwladyka14:04:50

working with XML without some helpers is nightmare

Pablo Fernandez15:04:55

Is (nth (explain record) 2) the most appropriate way of getting the map schema out of a record schema?

lvh16:04:26

Is there a Clojure profiling tool that works well for expressions that don’t terminate in a reasonable timeframe? (I have an expression in a third party library (intension) — it’s pretty simple, but there’s a preprocessing step I just added that makes the computation time explode. I don’t understand why, and I’d like to learn more :))

lvh16:04:46

I’ve found tufte, which I guess will work if I copy-paste the impl (it’s not complicated) and i use profiled instead of profile (or whatever the one that asynchronously collects data instead of synchronously returning iti s). Maybe I want cider-debug to begin with to see if it’s “obvious”.

emil.a.hammarstrom16:04:32

Is this strictly a clojure discussion chat or is it okay to toss in some beginners questions?

lvh16:04:57

@emil.a.hammarstrom Here’s fine but you might prefer #beginners

emil.a.hammarstrom16:04:14

oh, that channel was hidden, thanks 🙂

weavejester17:04:56

@matan You can always add more metadata to functions. I was considering supporting something like that for Codox, but I haven’t gotten around to it.

weavejester17:04:18

Metadata is generally better for function-level docs than comments.

matan18:04:05

@weavejester Thanks. Still, obviously, I assume no user of my library is going to "see" my functions' metadata (as in (meta my-func)), other than a very advanced clojurian I suspect. That's why support in a docs generation tool could have been nice indeed.

matan18:04:10

If I follow you correctly

noisesmith18:04:48

the :doc metadata shows up if someone uses clojure.repl/doc

noisesmith18:04:56

which everyone should be using...

weavejester18:04:21

Yeah. Codox already supports :doc/format metadata to change the format from plaintext to markdown, and of course the :doc metadata is supported by Clojure. Something similar could be used for arguments etc.

matan18:04:44

@noisesmith @weavejester is there any special format for organizing stuff inside :doc with per-argument comments?

noisesmith18:04:24

there's :arglists in meta, but clojure doesn't support per argument documentation

weavejester18:04:25

Codox supports a markdown extension for definition lists, that I often use for keywords etc.

weavejester18:04:58

And the :arglists meta as @noisesmith mentions, but nothing specific about argument documentatation.

matan18:04:19

could someone possibly refer me to an example usage if you have one on github? I am not sure I gather what @weavejester had meant in "definition lists" up here, but I am sure it is self explanatory to watch an example of that

matan18:04:14

Oh okay I got it

matan18:04:25

You just use markdown bulleted lists

weavejester18:04:07

No, not quite. I use definition lists, which are a markdown extension.

weavejester18:04:40

term
: definition

weavejester18:04:18

It’s not standard markdown, but it’s a useful extension that Pegdown supports, and Flexmark does as well when I get around to moving Codox’s markdown processing to that.

matan18:04:06

So it won't compile to an actual formatted form if used now? or maybe I am confused about the status of this extension

matan18:04:50

Or I'm just not sure how to add this extension to codox https://github.com/weavejester/codox

weavejester18:04:12

It’s in Codox by default

weavejester18:04:22

By “extension” I mean that it’s not standard Markdown

matan18:04:45

So term : definition somehow would render nicely?

weavejester18:04:27

Yes, as long as : is the first character on the line, I believe.

matan18:04:20

Okay this is awesome, I'll go deep into writing codox-ready code. Thanks for maintaining it!! @weavejester

matan18:04:53

are the public clojure language (clojure.core etc) docs created using it?

weavejester18:04:50

clojure.core? No, they have their own autodoc thing. I wrote Codox because I found autodoc to be a little clunky and didn’t support everything I wanted. At the time I believe there was some shell scripts involved to get it all working.

matan19:04:17

@weavejester I don't think autodoc creates anything very magnificent. Being markdown enabled makes Codox much better, so thanks again for maintaining it!

didibus19:04:15

Question: Why doesn't Clojure provide any non volatile local mutable reference?

ghadi19:04:14

to discourage their use

didibus19:04:39

Well, we've got local mutables that are volatile. But as far as I know, it is impossible to have a non volatile one. So its not just discouraged, but impossible.

didibus19:04:03

And from what I understand of volatile, a local mutable does not really need it. Since it's useful only in cases you'll cross a memory barrier, like a thread boundary. Which is rarer for it to happen locally.

noisesmith19:04:31

you can use a box class with a mutable value, clojure doesn't make this simple but it's not hard if you're determined

ghadi19:04:27

they're there for sure, i'm not going to tell anyone about them

didibus19:04:42

haha, ok fair enough

didibus19:04:22

What about global non volatiles? Can I optimize access to a Var by making it non volatile somehow, if I know what I'm doing?

mobileink19:04:50

you have to know the secret handshake to use them.

ghadi19:04:22

"more constant" vars have been a common request over the years. the closest thing we have is "direct linking" in clojure 1.8

didibus19:04:41

lol, I should probably start by signing the clojure contributor's agreement if I want in

ghadi19:04:52

which is a compiler mode that turns var calls into static method calls

ghadi19:04:19

but it's doubtful that var invocation is a bottleneck in most programs

didibus19:04:28

Right, ok. So I assume the choice was made this way so that by default shared memory is atomic in Clojure. Which comes at a minimal access cost for 90% of the use cases.

noisesmith19:04:40

@didibus literally anything you could do in java is possible with clojure, worst case you write 10 lines of java; usually you won't need to do that. But the things that are made difficult or inconvenient are actually problematic in the cases I've dealt with. The language is trying to help, it's just opinionated about how it does so.

noisesmith19:04:46

I'd say even 90 is low

didibus19:04:10

Ok, cool. Ya this all makes sense

didibus19:04:16

I was mostly curious

alex.ter.weele21:04:27

should I expect this to work?

(defprotocol One (one [_]))
(let [c 1]
    (defrecord OneImpl []
      One
      (one [_] c)))
I’m currently getting Unable to resolve symbol: c in this context, pointing to the usage of c in the implementation of one.

elena.poot22:04:33

functions in a defrecord are not lexical closures, they can only access fields. functions inside reify are lexical closures, so if you change defrecord to reify, that would work, but I don't know if it would do whatever else you want it to do.

alex.ter.weele22:04:51

ah, thanks. I expected the entirety of defrecord to work with a lexical clojure, but that makes sense. I’d prefer to use reify but for what I’m trying to do, I need a named class

elena.poot22:04:40

I was a bit surprised as well, but in my case reify turned out to be just what I needed in that case. With defrecord you'd need to add c to the field list and pass the value to the constructor when instantiating the record.

matan22:04:47

@ghadi I wonder how much "direct linking" breaks other features of the language, as is typically the case when a new foundational option is added late in the game, that it doesn't play well with other existing features.

noisesmith22:04:20

good code shouldn't be assigning to vars at runtime

noisesmith22:04:35

no mainstream library should be doing it, at the very least

noisesmith22:04:49

(this is with the exception of using def and defn during dev with a repl of course)

noisesmith22:04:51

and if direct linking breaks something, the fix is to put a mutable container in the var, and then deref that, which isn't all that complicated a fix

noisesmith22:04:54

expectations is a dev time tool

matan22:04:30

:thumbsup:

noisesmith22:04:24

I wouldn't want to use direct linking during dev, but I would also expect the things it breaks to be relatively rare and easy to fix (this was my experience with my product codebase)

didibus23:04:34

@noisesmith Wouldn't direct linking break all features of Vars apart from just the pointer behaviour? Like dynamic is gone, volatile is gone, watches are gone, validators are gone, etc. ?

matan23:04:45

@noisesmith I am trying to cross-reference this with https://clojure.org/reference/compilation#directlinking. Two things I haven't wrapped my head around are: In that doc: > If you wish to mark a var as supporting redefinition (but not dynamic), mark it with ^:redef to avoid direct linking. what is a "not dynamic" redefinition? And in your comment above: > the fix is to put a mutable container in the var, and then deref that What do you mean by a "mutable container"?

didibus23:04:02

@matan Non dynamic redef is a root binding redef

didibus23:04:34

I think he means something like an atom, or a volatile.

didibus23:04:10

So when you you direct link, you direct link to a reference type, you're almost back to having no direct linking at that point. I think it is still a bit faster because you save yourself the namespace symbol lookup

matan23:04:26

@didibus okay, cross-reading it all a few times, I get the intent of the the first sentence now >If you wish to mark a var as supporting redefinition (but not dynamic), mark it with ^:redef to avoid direct linking.

matan23:04:51

I guess an atom or something like that fits well there indeed, it will in fact "bypass" the static impact of direct linking.. if the actual value sits inside of an atom.

didibus23:04:20

So, I think direct linking replaces the symbol with the actual object. Nornally, without it, you have to do a map lookup of the symbol, which returns you the Var, and then you deref the Var and that gives you the object. So its a double hop

matan23:04:44

Yes, that's clear

didibus23:04:05

If you direct link to a Volatile, you just have to do one hop, deref the volatile

didibus23:04:35

I wonder if that's what ^:redef does for you

didibus23:04:54

A volatile is a var with none of the bells and whistles

didibus23:04:11

It would explain why it can't do dynamic for example

didibus23:04:41

But I'm not sure that direct linking replaces the symbol lookup to be honest

didibus23:04:17

Hum, actually, I think the namespace has to be looked up also, so it could even be a quadruple look up.

matan23:04:37

I'm not yet very sure how to think about volatiles in clojure, but obviously it is easy to avoid direct linking per Var: >If you wish to mark a var as supporting redefinition (but not dynamic), mark it with ^:redef to avoid direct linking. I am not sure how a volatile would behave differently and what other side-effects it may bring compared to ^:redef. Obviously from java docs a volatile is a loosely synchronized object, which can obviously be mutated, maybe it uses some form of indirection for reasons I am not aware of, and hence resilient to direct linking.

didibus23:04:54

Each cpu on a machine has a cache. If a value in ram is equal to 10. And one cpu writes to it, another one reads. So say one does inc on it, and the other does while < 100.

didibus23:04:09

Now, because both cpu have a cache, the writer will cache the value, increment it a few times, and then flush it back to ram. The reader will do the same, so the value in ram will not go 10, 11, 12, 13, but it might be jumping 10, 13, 18

didibus23:04:56

If it's really important for the reading cpu to break the loop at exactly 100, you'll need to make the variable volatile

didibus23:04:18

This tells the JVM, skip the cpu cache for this variable

didibus23:04:27

In Clojure, globals are always volatile.

didibus23:04:46

A Var is volatile. But a Var is a big object, it has like tons of extra features, such as dynamic, metadata, watches, validators, etc.

didibus23:04:08

Volatile is just a volatile variable with nothing more.

matan23:04:25

How does it, if at all, relate to direct linking?

didibus23:04:25

Well, I have no idea if volatiles are involved. But, if you're direct linking, you do it for performance. A volatile is faster than a Var, because it does nothing more then get and set a java volatile variable. So if you need performance to the point of direct linking, and you don't care about all the features of Var, it would make sense to me to use volatile

didibus23:04:47

Given you wanted redef

didibus23:04:24

Without redef, than you wouldn't need one, just replace the whole thing by the actual object. But if you want redef and the best performance, I think direct linking to a volatile that points to your object would be the fastest

matan23:04:06

okay, lets give volatiles a rest, they provide shared state without atomicity guarantees, and might not be much related here. If I am not very mistaken, the 1.8 announcement only says they are faster than atoms, not sure how they really relate to vars https://github.com/clojure/clojure/blob/master/changes.md

didibus23:04:28

No, volatile are atomic. They do not provide mechanism to control code execution synchronization. Same as Vars.

matan23:04:24

> Volatiles are faster than atoms but give up atomicity guarantees so should only be used with thread isolation.

didibus23:04:43

Yes, compared to atoms

didibus23:04:59

But I'm comparing them to Vars

didibus23:04:55

redef, such as changing the function definition, and loading it up again, this just needs atomic updates, it does not need to synchronize a code blocck

didibus23:04:26

All you want to do is swap one object for another atomically. Volatile will do this

didibus23:04:29

But it would not let you do: (if (= 10 v) (inc v)) in a safe way. Because that code block will not be executed atomically.

didibus23:04:28

An atom does this, by using a compare and swap (swap!) function. Which will make the whole thing atomic.

matan23:04:34

I fail to see how volatile compares to a regular Var which is by definition static, in Java/JVM jargon

matan23:04:11

Projecting the java meanings of volatile and static to the world of clojure is not entirely straightforward to me

didibus23:04:56

You just need to look at their implementation. A var has volatile Object root and a get and set that does: root = new-value; and return root. And volatile is the same: volatile Object val, val = new-value;, return val.

didibus23:04:31

The difference is that Var has many more fields and methods on its class.

didibus23:04:42

So instantiating a Var is slower.

didibus23:04:20

And the get and set functions will do things like call the validator, call all the watchers, etc.

didibus23:04:29

So they will be slower

didibus23:04:58

Anyways, we're getting pretty low level. Back to direct linking. I'm not sure what gets direct linked, if its just the Var is replaced by the object itself, or the symbol is replaced.

didibus23:04:29

The doc says that if you mark it dynamic, it won't be direct linked. This makes sense, that just means nothing is changed and everything is as normal. But, what does ^:redef do? If the symbol still points to a Var, its not logical that dynamic would not work. So I'm hypothesizing that redef might actually use a different thing than a Var

didibus23:04:34

Unless ^:redef just makes a Var that has dynamic behavior disabled. Actually, its probably that.