clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
Ethan Plante 2021-05-28T02:59:34.064900Z

Leiningen question: how does the main function work, once you run the app? Does it start at main and go through and evaluate all the code in that file, or does it only run the code you call from within the main function?

seancorfield 2021-05-28T04:26:20.065200Z

I answered that on Zulip -- hope that helped? (and this sounds like a good question for the #beginners channel here on Slack).

Endre Bakken Stovner 2021-05-28T05:52:51.065500Z

But I thought one of them might be relative-to or something 🙂

Endre Bakken Stovner 2021-05-28T05:54:06.065700Z

I had only worked with lein and that would be a bit more involved. Plus it would add another rather large dependency.

1
Karol Wójcik 2021-05-28T09:22:15.067100Z

I think I saw last time Clojure XML parser/generator which claims that it's faster than data.xml. Does anybody remember the name of it?

flowthing 2021-05-28T09:22:58.067200Z

Probably this: https://github.com/nilern/eximia

Karol Wójcik 2021-05-28T09:25:54.067500Z

Exactly. Thanks!

marrs 2021-05-28T10:24:28.070200Z

Can someone tell me what's going on with this problem I'm having?

(for [x [1 2 3]]
  (println "X" x))

; yields
; X 1
; X 2
; X 3
; (nil nil nil)

(do (println "DO")
    (for [x [1 2 3]]
      (println "X" x))
    (println "DONE"))

; yields
; DO
; DONE
; nil
Any ideas why?

2021-05-28T10:25:23.070400Z

for is lazy. You need something to realize it for side effects

thheller 2021-05-28T10:25:52.070700Z

use doseq instead of for if you want it just for side-effects

☝️ 1
marrs 2021-05-28T10:26:15.071Z

ah, side-effects!

marrs 2021-05-28T10:26:16.071200Z

thx

borkdude 2021-05-28T11:05:52.072Z

@alexmiller @hiredman Re: Clojure AOT problems with GraalVM native-image, A similar problem was reported with depstar and :aot true which has similar behavior to lein's :aot :all. https://github.com/oracle/graal/issues/1613#issuecomment-850325231

2021-05-28T12:51:40.076300Z

If we assume a structural editor for Clojure is desirable, what potential barriers would the design need to account for? What awesome things could the design account for?

👍 2
quoll 2021-05-30T17:23:14.171500Z

This has been an interesting thread, in that I wrote a project 5 years ago that parsed Clojure code and inserted it into Datomic for querying

quoll 2021-05-30T17:23:37.171700Z

It was more POC than anything, but it worked 🙂

quoll 2021-05-30T17:24:33.171900Z

https://github.com/quoll/cast

2021-05-31T16:48:19.212Z

Woah cool! @quoll did you do anything with it? Is there anything you explored doing with it?

quoll 2021-05-31T17:36:48.218800Z

Not for a long while, sorry! You’ll see my last checkin was 5 years ago.

quoll 2021-05-31T17:38:40.221Z

It’s a straightforward representation of the code. I imported the LispReader and then tweaked it for what I wanted. Specifically, I removed the macro evaluation step, and I kept comments.

quoll 2021-05-31T17:39:11.221700Z

The lists are then all stored as linked lists in the db

quoll 2021-05-31T19:29:34.224Z

From memory, different data types (vectors, sets, maps) are all stored as lists with an attribute to say what type they are

Ed 2021-06-01T09:27:13.238900Z

there's this too : https://github.com/Datomic/codeq ... which I've never played with enough to have anything substantial to say about it .... but it's interesting

2021-06-02T17:38:08.288300Z

@quoll Do you have any example databases that would be good to explore, perhaps through @djblue’s #portal?

quoll 2021-06-02T17:43:54.288500Z

Explore for what? For code? (quick answer: no)

2021-06-02T17:53:24.288800Z

I guess I just wanted to have a concrete syntax tree of code to play around with, but if your GitHub link still works, could I try it?

2021-05-28T12:58:04.076400Z

Do you mean like paredit / parinfer? But more specific to Clojure?

2021-05-28T13:00:44.078Z

Paredit or Parinfer are sources of inspiration! I’m referring to a sort of graphical/textual editor for manipulating and navigating code that prevents syntactic errors.

2021-05-28T13:01:33.079400Z

Something that would make it more approachable. The things I’m thinking about may apply to Lisp generally, but I’d prefer to start my explorations with Clojure

p-himik 2021-05-28T13:30:58.079700Z

Suppose you need to add a map literal somewhere in the code, like {:a 1}. When you're typing it in a text editor - no matter how advanced the editor is, it's still text, so you will end up having an intermediate step of {:a|} where | is your text cursor (the } was inserted by the editor itself - it's a very common functionality). Something like clj-kondo will likely highlight that map literal as being incorrect. But how an editor can prevent such an error instead of just highlighting it?

2021-05-28T13:39:51.080600Z

Ah so are you basically saying that it would need to account for intermediate steps on the way to correct code?

blak3mill3r 2021-05-28T13:43:52.080800Z

I've often thought it might be fun to have a way of editing lisp with a VR helmet and something akin to an xbox kinect field sensor

blak3mill3r 2021-05-28T13:44:24.081Z

Waving my arms about to do what lispy/paredit call slurping and barfing, etc

p-himik 2021-05-28T13:48:32.081200Z

@rob370 I simply don't see any other way around it right now. So the editor will only let you save the file when there are no syntax errors (at least, that's how I understand your initial idea). So between | and {:a 1|} there will be no saves, no ability to evaluate code. But... is it really helpful to justify a new editor by itself? What if you need to enter a big nested data structure, like {:a {:b {:c ...}}} , but you also want to push your work into your Git branch somewhere in the process of entering it to save the progress?

p-himik 2021-05-28T13:53:10.081800Z

Don't get me wrong - I'm all up for new tools. I'm just really unsure if an editor with more restrictions will be helpful. IMO it would be much more useful to have handy tools that help you make sense of the current state of your code, your development environment, and the relevant running processes. For example, a functionality to compare the code that has been evaluated most recently with the current code. And maybe it exists somewhere, but I haven't seen it.

2021-05-28T13:53:50.082900Z

Hmm only saving when there are no syntax errors is an option. Alternatively, one where it makes it visually clear what the gaps are and what can go in them.

2021-05-28T13:54:18.083100Z

> For example, a functionality to compare the code that has been evaluated most recently with the current code. Yes! This would be great.

p-himik 2021-05-28T13:54:22.083300Z

> one where it makes it visually clear what the gaps are and what can go in them But isn't that exactly what linters like clj-kondo do?

p-himik 2021-05-28T13:54:44.083500Z

@qmstuart Feel free to steal the idea. ;)

2021-05-28T13:57:17.084100Z

> For example, a functionality to compare the code that has been evaluated most recently with the current code. Yes! Would show me if function definitions and values are out of date

2021-05-28T13:58:56.086300Z

Clj-kondo means there’s something to build on! I just have a general open question about how to visually communicate this stuff as well as possible and I think standard text editors are gonna be limited there

p-himik 2021-05-28T13:59:48.086500Z

Also worth noting that syntax errors specifically are IMO vastly outbalanced in terms of human-hours by any other kind of errors. A bad map literal - you already get the exact line and column number with a clear description of what's wrong. Seconds. A function call with a wrong arity - tougher because often can only be handled in run-time, but still pretty easy. Seconds to minutes, if you trigger the error. Some other run-time error - the time can vary from a minute to a month or more, easily. Some strange AOT error - from hours to months as well.

p-himik 2021-05-28T14:01:53.087200Z

> how to visually communicate this stuff as well as possible OK, this is intriguing. Right now we have text decorations (red underlining and similar), editor decoration (scroll bar decoration, line highlighting), separate panels (list of errors in the whole project, list of errors in the current file). How could this be improved, assuming we can get past the plain text somehow?

2021-05-28T14:04:08.090Z

The error messages are really hard to parse for beginners so we get stuck on them for much longer than you might. I’m not sure if a structural editor would be useful for a l33t coder but I have little doubt that something that could prevent things that literally make no sense given the structure of the code or prompt you to input the right amount of arguments would be helpful to beginners

2021-05-28T14:05:35.090900Z

Re ways to make structure and rules more visually apparent, a (possibly) silly idea; https://clojurians.slack.com/archives/C03RZGPG3/p1622147058166500

Ed 2021-05-28T14:12:19.091300Z

> For example, a functionality to compare the code that has been evaluated most recently with the current code. > Yes! Would show me if function definitions and values are out of date (edited) Doesn't cider do this currently? If a defn is evaluated it has a green highlight for me in the gutter on the left and that goes away if I change the code, until I load the buffer.

Ed 2021-05-28T14:15:54.091500Z

I've often thought that it would good to have a query language for my codebase (kinda like https://github.com/borkdude/grasp maybe??) integrated into an editor - so maybe you could query for all the functions called by a particular stack trace, see them all on one view and edit them together, even though they may be distributed across multiple namespaces possibly even in multiple git repos ...

Ed 2021-05-28T14:21:25.091800Z

but I'm not sure that's the sort of thing you're after, is it... I think if you'll be fighting an uphill battle trying to replace the immediate interface that someone uses to work with code ... the text based thing has worked very well for a long time, and visualisation graphical editing environments have repeatedly appeared and vanished without a trace ... although https://www.unisonweb.org/ looks like an interesting approach that may lend itself to changing that in the very long term??

Endre Bakken Stovner 2021-05-28T14:52:49.092300Z

I agree with @l0st3d about text based editing. A different approach would be to let users see your visualization of the code live in a browser while they are using their favorite text editor. This would not show all intermediate steps though, just when the user saved their file (you could have a program that sent the changes to the browser upon filechange).

rende11 2021-05-28T14:54:26.092900Z

Hello! How to manage such a thing, monitoring, health checks?

(def thread
    (Thread. (fn []
               (loop []
                 (println "Do some work!")
                 (recur)))))

  (.start thread)
In a real project, it is a consumer for the queue. Any good approaches, libraries for this? I already have a couple of those threads started from the main thread.

emccue 2021-05-28T15:14:16.093400Z

@rende11 That is actually a fantastic question that I do not know the correct approach to

emccue 2021-05-28T15:15:15.094Z

Some potential ideas -

emccue 2021-05-28T15:17:41.094800Z

use an executor service and a thread factory to make threads that have names that are relevant

emccue 2021-05-28T15:18:02.095700Z

(Executors/newSingleThreadExecutor
  (-> (BasicThreadFactory$Builder.)
      (.namingPattern "chat-subsystem-%s")
      (.build)))

alexmiller 2021-05-28T15:18:26.096100Z

or just use future if you want simpler code

alexmiller 2021-05-28T15:18:46.096600Z

you will almost always want some way to tell that thread to stop

alexmiller 2021-05-28T15:19:31.097600Z

closing over an atom that holds a boolean is one such way. if using an executor, it has shutdown methods

emccue 2021-05-28T15:21:32.100300Z

with a named thread you can get decent monitoring with JFR

emccue 2021-05-28T15:21:45.100600Z

or whatever other JVM monitoring tool

David Orme 2021-05-28T15:21:53.100800Z

(.setName thread "queue consumer")

alexmiller 2021-05-28T15:21:57.101Z

you can change the name from inside the thread

alexmiller 2021-05-28T15:22:01.101200Z

^^

alexmiller 2021-05-28T15:22:41.102500Z

it's a little dirty but in a case like this where you're spinning a single thread, probably a good hack

emccue 2021-05-28T15:22:44.102700Z

health checks you can inspect the executor, or have the tasks work on an atom when they crash

David Orme 2021-05-28T15:23:29.102800Z

Then jconsole or jprofiler, or jstack.

David Orme 2021-05-28T15:24:21.103400Z

Also, log from the thread and spelunk.

emccue 2021-05-28T15:24:35.104Z

https://gist.github.com/bowbahdoe/ce961e6c7449c1ffe9877082465b1f47 this is the closest i've done - from a personal thing a year-ish ago

emccue 2021-05-28T15:24:38.104300Z

ghadi 2021-05-28T15:24:41.104500Z

naming a thread isn't going to help with monitoring -- you want something connected to the semantics of your domain

David Orme 2021-05-28T15:24:49.104600Z

(Spelling on splunk?)

ghadi 2021-05-28T15:25:28.105700Z

if your background threads are poll workers, exposing metrics on # of messages consumed -> prometheus or some metric system

emccue 2021-05-28T15:25:29.105800Z

maintaining a reference to whatever stateful thing is potentially useful too

emccue 2021-05-28T15:25:49.106200Z

^that is a better approach

David Orme 2021-05-28T15:25:55.106400Z

Also, what Ghadi said and throw domain specifics in a map in an atom that you expose to whatever you use to monitor or debug prod issues.

emccue 2021-05-28T15:26:17.107Z

then set an alert on cloudwatch or wtvr for if the rate drops

David Orme 2021-05-28T15:26:30.107100Z

:upvote:

emccue 2021-05-28T15:27:32.107900Z

one thing i've done in a past job is pass through a "listener" I called whenever I did a key action in the consumer

emccue 2021-05-28T15:27:45.108300Z

(twas in java, but same diff)

emccue 2021-05-28T15:27:54.108500Z

so like

emccue 2021-05-28T15:33:20.112100Z

(defn consumer-loop [listener]
  (let [msg           (poll-for-msg)
        _             (listener/started-processing-msg {:msg-id (:id msg)}]
    (try 
      (do 
        (insert-into-db (f msg))
        (listener/successfully-inserted-msg {:msg-id (:id msg)}))
      (catch ExpectedException e
        (listener/failed-to-inser {:msg-id (:id msg)}))))

emccue 2021-05-28T15:33:36.112500Z

so thats one approach to get your domain level info

lspector 2021-05-28T15:44:59.115600Z

Anyone know of, or feel like making, a site that will auto-reformat (re-indent) a field full of Clojure code? My use case is teaching beginners using no-installation tools that are just missing this crucial feature (currently Replit). If they could copy/paste/reformat/copy/paste via a site that just does reformatting, we'd have a workable solution, even if it's a little cumbersome.

David Orme 2021-05-28T15:58:25.115800Z

Does the code need to be executed/executable from within the site?

David Orme 2021-05-28T15:59:31.115900Z

Must the code be Clojure or is Clojurescript fine also?

lspector 2021-05-28T16:36:10.118500Z

I'm just thinking about reformating, not execution here. Execution could be fabulous too, but the goal here is just to have a formatting tool that could be used in conjunction with another solution for execution, like http://Replit.com. Clojurescript would be fine also, since the formatting is the same. I'm hoping for something like the standard reformatting capability in many IDEs like Cursive or Calva, etc.

Franklin 2021-05-28T17:34:23.118800Z

are there any data structures and algorithm books that use clojure?

2021-05-28T17:49:02.118900Z

Not exactly what you ask, but there is this: http://www.sicpdistilled.com/

2021-05-28T18:27:25.119200Z

Oh that’s brilliant thank you @didibus

James Carr 2021-05-28T18:35:40.119700Z

👋 anyone using open telemetry with clojure?

javahippie 2021-05-29T13:28:49.142400Z

After seeing this thread here yesterday, I had the time to write sth. about a wip on that topic: https://clojurians.slack.com/archives/C8NUSGWG6/p1622294885029000

Franklin 2021-05-28T18:36:06.119800Z

thank you @didibus

R.A. Porter 2021-05-28T18:47:17.120100Z

I did a little proof of concept work with it at my last job. I used this library: https://github.com/tendant/clj-telemetry

R.A. Porter 2021-05-28T18:50:06.120400Z

Ended up writing this macro (along with tracer which was an atom and this dynamic var

(def ^:dynamic *trace-parent* nil)

James Carr 2021-05-28T18:50:09.120600Z

Ah and the java agent to capture traces by default?

R.A. Porter 2021-05-28T18:50:52.120800Z

Nothing by default; anything I wanted traced, I'd wrap in the with-trace macro.

R.A. Porter 2021-05-28T18:51:11.121Z

Not sure it was the best approach, but it worked well enough for the PoC.

ghadi 2021-05-28T18:53:59.121200Z

@james.r.carr IIRC the java agent only knows how to open traces for certain libraries

ghadi 2021-05-28T18:54:28.121600Z

if your web server isn't on the handled list, that may not work for you

James Carr 2021-05-28T18:54:31.121800Z

yeah it seems to capture most however.

ghadi 2021-05-28T18:55:38.122Z

at cognitect we built a trace library for a client. Wasn't OTel compliant, we emitted things to Honeycomb

James Carr 2021-05-28T19:00:11.122200Z

yeah maybe we should just give the native DD agent a try

James Carr 2021-05-28T19:00:24.122400Z

but I think we are likely going to need to wrap things regardless.

James Carr 2021-05-28T19:00:47.122600Z

for example, by default we see jetty calls, but pedestal and the like are missing

ghadi 2021-05-28T19:01:28.122900Z

you'll need some sort of integration somewhere

ghadi 2021-05-28T19:01:56.123100Z

we had a convenient pedestal interceptor that took a set of key paths (into the context) and automatically traced those into the active span

kenny 2021-05-28T19:19:49.125300Z

We use the Java libs for opentracing and micrometer. Both are great. I think opentracing is moving to open telemetry? I don’t think we can switch because all the tooling hasn’t caught up yet (or something like that anyway).

ghadi 2021-05-28T19:34:36.125500Z

yeah it's like the xkcd standards comic

ghadi 2021-05-28T19:34:47.125700Z

endless churn in this space

ghadi 2021-05-28T19:35:43.125900Z

none of the libraries we were using participated in open*anything, so making a tight 300LOC tracing library seemed like a low risk thing

ghadi 2021-05-28T19:35:55.126100Z

spans are maps, that's pretty much it

dabrazhe 2021-05-28T22:30:03.130600Z

I'd like to print in repl /save to file some of the keys from the list of maps I've made, see posted put in this slack thread. The idea is to align the keys under each other so that I can easily compare the values, like in a table. How can I achieve this? Eg with some sort of tabulation.

{:BUY {:lastPrice 0.5 :volume 1 }   :SELL {:lastPrice 1.95 :volume 46}  :p2margin 17.35      :ticker "TSLA" }
{:BUY {:lastPrice 0.9 :volume 100 } :SELL {:lastPrice 1.95 :volume 460} :p2margin 18.2342420 :ticker "TSLA" }   
etc ... 

dabrazhe 2021-05-28T22:30:21.130900Z

({:BUY {:change 0.08000001
       :lastPrice 0.5
       :volume 1
       :etc :bunchotherkeys}
 :SELL {:lastPrice 1.95
        :safetyMargin 18.360813190331367
        :volume 46
        :etc :otherkeys}
 :p2margin 17.35
 :s-premium 1.27
 :ticker "TSLA"}
{:BUY {:change 0.08000001
       :lastPrice 0.9
       :volume 100
       :etc :bunchotherkeys}
 :SELL {:lastPrice 2.0
        :safetyMargin 18.360813190331367
        :volume 460
        :etc :otherkeys}
 :p2margin 18.2342420
 :s-premium 1.27
 :ticker "TSLA"})

dabrazhe 2021-05-28T22:34:41.131500Z

indy 2021-05-28T22:37:07.132600Z

Would this help? https://clojuredocs.org/clojure.pprint/print-table

dabrazhe 2021-05-28T22:40:55.133Z

cool. but only partially, because I'd need to reconstruct the maps. I'm looking for a way to extract only some keys from 2 level deep and then print a table