Fork me on GitHub
#clojure
<
2019-11-01
>
Nazral06:11:11

Hi! If I define two specs a and b that define two maps, is it possible to generate c as the union of the two specs ?

Nazral06:11:01

e.g .

(s/def ::a (s/keys :req-un [::foo]))
(s/def ::b (s/keys :req-un [::bar]))
could I define a s/def ::c from ::a and ::b that is equivalent to s/keys :req-un [::foo ::bar] ?

Nazral06:11:33

Ah it's sufficient to do (s/and ::a ::b), sorry, I didn't expect it to be that straightforward

dmarjenburgh09:11:09

For entity maps, (s/merge ::a ::b) might be closer to what you want

๐Ÿ‘ 1
vikeri11:11:25

Hi, Iโ€™m trying to parse a fairly large xml file (230MB) using clojure.data.xml but if I accidentally evaluate something that is too big then the REPL crashes. Any tips on how to work with big files in the REPL?

dmarjenburgh12:11:27

Be very careful what you evaluate ๐Ÿ™‚. Other than that, setting print-length can offer some protection. https://clojuredocs.org/clojure.core/*print-length*

vikeri13:11:04

Yes! I knew I vaguely recall something like that

andy.fingerhut13:11:17

Also perhaps your JVM's max memory settings could/should be increased? e.g. -Xmx2G or something like that.

andy.fingerhut13:11:53

Without specifying it, the default max memory is auto-calculated by the JVM when it starts up, perhaps different than you would want it to be.

vikeri11:11:48

Also, how do I get rid of all the \n in the output? I tried with :include-node? #{:element} but then the string content of the element was also removed

vikeri11:11:19

Maybe I should take this in #xml though

kwladyka12:11:29

Has somebody a github actions clojars deploy example using deps.edn (`clojure` command)?

Arto Kalishian12:11:54

Has there ever been a heated debate on Clojure vs Clojurescript (jvm/node) on this channel? And who won? :)

vikeri13:11:55

@arto.eg Even though I develop a lot of ClojureScript for the frontend I always prefer Clojure for the backend. Performance and tooling is generally a lot better. But, I do find js libs and sdks a lot simpler to integrate with. Things like uploading a file to S3 is just way less convoluted. For some libs I prefer the rest-api over the Java SDK.

๐Ÿ‘ 1
jsyrjala13:11:20

Iโ€™d like to do some 2d graphics with Clojure in JVM. Basically graphics for arcade style game. Focus more on easy to use than on perfomance/visual quality. What would be good libs to look at?

jsyrjala16:11:25

googling for java game-engine gave this https://litiengine.com/ and seems to close enough to what I was looking for

Brian14:11:06

Anyone familiar with transit here?

Brian14:11:39

I have a problem where transit is eating my single quote character '

Brian14:11:55

I run this statement through transit [{'(add-hash {:note "hello"}) [:artifact/note2]}] and when I receive it on the other side I get [{(add-hash {:note "hello"}) [:artifact/note2]}] where the single quote on character 3 has now disappeared

Brian14:11:37

Here add-hash is a mutation and I'm throwing that query into Pathom when I receive it

bfabry14:11:16

tried using (quote ...) instead?

bfabry14:11:51

or I guess you could quote it twice, seeing as it's just plain data

Brian14:11:09

(defn transitize [query]
    (let [out (ByteArrayOutputStream. 4096)]
      (transit/write (transit/writer out :json) query)
      (.toString out)))
Maybe my problem is how I am putting it into transit?

alexmiller14:11:17

the quote means "read, but don't evaluate". Clojure is reading it and making a list - this is all expected behavior

Brian14:11:47

Right I had a feeling it was evaluating it while packaging it. How can I tell it not to do that?

alexmiller14:11:01

I don't understand what you want it to do

alexmiller14:11:22

if you want it to be data, it's data on the other side so you've accomplished the goal of ' already

alexmiller14:11:36

if you want it to be evaluated, you'll need to eval it on the other side

Brian14:11:06

The problem is that when I un-transit the data, I end up with [{(add-hash {:note "hello"}) [:artifact/note2]}] and pathom says "invalid expression". But when I throw [{'(add-hash {:note "hello"}) [:artifact/note2]}] into pathom it works perfectly. So either I need that single quote to stick around, or I need some other solution that will satisfy pathom

alexmiller14:11:41

I think you're misidentifying the problem

alexmiller14:11:16

but not being familiar with the pathom api and your actual code it's hard for me to suggest something

alexmiller14:11:57

the quote is a reader shortcut for (quote ...)

Brian14:11:18

Ah I found the answer. I've understood what @bfabry was suggesting. I can write (<!! (parser {} (quote [{(add-hash {:note "hello"}) [:artifact/note2]}]))) and it works perfectly

Brian14:11:53

which means on the function side after reading off the wire, it looks like (<!! (parser {} (quote query))) and so it'll work for everything

paul93122416:11:32

Hello, how do I replace - to \-? I tried this code below, but it returns "-"

andy.fingerhut16:11:23

Try (clojure.string/replace "-a-" #"-" (clojure.string/re-quote-replacement "\\-"))

hiredman16:11:45

or use \\\\

andy.fingerhut16:11:08

The characters $ and \ are special when doing a regex/string replacement using Clojure.string/replace. The doc string mentions $, but not \

andy.fingerhut16:11:19

This also works. (clojure.string/replace "-a-" "-" "\\-"). Note that the second arg is a string, not a regex, which makes a difference in replace's behavior, again mentioned in the doc string.

๐Ÿ‘ 1
paul93122416:11:34

I tried all of the mentioned above. I've got "\\-a\\-" for all of them in the repl

andy.fingerhut16:11:57

That is a sequence of.5 characters in memory

chepprey16:11:29

user=> (println "\\-a\\-")
\-a\-
nil
user=> 

andy.fingerhut16:11:07

Different ways of printing a string produce either something that can be read back in via Clojure's reader, thus requiring extra \ escape characters, and some do not. println does not, by default.

paul93122416:11:08

I've setup victoriametrics, and I need to escape the dash character , I try it maybe works with two dashes

andy.fingerhut16:11:47

Try (count s) on a string to see how many characters it really is, no matter how it prints. Or (map int s) to see the sequence of Unicode code points it contains.

andy.fingerhut16:11:08

user=> (map int (clojure.string/replace "-a-" "-" "\\-"))
(92 45 97 92 45)

andy.fingerhut16:11:11

That is 5 characters

paul93122416:11:31

it totally works, thank you very much!

andy.fingerhut16:11:34

Escaping can be tricky, I agree, and it can be extra confusing given that different ways of printing strings can add escaping, vs. others that do not.

paul93122416:11:55

true, and I needed this because in promql queries the dash is a special character, and I needed to escape that one too ๐Ÿ˜„

chepprey16:11:12

The dash character is not a problematic character for URL's, so your need to escape this must be for the benefit of "victoriametrics"... perhaps it might be better to use standard URL encoding?

๐Ÿ‘ 1
chepprey16:11:43

for ex match[]=aseso_free\-ram --> match%5B%5D%3Daseso_free%5C-ram

paul93122417:11:48

that also totally works, never thought about like this, thank you for the new perspective. (Interesting but with match%5B%5D%3Daseso_free%5C-ram it doesnt work, but with match[]=aseso_free%5C-ram it does)

didibus17:11:12

Question , is there any way to have clojure.test tests with some sort of data provider? Like say I want to run the same test 10 times but with different inputs ?

borkdude17:11:51

@didibus I use dynamic vars (as a workaround for deftest not having arguments)

borkdude17:11:48

yeah, for short snippets are is nice, but I was writing integration tests which were like a page long

didibus17:11:34

Oh, thanks, those are both great options I hadn't thought of.

alexmiller17:11:06

at some point, writing your own test macros that do more makes sense

hiredman17:11:06

I've used fixtures with dynamic vars

hiredman17:11:34

e.g. binding whatever to different values and invoking the input function again

borkdude17:11:20

heck, even normal atoms work I guess. Just write a function that does take inputs, set an atom, run the test

borkdude17:11:51

Clojure gives plenty of ways to hack around issues ๐Ÿ™‚

didibus18:11:17

Haha, ya. I think for my particular case, fixtures with dynamic vars will work well

noisesmith18:11:49

also, even without dynamic bindings, is calls inside a function bubble up to the containing test

noisesmith18:11:15

so you can have a function that takes args which contains all your assertions, and call that with different args for your various setups

eraserhd18:11:24

It might be my test reporter, but when I do this with is, it reports the same source location for any failure.

eraserhd18:11:01

It correctly reports the test case name, but if I reuse the function in that test case, I don't know what's failed.

seancorfield18:11:18

This is good feedback for future versions of clojure.test if/when it gets broken out of core to a Contrib lib that can evolve independently ๐Ÿ™‚

seancorfield18:11:14

@eraserhd Yeah, is will just report the location of itself, rather than further up the call chain.

eraserhd18:11:47

My feedback is that the sort of literate is/`are`/`testing` seemed really nice, except it never works out that I can make sentences from them.

noisesmith18:11:56

I wonder if testing at the call site helps here

seancorfield18:11:06

Yeah, it would

user=> (require '[clojure.test :as t])
nil
user=> (defn foo [x] (t/is (pos? x)))
#'user/foo
(t/deftest foo-use
(t/testing "first"
(foo -1))
(t/testing "second"
(foo -2))
)
#'user/foo-use
user=> (foo-use)

FAIL in (foo-use) (NO_SOURCE_FILE:1)
first
expected: (pos? x)
  actual: (not (pos? -1))

FAIL in (foo-use) (NO_SOURCE_FILE:1)
second
expected: (pos? x)
  actual: (not (pos? -2))
nil

dominicm18:11:10

I've very little experience with other test runners, I'm really interested to see what someone can do with it.

didibus18:11:05

That's what I do

didibus18:11:36

(testing "that when this bla bla then that" (is ...) (is ...) (is ...)) (testing "that some other thing....)

didibus18:11:07

And I generally write it like I would write the readme guide for it.

didibus18:11:37

Like: You can also do this... And if you want to bla you can pass an additional X, etc.

ajs18:11:18

would I be close in assuming that the time complexity for float-array on a vector is on average linear? The vector is not a linear chunk of memory (necessarily) so it would need to be flattened or copied, is that right?

andy.fingerhut18:11:52

Yes, it is copied, and is close enough to linear time that it is reasonable to think of it that way (pedantically, there is an O(log N) factor in there with a base 32 log).

๐Ÿ‘ 1
hlolli18:11:18

Can I force a macro def to return a var of a symbol? I notice that it's possible to get the var, if I def the marco'd def

(defmacro defdummy [name]
  (let [name (with-meta name {:some :here})]
    `(def ~name 1)))
(def k (defdummy z))

(meta z) => nil
(meta k)  => {:some :here, :line 21, ....}
it seems strange, and I bet this wasn't always like this in clojure.

alexmiller19:11:48

it's unclear to me what you are asking? def returns a var and there are other ways to make vars, which would allow you to return them

alexmiller19:11:38

intern, resolve, var all potentially useful, depending on goals

hlolli19:11:04

I would love it I can return get var? true on the symbol that was defined from within a macro body

hlolli19:11:11

I knew about var, the other two, haven't tried!

alexmiller19:11:23

well, symbols aren't vars so that doesn't make sense

alexmiller19:11:51

a symbol is name that resolves (possibly) to a var in the scope of a namespace

hlolli19:11:18

the reson I'm asking is that something broke in overtone, could be my fault. But the print-method aren't picking the type, so def's that have huge AST, are being printed, which is sometimes a mb of data.

seancorfield19:11:55

user=> (defmacro defdummy [name] `(def ~(vary-meta name merge {:some :here}) 1))
#'user/defdummy
user=> (defdummy z)
#'user/z
user=> (meta z)
nil
user=> (meta #'z)
{:some :here, :line 1, :column 1, :file "NO_SOURCE_PATH", :name z, :ns #object[clojure.lang.Namespace 0x65e61854 "user"]}
user=> 
That follows the pattern used by deftest. Note that (meta z) is asking for the metadata on the value of z whereas (meta #'z) is asking for the metadata on the var z.

hlolli19:11:57

but what I'm able to reproduce is that print-method isn't receiving any type because the metadata

seancorfield19:11:41

In your code above, k is bound to the Var, not the value.

hlolli19:11:59

Yes, despite being less efficient, for the use case of overtone, it would make sense to have the var instead of the symbol

seancorfield19:11:00

(so the value of k is #'z)

hlolli19:11:16

yes exactly

hlolli19:11:32

I'll try intern/resolve

hlolli19:11:44

I just tried var, and it doesn't mix well with macros

alexmiller19:11:09

no, usually not what you want if you're making something new

seancorfield19:11:14

user=> (meta (var z))
{:some :here, :line 1, :column 1, :file "NO_SOURCE_PATH", :name z, :ns #object[clojure.lang.Namespace 0x65e61854 "user"]}
^ That is var called on a symbol defined by a macro.

hlolli19:11:24

(defmacro defdummy [name]
  (let [name (with-meta name {:some :here}]
    `(do (def ~name 1)
         (var ~name))))
(defdummy z)
(var? z) => false

seancorfield19:11:17

z is 1, not a Var

alexmiller19:11:50

I think you're going down the wrong path and you should go back and understand why your first thing didn't work

hlolli19:11:40

this code is ancient, but it did work until recently (this was first reported about like a year ago)

alexmiller19:11:51

in your very first example:

hlolli19:11:52

I agree, there's too much hacking there in the codebase

alexmiller19:11:53

(defmacro defdummy [name]
  (let [name (with-meta name {:some :here})]
    `(def ~name 1)))
(def k (defdummy z))

(meta z) => nil

alexmiller19:11:30

right there, you are asking for meta on the symbol z that you just made, which is nil

hlolli19:11:57

yes, and I understand that symbols don't have the meta like vars

alexmiller19:11:58

the meta is on the var

alexmiller19:11:01

user=> (meta #'z)
{:some :here, :line 1, :column 1, :file "NO_SOURCE_PATH", :name z, :ns #object[clojure.lang.Namespace 0x695a69a1 "user"]}

hlolli19:11:28

if I can bind k to the var of z, can't I bind z to the var of z too?

alexmiller19:11:28

in other words, defdummy is doing exactly what you want it to do afaict

alexmiller19:11:58

can't I bind z to the var of z !?

alexmiller19:11:42

is that what you meant to ask? b/c it does not sound sensible

hlolli19:11:42

no, it doesn't make sense ๐Ÿ™‚ when this is a symbolic lookup, not pointers in C

alexmiller19:11:10

what are you actually trying to do that doesn't work?

alexmiller19:11:52

(nothing has changed in this area of clojure afaik)

hlolli19:11:54

maybe not, but there was a change while back from 1.4 to 1.5 that functions dont carry metadata anymore, so I tought it wasn't unlikely that further optimization on symbols has been carried out, not sure.

alexmiller19:11:36

that's a mighty long while back

hlolli19:11:39

but, I'll try to find another way to solve this, use a different way of specifying type for instruments that don't rely on custom metadata.

hlolli19:11:53

Excuse my rapid assumption

alexmiller19:11:06

I think, again, it would be best to actually understand what is wrong first, before randomly changing things

alexmiller19:11:33

can you reproduce the behavior outside cider just using a bare repl?

alexmiller19:11:15

it seems far more likely given the frequency of change and this description that something has changed in cider, rather than in clojure or overtone here

hlolli19:11:44

yes that's very true with that logic

hlolli19:11:00

strange thing to break in cider but not impossible

alexmiller19:11:12

it looks like (m/harpsichord) is invoking an overtone function that plays the sound, then returns a large map, which cider prints

alexmiller19:11:38

that's what a repl is supposed to do

alexmiller19:11:47

is that what the overtone function is supposed to return?

hlolli19:11:19

it should return the record type of buffer

hlolli19:11:39

or just type

hlolli19:11:59

I mean, that's what records are, they don't print enirely their contents?

alexmiller19:11:05

maybe cider is installing some print-method extensions that do something based on the type that happens to be returned here

alexmiller19:11:43

generally, records print as typed maps:

alexmiller19:11:45

user=> (defrecord R [a b])
user.R
user=> (->R 1 2)
#user.R{:a 1, :b 2}

hlolli19:11:16

ok, I can test older cider, good point. My first gut was that the print method was broken. But I'll rule out other possibilites. Thanks for looking at this ๐Ÿ™‚

alexmiller19:11:22

well, I agree that's a good place to look. First, I'd try to repro outside of nrepl/cider/etc - that will tell you whether it's cider or not. Then I'd capture the result of harpsichord to look at it's type, metadata and understand how it is likely to be printed. You might be missing a prefers-method or something.

alexmiller19:11:47

I assume for your issue debug that harpsichord returns an Inst, and that's being given meta of ::instrument, and a print-method is being installed for ::instrument.

alexmiller19:11:54

in the case that fails, that's not working

alexmiller19:11:26

first, I'd try to verify that (harpsichord) returns an instance, that has the right meta

hlolli19:11:36

exactly, I believe I tried that, I added print-method for moth cases Inst and ::instrument.

hlolli19:11:12

The meta of the return value from (harpsichord) has overtone to-string helper, it's totally strange, I think it's from one of those nested macros.

hlolli19:11:49

#:overtone.helpers.lib{:to-string #function[dev.bug/fn--20178/fn--20205]}

hlolli19:11:22

I'm testing old cider now with nixos, making a sandbox of older cider version. Doing it the hard way ๐Ÿ˜›

alexmiller19:11:03

make sure you check both class and type

alexmiller19:11:52

class will tell you the actual Java class. type is the same, but can be overridden with the :type metadata

alexmiller19:11:11

print-method uses the latter

alexmiller19:11:23

gotta run...

hlolli19:11:25

exactly, I looked at how print-method was implemented, and how it fallsback to class.

hlolli19:11:27

ok thanks again

macrobartfast19:11:14

is anyone using Polylith? is it still alive and well? I noticed the repo seems to not have had any commits for a while.

macrobartfast19:11:48

I don't want to invest in figuring it out and using it if the creators have found a better approach or lost interest.

macrobartfast19:11:43

and that's because it takes me a lot more time to figure things out and implement them so I have to choose more carefully than more talented people who can work quickly through things, glean some ideas, and move on.

macrobartfast19:11:43

open to suggestions for how to build and use something on my machine that might be broken out into smaller services in deployment (which is what I understand Polylith to be about).

macrobartfast19:11:22

I don't have 32GB of RAM, which is a factor for me... I can't spin up lots and lots of little clojure apps locally.

macrobartfast19:11:35

or maybe I'm taking the wrong approach.

sogaiu19:11:25

there was a post in september from a creator of polylith on clojureverse -- it sounded like they were still using it. fwiw, i think the following is the thread: https://clojureverse.org/t/the-origin-of-complexity/4839

macrobartfast19:11:10

cool! it might still be alive.

macrobartfast19:11:27

could be the case that there are fewer commits because it reached a usable point.

Andreas S.19:11:13

good evening!

Andreas S.19:11:26

how do I print the source of a function/def in the repl?

Andreas S.19:11:44

how do I import the repl namespace?

alexmiller19:11:28

(require '[clojure.repl :refer :all])

alexmiller19:11:42

or (use 'clojure.repl)

Andreas S.19:11:53

ah i forgot the quote!

Andreas S.20:11:51

hm it doesn't work?

Andreas S.20:11:08

I have a very simple (def d 123)

Andreas S.20:11:31

but (source d) doesnt work? : source not found ?

alexmiller20:11:31

source only works for code read from files

Andreas S.20:11:47

and if I want to recall previous repl definitions?

Andreas S.20:11:05

now that you say it the name makes sense ๐Ÿ˜„

alexmiller20:11:11

by default, the basic repl doesn't do that

alexmiller20:11:46

many repls let you up-arrow and there are some libs that do more

Andreas S.20:11:06

ok! thank you

vdmit1122:11:09

Hi folks! What if I tell you that I'm trying to do an evil thing: monkey-patching Clojure to add support for triple-quoted string literals. I've just sketched a proof-of-concept implementation here: https://github.com/vdmit11/clojure-triple-quote-strings It sort of works, I'm already able to do (defn """ ... """) with Python-style multi-line docstrings. But, there is one thing I can't tame: it seems as if REPL somehow tokenizes the input. That is, this split to 3 strings:

clojure-triple-quote-strings.core=> """foo"""
""
"foo"
""
But this thing works:
clojure-triple-quote-strings.core=> ["""foo"""]
["foo"]
And read-string works of course:
clojure-triple-quote-strings.core=> (read-string "\"\"\"foo\"\"\"")
"foo"
Seems the issue is somehow related to the REPL, as if it splits input into tokens before passing the input to the reader, but I can't find the code where that happens. So, is anybody able to give me a hint? And, generalizing: how do I debug reader process? Any recommendations on tools? Is there an IDE where I can step over Java and Clojure (combined) with the debugger?

hiredman22:11:30

it is likely you are using lein, which uses nrepl for the repl, and nrepl is a client/server architecture, and the client lein uses is reply, and to support whatever features reply isn't just a dumb client passing data back and forth

vdmit1122:11:04

It turned out to be a little challange for me to include a compiled .jar file as a part of deps edn with bare clojure (still figuring that out). But I think you're probably right, it is something about repl client. I've seen the nrepl message, but for some reason completely ignored the fact that it is running over a network. Thanks for the hint, I'll try to dig into that direction.

sogaiu22:11:02

@vdmit11 in case you haven't seen it, perhaps you'll find the following to be of interest: https://archive.clojure.org/design-wiki/display/design/Alternate%2Bstring%2Bquote%2Bsyntaxes.html

vdmit1122:11:26

T.Hanks! And by the way I also have plans for string interpolation ๐Ÿ˜‰

sogaiu22:11:36

sounds like fun ๐Ÿ™‚

vdmit1123:11:16

Actually string interpolation is easy. Can be implemented in 2 lines of code:

(require 'cuerdas.core)
(set! *data-readers* (assoc *data-readers* 'f (fn [s] `(cuerdas.core/istr ~s))))

vdmit1123:11:14

and then you can do:

(let [name "John Doe"
      age 42]
  #f"Hello ~{name}, you were born in ~(- 2019 age)")
which yeids:
"Hello John Doe, you were born in 1977"
Almost python's f-strings.

vdmit1123:11:57

It is actually a matter of choosing a good interpolation library (or writing one) and popularizing it across the community.