Fork me on GitHub
#beginners
<
2022-04-02
>
jeffmk01:04:22

Anyone know of good no-frills guides for getting a minimalist ClojureScript project up and running from scratch, that integrates well with IntelliJ/Cursive? I've been out of the CLJS game for a while and frankly what's out there from my searches is pretty confusing to me. I'd prefer to take a deps.edn and/or shadow-cljs route if feasible. Ultimate goal is to get a Reagent site going, if that changes anything

practicalli-johnny09:04:16

Nope, sorry, no idea about cursive. I do use https://github.com/bhauman/figwheel-main-template to generate a deps.edn project with ClojureScript and reagent. It's all I've needed so far. Haven't found the time to study the detailed shadow-cljs guide yet

solf10:04:21

Maybe better luck in #cursive

jeffmk14:04:50

Thanks y'all

Alex09:04:38

hey guys, i'm looking for a better way to program clojure, interested in using it in a part of my company's streaming pipeline in my downtime, but i'm an acme user that writes primarily go (ocaml, rust and chicken scheme too) and the experience has been excruciatingly painful so far, was just giving cursive a shot with ideaj but it's super overwhelming, would anyone recommend sticking it out or should i try something else? can't really use vim due to lackluster colemak support, don't use emacs, etc...

craftybones09:04:21

If you can help us understand what you find painful, we should be able to help you better. What is bothering you the most?

👍 1
Alex09:04:14

So with my go/chicken/ocaml, I have keybinds set up to very quickly get information about libraries, etc, and I've memorised the standard libraries for the two, with clojure I know F all, and am wondering if there's a better way to build programs using it instead of “writing, running the build process” without any type info, documentation, etc

Alex09:04:36

Whether there's a way to quickly use the repl since I don't have that type safety the other languages afford me

flowthing09:04:56

What's your preferred editor for OCaml etc?

Alex09:04:42

using acme for everything across the board, having code that looks for file changes and recompiles is super ez, since i'll know with the type system most of the time whether something went south, that's not including using LSP though, i haven't found the tooling mature enough to use it for anything and i cbf patching it up

flowthing09:04:21

Oh, the Acme editor, got it. :thumbsup:

👍 1
craftybones09:04:12

So how do you use the REPL currently?

Alex09:04:28

just starting with clojure, so currently i use lein repl

craftybones09:04:31

Ideally, most of us have the repl hooked up to the editor and evaluate code from within the editor without switching over to the repl

Alex09:04:55

there's a program someone has written which lets you port over stdin to a repl running with lein, but i haven't found that very stable so far

craftybones09:04:58

for instance, i am on VSCode, and I’ll type in (+ 2 3) for instance and hit alt-enter

👀 1
craftybones09:04:18

that will evaluate and show me the evaluated result in the editor itself

Alex09:04:57

nice, would appreciate someone sharing a screencast of them doing some development in a more "interactive" environment that's not revolving around build and pray

Alex09:04:15

would you recommend anything like this?

craftybones09:04:32

Build and pray is not what we do. If you are doing that, then clearly something is wrong

☝️ 3
craftybones09:04:45

the screenshot above is from within my editor where you can see I’ve evaluated some arbitrary code

Alex09:04:01

nice, trying to find a workflow that's similar, so you use vscode for each

Alex09:04:19

is there any way to quickly get a TLDR of something similar to this in a command line tool in simple text hooked up to a pager?

craftybones09:04:20

This is of course possible with Cursive

Alex09:04:06

need something similar, this is triggered by command + /

craftybones09:04:28

you only wish to use Acme?

Alex09:04:43

which uses chicken-doc

craftybones09:04:47

I am not sure how much Clojure support is available in Acme.

Alex10:04:06

and nah open to whatever just found it a wild and whacky experience ideaj + cursive, like off the bat opening up a project doesn't create any clojure files and i can't even see how to make one

craftybones10:04:20

Have you used intellij before?

craftybones10:04:43

Then, you’re probably fighting too many things

craftybones10:04:11

Is there any reason for the hurry? My recommendation is to slow down and take your time learning things

Alex10:04:32

this isn't the first time playing around for me and this time thought it made sense to ask

craftybones10:04:43

Playing around is one thing

craftybones10:04:48

but using it in a systematic way to build is another

Alex10:04:01

noone i know is using clojure so haven't had any info on how others do it

craftybones10:04:16

Yes, that would be useful indeed

Alex10:04:19

i'm going to spend more time learning the build tooling and go from there

craftybones10:04:22

Do watch that video shared above

craftybones10:04:00

The build tooling…I am not sure that’s the place I’d begin mucking around with

craftybones10:04:37

There is also Eric Normand’s set of courses

Alex10:04:45

i'd like to find a way to start developing it first so

Alex10:04:22

having something that lets me use external libraries like code to take stuff off our queue would be a good place to start for me, that way i can work on my goal

Alex10:04:25

thanks, gonna play around with that

craftybones10:04:50

That does sound ambitious. Best of luck.

Alex10:04:56

thank you for your help

practicalli-johnny10:04:19

@U039WAHFF4L I use Rebel Readline if I'm doing some quick experiments https://practical.li/clojure/clojure-cli/repl/ Although the vast majority is via an editor. There are many to choose from that support Clojure well https://practical.li/clojure/clojure-editors/

leifericf10:04:50

Here is a succinct demo by @U0ETXRFEW of “the idiomatic Clojure interactive workflow” using Visual Studio Code with Calva. Even if Visual Studio Code is not your default/preferred editor, it is arguably the quickest and easiest way to get up-and-running and familiar with Clojure. Then you can apply what you've learned in your preferred editor afterwards. https://youtu.be/d0K1oaFGvuQ

calva 1
clojure-spin 1
pez10:04:43

I'd also recommend running Calva's Getting Started REPL. It will guide you both in getting a nice REPL workflow and introduce you to the Clojure language as well.

👍 4
Alex12:04:08

cheers peeps, played around with cursive and ultimately got too frustrated with how it tried to be smart with the bracket matching and would refuse to close out (not allowing me to do it for me), while not reliably loading the file into the repl, so coming back before i take the leap and experiment with vsc, would anyone recommend a tool that could get me something similar to the following (this is how my code works here...):

Alex12:04:00

aka simple command line tool that takes an argument of a package, then lists what's in it, without any fluff, i can wire that up pretty easily

craftybones13:04:32

Without meaning to sound overbearing or rude, I feel like you are trying to shoehorn your way of working instead of trying to understand how things are. Perhaps if you give it a fair shot without wanting it to work the way you wish for it to work might bring out the best out of the tools?

craftybones13:04:49

Honestly, VSCode or Cursive work perfectly fine

craftybones13:04:18

The bracket matching is often quite helpful and most of us usually leave it on.

craftybones13:04:45

Why not check out the video where @U0ETXRFEW explains his workflow?

Alex13:04:58

surely there's a program out there that just lists what a package provides without any extra action, i'm willing to experiment with new tooling

Alex13:04:23

cursive i found was buggy, i have lots of tools built into my current environment so i'd like to use it to benefit from thoes

craftybones13:04:26

All you wish for is something that autocompletes? Is that it?

Alex13:04:18

ideally documentation that's easily queryable using a command line tool that produces simple text and a way to send information to a repl

Alex13:04:31

i can get the repl integration stuff sorted, but not the documentation front

craftybones13:04:23

if you are jacked into a REPL then simply typing in (doc name-of-func) should get you some documentation

craftybones13:04:07

Documentation is often written as a part of the function definition itself and is queryable. It is merely data on a function or a var

craftybones13:04:37

(defn add "adds two numbers" [a b] (+ a b))

craftybones13:04:55

Then, add can be queried later on the REPL

Alex13:04:04

okay so what you're saying is that to get documentation it would be better to query the repl

Alex13:04:17

anything to list what's available in a namespace?

craftybones13:04:01

Look up `ns-publics)

Alex13:04:11

so the user namespace gives you the tools to query this info, seems like it

craftybones13:04:19

The language is highly reflective

craftybones13:04:36

Data can be associated to a lot of entities, if not all and can then thus be queried

Alex13:04:19

what i'm gonna do now is enumerate the available stdlib namespaces, pump them out into a file, have some code that gets that information very quickly into something i can use as a list, then that should be enough, cheers

craftybones13:04:38

I understand you have a plan

craftybones13:04:22

But my genuine advice is to go about learning the language first instead of fixating on your eventual outcome. My experience is that this approach causes a lot of people to flame out and give up

craftybones13:04:37

Clojure is genuinely different and takes a little getting used to

Alex13:04:21

yea i get what you're saying, just for me to program i have to have tools to know what functions are available, ideally without asking google for help every two seconds, just trying to have a way to quickly get the names of what's out there so i can grep for what i'm looking for

Alex13:04:56

for chicken scheme i have a huge list compiled by this one program that makes pressing command and / very easy to get that, then it goes deeper, i'll have a tool ready to query the repl in the future instead

Alex13:04:38

appreciate the advice and am gonna play around with vsc next and the more standard workflows to experiment with the tutorials people have written then go from there

craftybones13:04:34

This is my VSCode setup

Alex13:04:52

nice, seems very comprehensive

craftybones13:04:57

As you can see, I typed in the function map and hovering my cursor on it immediately fetched me the doc

craftybones13:04:39

I am not sure if you really need to rebuild tooling just for your purpose. I believe that a lot of what you seek is already there

craftybones13:04:51

<looks around to see if somebody else can help me convey what I am trying to say. I feel like i am failing>

Alex13:04:55

nah i get it, chats to the repl to use doc to get info on the function under the cursor, what i'm looking for is a way to get information like this very quickly, but this is fine since i can chain the question of what's available in a namespace with some scripting, would you recommend any way to get all the available namespaces at a point in time?

Alex13:04:14

aka i can just search the list and it fuzzy matches it and opens up documentation, so i'm 90% of the way through having something similar with what you just shared, cheers

Alex14:04:37

no call-with-values in clojure i see

Alex14:04:48

trying to write a cheeky little compose function

Alex14:04:22

looks like the builtin offering's called comp 👀

craftybones14:04:21

No continuations in Clj

👍 1
Alex14:04:21

#!/usr/bin/env clojure

(defn -main "" []
  (print 123))

(-main)
is there a better way to do this if i want to script around with it? to implicitly call the entrypoint?

Alex14:04:02

do you recommend anything to format clojure, aside from schematic-format?

Ben Sless14:04:03

With acme I'd try to set up something to send a file or form over a socket to a running REPL process Same for doc for symbol at point, source for symbol, etc

Alex14:04:29

thanks, playing around with automating gonrepl (found online)

Ben Sless14:04:40

Working in Clojure heavily relies on having a running REPL process and communicating with it. I recommend going over this section for useful references https://clojure.org/guides/repl/launching_a_basic_repl

Alex14:04:18

#!/usr/bin/env clojure

(def format-module-name #(apply str % "/" %&))

(defn get-modules
  "Take the namespaces available in the toplevel and return the functions
   in fun formatted strings."
  []
  (map
   (fn [ns]
       (map (partial format-module-name (ns-name ns))
            (keys (ns-publics ns))))
   (all-ns)))

(map println (flatten (get-modules)))
been golfing around for the last while, would anyone recommend a better way to write this?

Alex14:04:53

might start by dropping the let

craftybones14:04:01

(defn get-modules [] (map (comp str symbol) (mapcat (comp vals ns-publics) (all-ns))))

👀 1
craftybones14:04:05

No need to flatten

craftybones14:04:15

No need for format module either

Ben Sless14:04:20

Again,I recommend not building this up as a set of CLI utilities but as a set of dynamic functions invoked from the REPL

Ben Sless14:04:47

And send all this code to your running REPL instead of running a clojure process each time

craftybones15:04:12

If you are using VSCode or Cursive, you wouldn’t need to build all this tooling to begin with

Ben Sless15:04:23

There's also a bunch of existing tooling you can build on. For example, both calva and cider share back end code in clojure

Ben Sless15:04:15

So don't try to shoehorn clojure to work with acme like acme does things. Make acme participate in how clojure does things instead (if you insist on using acme)

🙇 1
Alex15:04:08

ayyy, cheers

Alex15:04:08

so cause of the sequences, all of this is lazy til it hits the function with side effects?

Ben Sless15:04:29

map is lazy, it returns a lazy sequence

Ben Sless15:04:50

But try working with data rather than side effects

Alex15:04:52

cheers

👍 1
Alex16:04:10

thanks for your help guys, this works perfectly for me, got lein running as a server, now to implement some stuff to do exec, cheers

#!/bin/sh -e

alias exec_stdin="gonrepl -a :7182 2>&1"

get_namespaces() {
	exec_stdin <<EOF
(map
  (comp println str symbol)
  (mapcat (comp vals ns-publics) (all-ns)))

EOF
}

doc="$(get_namespaces | dmenu)"

[ -z "$doc" ] && exit 1

echo "(clojure.repl/doc $doc)" \
	| exec_stdin \
	| PlumbAndClean "/clojure/doc/$doc/"

Chase16:04:54

https://clojure.org/api/cheatsheet This is also a great way to explore the std lib. But yeah, if you can't get a repl driven workflow going with Acme where you evaluate expressions in your source code I think you might bounce off Clojure because that is why most of us are here almost. It is where a lot of the joy and flow comes from imo. That is why everyone is concerned about reiterating that to you.

Chase16:04:33

A quick google search resulted in a couple of possible avenues to explore: https://github.com/mkmik/acmeclj and http://blog.mattyw.net/blog/2013/10/17/clojure-programming-in-acme/

noisesmith16:04:35

regarding acme: I think the best bet would be to start a socket repl and use nc to send code to it

# start the server in the terminal
justin@abjection:~$ clj -J-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"
Clojure 1.10.1
user=> 
# send input with nc or any other cli program that writes to a socket:
justin@abjection:~$ echo '(+ 1  1)' | nc localhost 5555
user=> 2
user=> 
^C

clojure-spin 1
zakkor07:06:37

@U051SS2EU this is perfect, thanks! I'm also trying to get an acme setup going, but what you provided is basically 99% there

zakkor07:06:25

I'm also planning to adapt the code from https://github.com/mkmik/acmeclj responsible for intercepting B2 clicks, and make it do echo '$selection' | nc localhost 5555 instead

zakkor07:06:41

this + starting the clojure socket REPL in win should get me an environment with an interactive REPL you can type in, and also a way to send code from any file into the REPL too

zakkor09:06:29

Don't really need anything extra - it just works!

noisesmith15:07:45

that's how it should be, awesome

sheluchin11:04:17

https://clojure.org/reference/transducers says that transducers > specify only the essence of the transformation in terms of an individual element. How is it possible to use dedupe in a transducer if transducers only look at individual elements? Dedupe needs to compare consecutive elements to do its thing. What am I misunderstanding here? edit: nevermind, I see this is explained further in https://clojure.org/reference/transducers#_transducers_with_reduction_state

👍 1
delaguardo11:04:18

The missing part is "statefull transducer".

sheluchin11:04:12

I see that. Thank you. This stuff is pretty hard to understand at first. Going to take a good bit of review to get the concepts to stick.

Chase16:04:38

For some of us it is hard to understand at the upteempth time going through it. lol But I'll keep trying

❤️ 1
dominikk16:04:39

Hello everyone, I'm currently working on my learning-project (basically a glorified CRUD-App), which i wrote in clojurescript. It's my first ever clojure/script app and I wanted to keep everything really simple. Therefore I decided not to use a database but store everything in a map wrapped in a reagent atom. I (naively) thought: at some point I will just write the map to disk to save my 'database'. I just realized that I cannot do this from clojurescript (for good reasons) so it looks like I need to set up some kind of clojure backend for the database. I'm in need of some guidance how to do this. I'm currently using figwheel-main for the reloading and deps.edn for dependencies. I'd like to avoid using leiningen, since I'm used to deps.edn now. I looked around for good tutorials but it's difficult since there are so many different libraries and combinations of tools people use. Can someone recommend a simple way to do this or a tutorial which is also keeping complexity to a minimum? Thank you!

pithyless17:04:09

@U0372PMDM60 just out of curiosity - if you don't have a lot of data and it's good enough to work only on your local machine; perhaps you can just 'save' the data to the browser localstorage?

pithyless17:04:54

That would be pretty close to your original idea of just writing the map to disk.

pithyless17:04:49

This could be as naive and simple as:

;; write
(.setItem js/localStorage "db" (pr-str @db-atom))

;; read
(reset! db-atom (cljs.reader/read-string (.getItem js/localStorage "db")))

Chase17:04:18

And if you do decide to go the backend route, most recommend starting small with ring and maybe compojure. Here is a short tutorial that could help get ya started: https://www.youtube.com/watch?v=M97jWSKoV3k

dominikk17:04:44

Thank you both! I thought about using localStorage. Since I planned extending it with a backend at some point anyway maybe it's just time to get into that. Thank you for the video link. Looks promising!

Chase18:04:39

If you get more ambitious on the backend, this example app uses the same technologies and goes more in depth: https://github.com/seancorfield/usermanager-example The author is very active on here (this whole community is quieter on the weekends just fyi).

👍 1
dominikk06:04:37

Seems like a good reference. I think I can start from there. Thank you!

1
JoshLemer19:04:06

Is there anything in clojure.core like a atom but which is not thread-safe? Like, sometimes if you want a local "atom", but don't want the overhead of thread-safety? (Assuming there is some overhead of synchronization)

Alex Miller (Clojure team)20:04:56

you should consider Box to be internal implementation, not public API

JoshLemer22:04:48

Indeed setting/getting on Box is about approx 10x faster than atom

ghadi23:04:12

You can simulate Box with a deftype + mutable field