Fork me on GitHub
#clojure
<
2019-08-19
>
Silenced Ego01:08:06

why is it (ns foo.bar (:require.. and not (ns foo.bar ('require... why keywords and not symbols? If keywords as list first arg usually mean map indexing

Silenced Ego01:08:52

or even just (require .... since ns is a macro no need to quote..?

Alex Miller (Clojure team)01:08:24

this syntax, as central as it is, was not deeply considered - it was actually one of the first significant external contributions to Clojure

Alex Miller (Clojure team)01:08:43

if created today, it would likely be quite different

Alex Miller (Clojure team)01:08:13

so I don't think there is a great justification for it

Stefan07:08:43

Hehe last week I hosted a coding dojo about clojure, for people new to it, and the ns form was indeed puzzling to most, and I was not able to clarify much 🙂

andrea.crotti08:08:55

Yeah I'm always been puzzled as well, how did you declare a namespace before that by the way?

andy.fingerhut08:08:33

I do not recall, but note that you can implement the effect of an ns form with a combination of create-ns, in-ns, require, and import calls (probably with a few exceptions I am forgetting about, that require a few other calls to implement).

vemv11:08:17

Let's say I place a nonsensical type hint, shouldn't that cause a runtime error?

(let [^String a (fn []
                   42)]
  (.invoke a))

dominicm11:08:43

Isn't that metadata, instead of a type hint?

dominicm11:08:13

I have no idea, just guessing.

dominicm11:08:14

nvm, I'm completely barking up the wrong tree 😄

dominicm11:08:37

@vemv fwiw, that generates a reflection warning:

user=> (set! *warn-on-reflection* true)
true
(let [^String a (fn []
                   42)]
  (.invoke a))
Reflection warning, NO_SOURCE_PATH:3:3 - reference to field invoke on java.lang.String can't be resolved.
42

vemv11:08:29

yup, I would normally get the warning as well but I was concerned that placing useless/wrong info can be compiled successfully IIRC under certain circumstances, placing the wrong hint would cause a runtime error? I'd appreciate such behavior, always

dominicm11:08:20

maybe it's not a runtime error, but a compile error?

dominicm11:08:20

https://stackoverflow.com/questions/34963349/why-doesnt-the-clojure-compiler-throw-an-error-for-an-incorrect-type-hint Notably this comment: > quick demo of what you're saying about hints and errors user=> (.length ^String [1 2 3]) 3 user=> (defn strlen [^String s] (.length s)) #'user/strlen user=> (strlen [1 2 3]) ClassCastException clojure.lang.PersistentVector cannot be cast to java.lang.String user/strlen (NO_SOURCE_FILE:4) – noisesmith Jan 23 '16 at 13:53

dominicm11:08:38

Interestingly, it looks like that's only for caller errors, not hinting errors. For example, if you do:

user=> (defn foo [^String a] (.invoke a))
#'user/foo
That's not gonna blow up, probably because the code generated was reflection. But in the length example above it does because the bytecode was generated against String.

4
vemv11:08:02

Good links / examples! Probably what I want is simply not implemented - what I remembered (`IIRC [...]`) was an instance of a caller error, not a hinting error. I wish there was a *throw-on-reflection* option - or at least a weaker variant: *throw-on-wrong-reflection*

kah0ona12:08:00

Hello, I need to build up a string and then make it a regex. I can do this by re-pattern, but I’m struggling with ‘unallowed escape character’ for the string parts. Prefixed with # they are ok, but not when they are strings. For instance: #"\-" is ok, but "\=" (as a string), isn’t

kah0ona12:08:27

how to transform the latter into a string that, when used in re-pattern, wil produce the former?

Andrew13:08:29

user=> (re-pattern "\\=")
#"\="

kah0ona13:08:34

hm i thought i ’ve tried that (this is a simplified example of course), but that’s the way to go?

kah0ona13:08:53

ah yeah it works, i typo’d befoer

👍 4
Jakub HolĂ˝ (HolyJak)15:08:00

We need more volunteer mentors for http://Exercism.io https://exercism.io/, helping folks who want to learn Clojure. Perhaps you can help us? Once you get going, it doesn't need to take more than few minutes per review. (Ideally 1h/week but any contribution will help us fight the growing queue)! Thanks!

👀 4
zane16:08:28

@U0522TWDA Perhaps worth reposting in #code-reviews?

👍 4
enforser17:08:24

I'd be interested in participating in this! I haven't worked professionally in Clojure for about 6 months, and have been itching to get back into it in some capacity! How do you become a mentor? I signed in but think I may be restricted to just the mentee role?

hlolli17:08:39

I discovered a tab on the upper right corner that says become a mentor. Already reviewed a few solutions. Quite easy to do.

👍 4
❤️ 4
Chase19:08:45

As a learner, I just want to say thanks to you folks for considering this. I've found exercism a fun way to learn and I also bring my solutions to the #beginners channel for even more education. It's been great.

❤️ 4
Chase19:08:03

But yeah, the queue does take a while but it's all volunteer work so I gladly work on other problems while I wait.

Chase19:08:01

It's weird I submitted one solution on the mentor track but my place in line keeps moving back because it's the 5th or 6th exercise so they keep putting the earlier ones before me. c'est la vie!

Jakub HolĂ˝ (HolyJak)19:08:10

Well, personally I haven't got beyond mentoring the first three.... [yet]

Phil Jackson16:08:03

Hey. When I call (stest/instrumentable-syms), a bunch of definitions are listed that I would expect. However, when I call (stest/instrument) on the next line, nothing is instrumented. Perhaps I'm misunderstanding, but shouldn't they echo each other?

Alex Miller (Clojure team)16:08:14

instrumentable means "can be instrumented", not "is instrumented"

Phil Jackson16:08:45

But if I call instrument with no args, shouldn't it instrument everything?

Alex Miller (Clojure team)16:08:12

it will instrument everything in the registry

Alex Miller (Clojure team)16:08:07

you need to run code (typically by loading a namespace that has top-level s/defs) to put specs in the registry

Alex Miller (Clojure team)16:08:29

the things in your registry can be seen with (keys (s/registry))

Phil Jackson16:08:06

Hmmm, I think I'm falling afoul of some shadow reload magic that I don't understand.

Phil Jackson16:08:15

Thanks, Alex. I'll keep playing.

Phil Jackson16:08:43

Yea, it's magic related. Reloading the page makes everything behave as expected.

Phil Jackson16:08:54

:man-shrugging:

g17:08:57

hey guys. i’m trying to cobble together a datastructure that is as close to a map as possible (in terms of behaviour and performance characteristics), with one additional property: i can keep track of last access time for each item.

g17:08:28

some ideas that came to mind were tuplifying the values, or somehow adding a metadata tag to each record

g17:08:43

(not sure how i’d do the latter)

andy.fingerhut17:08:47

access meaning the last time the key was looked up?

andy.fingerhut17:08:20

Then you will need to override some low-level access Java methods (if you are using Clojure/Java) to modify how the lookup behaves.

andy.fingerhut17:08:12

There are examples of other data structures built on top of Clojure maps that do this, if you would like to see how others have done similar things. data.priority-map for one, although it modifies more about the behavior than you want to.

g17:08:16

hmm, sweet. thanks

g17:08:29

i guess i’m not too concerned about sort order, now that i think about it. if that’s the best way to go about it, then it should be fine

andy.fingerhut17:08:22

I point at that example not because of the sort order, but because it shows one way to change the behavior of a data structure that otherwise behaves like a map.

g17:08:04

gotcha

Silenced Ego19:08:21

Hi guys, I'm new to spacemacs and lisp editing and I'm having trouble creating complicated expressions. I feel like I'm managing the parentheses and indenting wrong. How do experienced people manage these?

ghadi19:08:08

Clojure programmers tend to use structural editing -- enable paredit in Emacs

Silenced Ego19:08:19

thanks, I will try this

Silenced Ego23:08:57

is there any other operation besides slurp / barf that is important for editing lisp?

Suni Masuno23:08:39

I find "next token" important, n in vim. and matching paren, % in vim. and "end of form" I use f) in vim or start of form F( in vim. There is certainly a version in your system of choice.

Suni Masuno19:08:35

(not a spacemacs user but when people are annoyed by parens in lisp editing it's usually that they want slurp/barf)

g20:08:17

would it be unwise to put something like a memcached connection inside an atom, given that it’s supposed to be multithreaded? i guess i’m a little fuzzy on how atoms work under the hood, i assume they can only be accessed by one thread at a time

noisesmith20:08:35

atoms have no thread protection - they don't use locks to protect access during updates

Suni Masuno20:08:13

swap! achieves some of that, but yeah, it's far from the same thing.

noisesmith20:08:42

it's worse - swap! guarantees behavior that will cause errors if trying to do updates to something mutable

noisesmith20:08:13

either it detects the mutable object equality via reference and doesn't protect against race conditions at all

g20:08:18

the line in the docs “changes are always free of race conditions” threw me off i suppose, sounded like thread protection to me

noisesmith20:08:33

that's only if the object inside is immutable

noisesmith20:08:43

it does thread safety via compare and set retries

noisesmith20:08:55

which assumes you can do a change, and throw it away and retry on a new target

noisesmith20:08:17

this will cause errors if the object inside the atom is mutable and your swap! function mutates it

g20:08:49

gotcha. ok, sounds like i’m alright for a connection then, since i’m not really mutating it after it’s opened

noisesmith20:08:16

is it a problem if your old connection is simply dangling without being closed?

noisesmith20:08:29

that would be the failure case

g20:08:11

i’m not 100% sure, i imagine nothing would happen, but that’s a good thing to keep in mind. thanks

andy.fingerhut20:08:06

It should be fine if you have mutable objects inside of the atom, e.g. as values of keys inside an immutable map, if you are just 'carrying them along unmodified' by the swap! fn as associated values in the map. True?

andy.fingerhut20:08:45

If that is OK, it is because the mutable values are not really being mutated, but used as unchanged values inside the swap!

noisesmith20:08:33

right - you could even have the mutable object naked in the atom, so to speak, as long as all you do is replace it and let it leave scope

noisesmith20:08:57

but that takes discipline and introduces the possibility of nasty bugs if the next dev touching related code misunderstands

noisesmith20:08:27

(if you are willing to rely on dev reasoning and discipline you can just go back to old fashioned mutex locks haha...)

andy.fingerhut20:08:34

sure. I only ask because, if I understand correctly, sometimes people create applications with a 'big config map', where some of the values associated with keys are mutable objects. Not sure if I understand that correctly.

noisesmith20:08:42

oh yeah - but if you look at the docs / README for the lib most commonly used for this (stuartsierra/component) they explicitly don't suggest using an atom, and instead want you to use a runtime argument in prod, and a var in dev

noisesmith20:08:29

which eliminates questions of retries entirely (and doesn't hurt the semantics, since that map should only be updated from the top level immediately after a code reload - it's part of dev UI)

noisesmith20:08:30

@UAKE446AJ I didn't even think to ask, but is the memcached connection soemthing that you need to protect against concurrent reads? (that's rare but I'm realizing it is an issue with some kinds of objects...)

g20:08:46

no, my datastore is immutable

g20:08:55

should be ok

noisesmith20:08:43

cool - the underlying java layer probably takes care of read consistency for you when writes are going on anyway

g20:08:33

(maybe better for #beginners )

imetallica20:08:42

Is anyone using vertx with clojure?

Bryan Duxbury21:08:20

hi folks, does anyone have experience trying to construct sorted-map instances from already sorted input? i'm trying to avoid the O(n log n) cost of doing an (into (sorted-map) ...)

noisesmith21:08:10

no matter how you construct it, using clojure's sorted map it will still need to do the extra work to build the underlying b-tree which as I understand it is where that cost is coming from

noisesmith21:08:48

I guess you could make your own pre-sorted map that doesn't support assoc/dissoc?

noisesmith21:08:30

but I think that cost is unavoidable once you guarantee sorting and allow deriving new maps by adding or removing keys

noisesmith21:08:18

you could use an insertion-sorted map I guess, there's a few versions available

andy.fingerhut21:08:39

The underlying red-black tree should be constructable in linear time, with a function written specifically for that purpose, which assumed/knew that the input sequence was already sorted. It would not be the existing constructor code, I don't think.

noisesmith21:08:33

oh, it could even use something like spliterator right? (with each split being directly turned into a branch) n/m that wouldn't work

borkdude21:08:21

how do I test an interactive terminal program that reads from stdin, prints something, reads something again? reason I'm asking: https://github.com/borkdude/jet/pull/33#issuecomment-522327719

borkdude21:08:44

also: it first reads from stdin and then switched to /dev/tty

andy.fingerhut23:08:08

You want an automated test that normally reads from the terminal, but during the automated test does not read from the terminal?