beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
2021-03-12T05:54:04.333Z

Is there a way to “de-string” a string? I have a string that looks like a hash-map "{:foo \"foo\" :bar \"bar\"}", and I need it to just be the hash map. str makes a string, but is there an opposite function that just gets rid of the string?

dpsutton 2021-03-12T05:57:12.333400Z

you can check out clojure.edn/read-string

💯 2
👀 1
✅ 1
2021-03-12T14:02:15.342Z

As a Clojure beginner I feel like the language makes a lot of sense and is easy to grok and get going with. But sort of opposing that is the complexity that is the ecosystem. As someone with zero experience of the JVM that of course is some degree of complexity but even larger to me is understanding how things are done, what libs are actually used, how you are supposed to deploy and run your Clojure code etc. How do people approach this? I get that all languages with some history have a degree of “you just have to learn this as you go” but to me it feels like Clojure has more so than many other languages I’ve seen. I really love the language but I feel like this complexity of ecosystem makes it hard for me to see a path forward.

2021-03-12T14:13:02.343200Z

@anders152 What type of projects do you want to approch? Web development? Other?

2021-03-12T14:13:37.343700Z

Back-end / front-end?

2021-03-12T14:37:05.348400Z

@anders152 yes, agree, I learned the clojure from http://braveclojure.com but up until now, I still don't have idea how to compile & deploy the code? I'm using the code for fun right now, but I've also done it to clean some data in csv to be feed into power bi. then I'm asking to myself, if i want to run it automatically, how to do that? it's still my homework to figure out... a bit slow progress than anyone else, but I'm enjoying the process

2021-03-12T14:43:18.349400Z

@admin055 everything to be honest. But I’m fine with putting off frontend for a bit.

2021-03-12T14:44:51.351700Z

Yeah that mirrors my journey somewhat. I’ve read a number of books and I’m trying to focus on the “real world” stuff I can find. But the truth is I have a hard time even knowing if I’m learning the way or just a way of doing stuff. Which goes for exploring libraries as well.

2021-03-12T14:45:40.353100Z

I think it’s just an effect of Clojure being 1) highly community-driven and 2) situated in the JVM ecosystem which I have no experience in.

raspasov 2021-03-12T15:13:23.353700Z

@anders152 Not to discount the issue, but isn’t that an issue with any new language/environment? For example, I was learning about Machine Learning a few months back quite actively, and just learning anything around python like setting up the environment, etc felt very foreign and complex. And in some ways it is way more complex than the JVM, because Python suffers the worst case of “works on my machine” - almost everything is related to how your environment is setup and can just break in a version upgrade of MacOS for example (which it did for me). So there’s tools/setups to mitigate that problem but you need to learn those… I spent a day or two learning those tools and my experience improved. If you have any specific question, feel free to ask. You mentioned deployment. One straightforward approach for deployment which I’ve used is: 1. make an uberjar 2. put it in a docker container 3. deploy Now each step has complexity within, but I would say that’s equivalent to any other language/ecosystem.

raspasov 2021-03-12T15:16:30.354Z

Perhaps you’re right that Clojure has less step-by-step tutorials how to do common things. Or that you need to assemble the knowledge/steps from different library README’s . For example here’s a guide I’ve used to make an uberjar out of a deps.end project: https://github.com/tonsky/uberdeps

raspasov 2021-03-12T15:18:37.354400Z

Do you have any previous experience in a language/ecosystem? I came to Clojure with zero Java/JVM experience (was writing OOP PHP before Clojure) so I can relate 🙂.

2021-03-12T15:31:48.354600Z

@anders152 what I've always relied on is • learning how to turn a clojure project into a vanilla fat jar (`lein uberjar` or depstar are the right choice for 99% of projects IMHO) • following instructions for java project deployment

👍 1
👆 1
2021-03-12T15:31:55.354800Z

java is very well documented

2021-03-12T15:32:39.355Z

(there are some gotchas - eg. gen-class with your own main is a default, but using clojure.main is often better, but this is a good 80% approach to get what you need)

Dimitar Uzunov 2021-03-12T16:02:37.362100Z

@adrianimanuel the first chapter of braveclojure shows how to build a JAR and run it, but you mention running it automatically. If you mean to run it as a restartable service your might want to run it using systemd for Linux, here is a simple guide: https://computingforgeeks.com/how-to-run-java-jar-application-with-systemd-on-linux/ If you prefer Windows you can try https://nssm.cc to setup a windows service. Then of course you can put the JAR in a Docker image and run the container in Kubernetes or Nomad if you need plenty of features. https://hub.docker.com/_/clojure - a good starting point might be this

🎯 1
Dimitar Uzunov 2021-03-12T16:04:42.362900Z

and there is also this: https://www.braveclojure.com/quests/deploy/ (jar on a linux VPS configured using Ansible)

2021-03-12T16:09:06.363Z

@raspasov I have about ten years experience in .net/C# development, and I could see how someone coming to that ecosystem today would be quite overwhelmed with all the history of the language and all its kinks and quirks, but its also quite easy to follow a beaten path with clear "this is the modern way of doing stuff"-type tutorials. But .net has millions of Microsoft dollars behind it and I can see the differences in the whole community and culture of course.

2021-03-12T16:09:59.363200Z

But if Clojure was running on the CLR as a first-class citizen I would also feel zero stress about "getting the ecosystem" since I have all the experience of that already. And that is what I think many coming from the JVM to Clojure have.

2021-03-12T16:10:17.363400Z

(And yes, I know about the clojure CLR implementation but that hardly seems a viable real-world choice)

raspasov 2021-03-12T16:11:47.363700Z

@anders152 re:CLR, yes… (I have no experience with it)

2021-03-12T16:12:33.363900Z

@anders152 the only thing that makes clr clojure not seem like a real world choice is that it relies on clr tooling instead of having a build tool like lein or deps.edn

2021-03-12T16:12:54.364100Z

it's mature, and up to date with jvm clojure, you are just expected to use the existing dependency and build tools with it

2021-03-12T16:13:36.364300Z

(there's less community libraries to be sure but IMHO for most libraries interop will be the best choice anyway)

2021-03-12T16:15:08.364500Z

@raspasov Regarding it being an issue for all languages... yes - of course, to an extent. But I am very interested in exploring different languages and have done so for a long time. I find Clojure to be an extremely refreshing and interesting language but I have a hard time recalling when I ever felt as lost in terms of understanding the ecosystem and everything else around the actual language. Maybe elixir, which has a few commonalities.

raspasov 2021-03-12T16:15:32.364700Z

Way less community libraries 🙂 (not discounting the quality of Clojure CLR itself)… it really depends on what you’re doing with it… if you don’t need interop-heavy libs + you have a ton of experience with C# development, perhaps it’s worth trying it out! (sounds like a good fit for someone like @anders152 with a ton of experience in C#)

2021-03-12T16:15:57.364900Z

Interesting!

2021-03-12T16:16:14.365100Z

But to be honest I want to get away from .net 😄

raspasov 2021-03-12T16:16:59.365400Z

But once you need an HTTP library in Clojure… you might be back to object interop with whatever is in C#? (I have no idea about Clojure CLR ecosystem)

2021-03-12T16:17:39.365600Z

Yeah I mean assuming it's running on the CLR it has access to all of .net framework (aka "the standard library" and then some) so that's not a problem.

raspasov 2021-03-12T16:18:47.365800Z

For somebody with experience in C# I bet it’s not 🙂 But coming to Clojure some years ago with zero Java experience, it was definitely nice to use idiomatic Clojure library wrappers around Java libs/frameworks to start with

2021-03-12T16:20:03.366Z

Yep, can definitely see that. And it would honestly feel sad to just use clojure as a glue language between .net dependencies.

raspasov 2021-03-12T16:22:07.366200Z

The main things are HTTP clients and HTTP server libraries/frameworks… The mature/established ones are usually wrappers around existing libraries. And most database drivers, those also.

raspasov 2021-03-12T16:23:24.366400Z

Nice to have idiomatic wrappers around those… Many other things should be re-usable in Clojure CLR (But again… you need to check…) if the library is doing even a bit of Java interop in, I assume it will fail to load in CLR

2021-03-12T16:23:54.366600Z

Yes, 100% guaranteed 😄

raspasov 2021-03-12T16:24:45.366800Z

Even something like this (super nice logging library IMO): https://github.com/ptaoussanis/timbre/blob/master/src/taoensso/timbre.cljc

raspasov 2021-03-12T16:25:03.367200Z

… depends on [io.aviso.exception …]

raspasov 2021-03-12T16:25:13.367400Z

And if you look in that library, it’s doing Java interop

raspasov 2021-03-12T16:25:47.367600Z

So it won’t work… it seems like you’ll be doing a ton of extra work on CLR, or at least lose a ton of great Clojure libraries… Doable, but definitely “you’re on your own” kind of experience

2021-03-12T16:27:54.368200Z

that's chicken/egg though - there's no libraries until people write them, they don't write them until they use it

raspasov 2021-03-12T16:27:55.368400Z

The zuper big win in Clojure for me, for example, is the fact that 90% of the modern Clojure code works exactly the same in Clojure and ClojureScript (and most libraries that are useful in both are designed to “just work” in both)

raspasov 2021-03-12T16:28:36.368600Z

juxt/time , timbre

raspasov 2021-03-12T16:29:15.368800Z

I was SO excited when I got juxt/time working … the fact you can have a date time library work 99% the same across both platforms is just so nice.

raspasov 2021-03-12T16:30:44.369Z

@noisesmith absolutely… it just requires a much bigger initial commitment to be among the first people on the island 🙂

2021-03-12T16:36:37.369700Z

Yeah the ”full stack Clojure” promise is really enticing.

raspasov 2021-03-12T16:38:55.369900Z

Yes… also sharing code across both is now so simple and easy via deps.edn https://github.com/raspasov/alexandria-clj

raspasov 2021-03-12T16:39:14.370300Z

I have this big repo which I just require from both CLJ and CLJS

raspasov 2021-03-12T16:39:26.370500Z

And require the namespace which I need… that’s all.

raspasov 2021-03-12T16:39:45.370700Z

Perpetual, ever-expanding code re-use! 🙂

raspasov 2021-03-12T16:40:21.370900Z

Talking about dates… https://github.com/raspasov/alexandria-clj/blob/main/src/ax/time.cljc

raspasov 2021-03-12T16:40:40.371300Z

Works 100% the same, CLJ + CLJS

2021-03-12T16:59:07.371900Z

@anders152 What languages and ecosystem are you comfortable with. This will perhaps allow us to give some clues on the Clojure equivalents (libraries, etc.).

2021-03-12T17:12:40.373Z

C#, F#, Python and ”modern JavaScript” i feel fairly at home with.

teodorlu 2021-03-12T17:23:00.374600Z

Hello! I'm trying to use the https://docs.sentry.io/platforms/java/ from Clojure, but I'm hitting interop problems. This is the java example from the docs:

import io.sentry.Sentry;

Sentry.init(options -> {
  options.setDsn("<https://examplePublicKey>@o0.ingest.sentry.io/0");
});
Here's what I'm trying in Clojure:
(comment
  (import '[io.sentry Sentry])

  ;; source: <https://docs.sentry.io/platforms/java/>

  (Sentry/init (fn [options]
                 (.setDsn options "<https://examplePublicKey>@o0.ingest.sentry.io/0")))
  ;; =&gt;
  ;; 1. Unhandled java.lang.IllegalArgumentException
  ;;    No matching method init found taking 1 args

  ;; Can we use reify? Is my problem that Clojure functions arent valid java lambdas?
  (Sentry/init (reify java.util.function.Consumer
                 (accept [this options]
                   (doto options
                     (.setDsn "<https://examplePublicKey>@o0.ingest.sentry.io/0")))))
  ;; =&gt;
  ;; 1. Unhandled java.lang.IllegalArgumentException
  ;;    No matching method init found taking 1 args

  ;;
  )
Any advice?

seancorfield 2021-03-12T17:27:24.377200Z

@dharrigan You’ve worked with the Sentry stuff, yes?

2021-03-12T17:27:50.377400Z

When I inspect a ring request map on a server which is using the ring-anti-forgery middleware, I'm seeing this in the REPL:

{:session #:ring.middleware.anti-forgery{:anti-forgery-token "Some-big-long-CSRF-token"}}
What's up with the #:ring.middleware.anti-forgery piece that's in front of the session object? At first I thought it might be metadata or something, but I'm not sure why it's there, or whether I need to care about/can interact with it or not. Or if it might trip me up in subtle ways!

dharrigan 2021-03-12T17:28:26.377800Z

@teodorlu I look after the sentry-clj (for the moment)

👍 1
2021-03-12T17:28:50.378400Z

strange but there is no init static method which is taking a lambda https://getsentry.github.io/sentry-java/

1
dharrigan 2021-03-12T17:28:59.378800Z

The documentation shows how to use it, along with some examples in the examples directory

👍 1
dharrigan 2021-03-12T17:29:45.379Z

<https://cljdoc.org/d/io.sentry/sentry-clj/4.3.143/doc/readme>

👍 1
👀 1
teodorlu 2021-03-12T17:31:30.379400Z

Thanks, I realize I didn't look very hard. Still want to learn what I did wrong above, I'd like to learn a bit more about Java interop.

dharrigan 2021-03-12T17:32:38.379700Z

No problem, have a look at the source code of the library. Maybe that will help, as it's all interop 🙂

💯 1
teodorlu 2021-03-12T17:55:23.380200Z

It's shorthand for namespace qualified keywords used as keys in maps.

👍 1
2021-03-12T18:04:36.380500Z

Thanks! Now I've got something to google.

teodorlu 2021-03-12T18:17:04.380700Z

A bit terse response, I was on my phone. Does this help?

(= {:foo/bar 1}
     #:foo{:bar 1})
  ;; =&gt; true

teodorlu 2021-03-12T18:17:41.380900Z

the #:key{} notation is present to simplify maps with namespaced keys.

teodorlu 2021-03-12T18:19:11.381100Z

{:person/name "Teodor"
   :person/age "Not too old"
   :person/preferred-pet :dog}

  #:person{:name "Teodor"
           :age "Not too old"
           :preferred-pet :dog}
The latter lets you avoid repeating person for each key 🙂

teodorlu 2021-03-12T18:22:14.381700Z

Here's the official docs: https://clojure.org/guides/weird_characters#_and_namespace_map_syntax

2021-03-12T18:30:39.386100Z

If you have a file like this:

param1: 1
param2:
   subparam1: 1
   subparam2: 2
param3: 3
...
and you wnat to convert that into a nested map {"param1" 1 "param2": {"subparam1" 1, "subparam2": 2 }, "param3": 3}. How would you do this in an efficient way in clojure? Im experimenting with partition-all, but cannot really get it right.

NoahTheDuke 2021-03-12T18:34:33.386800Z

i thought keywords couldn't start with numbers, but the clj repl lets me type it in no issue

2021-03-12T18:38:01.388100Z

They are not officially documented as supported, but due to legacy code bases that used them, they are allowed.

NoahTheDuke 2021-03-12T18:38:12.388400Z

should i avoid them?

2021-03-12T18:38:52.389400Z

That might depend on what you want to do with them, but certainly seems like you would hit fewer issues overall by avoiding them.

2021-03-12T18:40:14.390600Z

e.g. use cases like using them as keys in maps that you write to JSON, and expect to read back? Using them as keywords to database APIs that might convert them in varying ways to SQL table field names? etc. If you just use them inside of your own Clojure program and they never become visible outside, then should be no issues.

NoahTheDuke 2021-03-12T18:41:08.391500Z

i'm storing data in mongodb, and using numbered keys, which are converted to keywords when pulled out

2021-03-12T18:41:51.392700Z

I'm giving generic advice/cautions here. Someone who has worked with mongodb (I haven't) could say more about their experience, perhaps.

👍 1
NoahTheDuke 2021-03-12T18:41:52.392800Z

i could turn off "convert keys to keywords", but this is nested in other stuff that i want to have keyworded

NoahTheDuke 2021-03-12T18:42:01.393100Z

cool, thanks

2021-03-12T18:42:11.393200Z

@teodorlu the fn macro creates an object of type clojure.lang.IFn, which methods like call, invoke, and applyTo for usage as a first class function

2021-03-12T18:43:06.393400Z

so yes, clojure functions are not java lambdas (they do not implement interfaces like Consumer - this is easy to check in a repl by the way

user=&gt; (supers (class (fn [])))
#{java.lang.Runnable java.util.Comparator clojure.lang.IFn clojure.lang.Fn java.util.concurrent.Callable java.io.Serializable clojure.lang.IMeta clojure.lang.AFunction clojure.lang.AFn clojure.lang.IObj java.lang.Object}

2021-03-12T18:43:20.393800Z

and yeah, you could do this by reifying Consumer (or using the wrapper)

teodorlu 2021-03-12T18:43:36.394200Z

👍

2021-03-12T18:43:47.394400Z

you can not use a clojure fn as a lambda, but you can of course use one in the implementation of a lambda

👍 1
2021-03-12T18:45:21.394700Z

and if my memory serves, "lambda" is a syntax, it compiles into an anonymous class implementing the implied method signature

👍 1
2021-03-12T18:46:15.394900Z

and clojure has macros for adding syntax, but out of the box it has no such syntax, and the way clojure works with types, it would not look as streamlined as the java version...

👍 1
teodorlu 2021-03-12T18:51:02.395300Z

I suspect I'd have to dig a bit deeper into how the Java code works to find out what kinds of types it was expecting. sentry-clj used SentryOptions.

2021-03-12T18:52:31.395500Z

yeah, I did a search for the javadoc but all I found was api docs for a REST endpoint - if that means Sentry is a REST service and the java classes are a wrapping of that into java world, I'd skip that nonsense and use something like clj-http

2021-03-12T18:53:51.395700Z

(eg. similar to ,the way cognitect made a AWS API lib that uses REST / JSON directly, instead of making a clojure flavored wrapper over a java flavored wrapper of a data oriented API)

👍 1
2021-03-12T19:04:12.395900Z

OK for begin, let's take NodeJS for eg. To which libraries do you want to have the equivalents? Express ?

2021-03-12T19:55:29.396100Z

Ahh, ok, really appreciate the followup. Not terse at all 🙂

👍 1
Henri Schmidt 2021-03-12T21:43:52.396500Z

It would be straightforward to write a recursive descent parser for this grammar.

Henri Schmidt 2021-03-12T21:45:27.396700Z

I would also simplify the problem and write a parser for only a single param, as they are layed out linearly it is no problem to adapt.

2021-03-12T23:48:33.397600Z

Just finished the simple parser, if anyone is interested

😁 1