Fork me on GitHub
#beginners
<
2019-06-26
>
PaulGureghian01:06:32

How to download the lein for Windows files ?

andy.fingerhut01:06:25

I do not know if that is the correct link, but you could copy and paste that into a web browser and see

andy.fingerhut01:06:57

If it isn't, you can go to https://leiningen.org, find the 'install' section, and look for the link to the lein.bat Windows install script

PaulGureghian01:06:02

How to download the file ?

dpsutton01:06:02

right click and "file save as"?

PaulGureghian01:06:15

Which file do I run ?

dpsutton01:06:32

i think there's a file called lein.bat that you run

dpsutton01:06:40

that's what you should have downloaded

PaulGureghian01:06:45

I think this is it. but it faulted

PaulGureghian02:06:50

Do I need to put the .bat file into the other directory ?

seancorfield02:06:22

@paulgureghian Do you have Java installed? What does java -version print?

PaulGureghian02:06:56

I think I just need to put 'lein' in the PATH first.

dpsutton02:06:27

(sorry i'm at the very edge of my windows help capability :)

PaulGureghian02:06:00

Do I have I to make the lein.bat executable ? or is that only for the linux script ? .bat is already executable ?

PaulGureghian02:06:24

I put 'lein' on the path and it still faults. # lein.bat Error: Could not find or load main class clojure.main

seancorfield02:06:56

I just downloaded lein.bat (right click > save link as... ) on a Windows machine that has Java but not Leiningen. When I ran lein.bat it said I needed to self install, so I ran lein.bat self-install and it set up Leiningen. Then lein.bat prints out help, as I would expect.

PaulGureghian02:06:27

Win 10 right ?

seancorfield02:06:32

C:\Users\seanc>lein.bat

C:\Users\seanc\.lein\self-installs\leiningen-2.9.1-standalone.jar can not be found.
You can try running "lein self-install"
or change LEIN_JAR environment variable
or edit lein.bat to set appropriate LEIN_JAR path.


C:\Users\seanc>lein.bat self-install
Downloading Leiningen now...

C:\Users\seanc>lein.bat
Leiningen is a tool for working with Clojure projects.

Several tasks are available:
change              Rewrite project.clj with f applied to the value at key-or-path.
check               Check syntax and warn on reflection.
...

seancorfield02:06:09

Yeah, Windows 10. I don't know why you get that message about not finding clojure.main

seancorfield02:06:36

C:\Users\seanc>lein version
Leiningen 2.9.1 on Java 11.0.2 OpenJDK 64-Bit Server VM
C:\Users\seanc>java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.2+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.2+9, mixed mode)

PaulGureghian02:06:03

Looks like I really need to upgrade my PS

seancorfield02:06:18

I'm using cmd for this, not Powershell.

seancorfield02:06:36

I don't know whether the lein.bat file will run in Powershell?

seancorfield02:06:33

Can you try using cmd instead and seeing if the lein.bat self-install script will run there?

PaulGureghian02:06:46

I think you might be right. I need a new method

dpsutton02:06:15

did you follow the suggestion there? to download the zip file manually?

PaulGureghian02:06:50

actually im using con emu, and it tells me to upgrade PS

dpsutton02:06:07

no idea what that is but i hope it works 🙂

dpsutton02:06:41

@seancorfield loved the memoized screencast. Using tap> at work and just fixed a bug in cider-nrepl with it. Quite handy

dpsutton02:06:54

you're an excellent walker-througher 🙂

seancorfield02:06:08

I think tap> is great -- especially since REBL added the browse taps functionality!

dpsutton02:06:44

yeah i'm tapping into the repl and into a sliding buffer of the last ten values. Need to get rebl hooked up with my environment soon

seancorfield02:06:04

@deleted-user a debugging function added in Clojure 1.10.

seancorfield02:06:55

@dpsutton And thanks for the kind words about the screencast 🙂

dpsutton02:06:28

of course. thanks for all you do

PaulGureghian02:06:40

Even cmd.exe tells me to upgrade PS.

seancorfield02:06:26

@paulgureghian You could follow the ZIP download advice. Go to this page https://github.com/technomancy/leiningen/releases/tag/2.9.1 and right click > save as on the .zip link. Then extract the ZIP contents. Not sure what the next step is at that point tho'... [then rename it to a .jar] possibly set the LEIN_JAR environment variable to the path of that .jar file

PaulGureghian02:06:00

When I tried that way 'lein.bat' said to uninstall since it would do it itself.

PaulGureghian02:06:23

I guess I need the PATH stuff

seancorfield03:06:36

Ah, looks like that ZIP is the JAR file. I just renamed it (from .zip to .jar). So I downloaded the .zip from the releases page, to my home folder. Renamed it to end in .jar instead of .zip. Then I edited my environment variables for my account so LEIN_JAR was the full filesystem path to that .jar file (in my case c:\users\seanc\leiningen-2.9.1-standalone.jar) and, sure enough, lein.bat was able to find it and run Leiningen for me.

seancorfield03:06:45

@paulgureghian ^ maybe that will help

dpsutton03:06:38

That was the instruction given in the first screenshot. Just easy to miss

seancorfield03:06:44

@dpsutton Yeah, I hadn't read it closely because "It Just Worked" for me without that. Good to know how it works in the non-installing case 🙂

Ahmed Hassan05:06:20

How can a function be side-effectual and idempotent at same time? >Like halt-key!, suspend-key! should be both side-effectful and idempotent.

seancorfield05:06:56

@ahmed1hsn A bit of context, perhaps? 🙂

seancorfield05:06:51

Ah, I figured it would be something like Component... yes, in Component, both start and stop should be designed to be idempotent but they are (usually) side-effecting.

seancorfield05:06:34

What it means is you can safely call suspend-key! multiple times. It will apply its side effects as needed, but it can be called multiple times on a system.

seancorfield05:06:32

In Component, what that means is that if you start a system that has already been started, it will have no effect (the system remains started). When you call stop, it will stop the system if it is running. If you call stop on a stopped system, it will have no effect.

metehan08:06:02

I am trying to render a simple graph with cljsjs.chartjs. I think I am sending data to graph in wrong way when i need to send a JS object shouldn't I send a map instead?

Mno08:06:39

I'm not sure how the library works, but you could try passing it the js version of your opts (clj->js opts)

kstehn09:06:28

You need to call it like (js/Chart. ctx (clj->js opts))

metehan09:06:12

thank you very much

metehan09:06:20

it worked like this 🙂

dmaiocchi09:06:49

what is the latest data serialization you have used in your clojure project as curiosity question?

dmaiocchi09:06:12

I'm about to pick-up nippy with rabbitmq

acron10:06:22

nippy is very good

papachan12:06:26

is there a way to launch my project clj -A:dev directly through cider?

dpsutton12:06:49

@papachan sure is. use a prefix when you jack in. If you're not familiar, jack-in is C-c M-j and just add a C-u right before it (that's the prefix). This will let you edit the jack in command

dmaiocchi13:06:55

I dunno if anyone has used already the langohr rabbitmq library, I just ask in case somebody knows 😁 I'm trying to pass an argument to my handler function that I use to consumer subscribe

dmaiocchi13:06:40

this works, but it is without args from message-handler

(lc/subscribe ch qe-name msg-handler {:auto-ack true})

dmaiocchi13:06:54

so i would like to pass to

msg-handler
like an argument, but seeing the definition of the library, I can't find a way ( https://github.com/michaelklishin/langohr/blob/8506117cb7c29256f3d7e94dc8d510c7c0946fe0/src/clojure/langohr/consumers.clj#L86)

dmaiocchi13:06:32

reading the doc it says that it take a Clojure map of message metadata. But I don't know where I could modify this metadata to append my argument to the handler 😁

dmaiocchi13:06:56

ok I might find out a workaround, I can define the handler via let inside my function and then I can create it more or less dynamically

cider 4
clj 4
🦆 4
papachan14:06:18

I do clj -Atest but i have no test running

papachan14:06:02

my basic deps.edn file

papachan15:06:06

maybe because its a clojurescript project?

credulous16:06:36

Hi, not sure if this is the best place to ask this, but I’ve got an issue deploying a compojure app. I’m using these routes:

(compojure/defroutes app
  (-> (compojure/routes
        (compojure/GET "/" [] (response/file-response "index.html" ))
        (route/resources "/")
        api/routes )
      reload/wrap-reload))

credulous16:06:46

The first two are probably redundant

credulous16:06:19

In any case, I can run on localhost against an uberjar, and can load index.html as expected

credulous16:06:51

But the same uberjar on my production server gives 404s for everything… except the API routes, which work perfectly

ghadi16:06:16

what is api aliased to?

credulous16:06:39

[alexandria.api.routes :as api]

dpsutton16:06:45

is this the standard "files don't exist in jars" problem?

ghadi16:06:02

yeah probably dpsutton

ghadi16:06:19

perhaps the uberjar locally is not just the uberjar

credulous16:06:39

I tried running against the uberjar in a clean folder

ghadi16:06:46

with what command?

credulous16:06:07

I also tried unzipping the jar on the production server and using the unzipped folder in the classpath

ghadi16:06:33

(defn resources
  "Returns a route for serving resources on the classpath.
  Accepts the following options:
  :root
  : the root prefix path of the resources, defaults to \"public\"

credulous16:06:59

In the unpacked folder, I also moved all the resources into a public folder

credulous16:06:30

sudo java -cp unpacked/ clojure.main -m alexandria.core is the command I used to run it… is that what you meant @ghadi?

ghadi16:06:55

is all your code + resources under unpacked?

ghadi16:06:36

the way I debug stuff like this is to load a repl and run the following:

(require '[ :as io])

(io/resource "public/js/main.js") ;; or whatever

credulous16:06:48

Yes. Two resources for example: index.html and js/main.js - they exist both as unpacked/index.html and unpacked/public/index.html

ghadi16:06:19

if io/resource returns nil, there is a classpath problem

ghadi16:06:29

if it returns a URL, all good

ghadi16:06:09

you can introspect the active classpath with (System/getProperty "java.class.path")

credulous16:06:01

Thanks… so I am getting nil when I just start a repl with clj… sorry for the newb question, but how can I start a repl that has the same classpath as when I execute java -cp unpacked?

credulous16:06:45

I’m pretty sure I’ve heard of people attaching a repl to a running server, but that’s above my paygrade at the moment

ghadi16:06:05

if you are getting nil with clj, something is wrong already...

ghadi16:06:29

make sure resources is in your :paths in clj

ghadi16:06:31

and that your stuff appears under $root/resources/public/js/whatever.js

credulous16:06:33

Do you mean make sure resources is in :paths in deps.edn?

credulous16:06:37

or something different?

ghadi16:06:13

^ when you look at that using java or clj or lein, one of the root classpath directories will need to have a public folder underneath it

ghadi16:06:28

if that is true, you'll be golden

credulous16:06:47

When I run clj is it modifying the classpath from the deps.edn contained in the folder I run it from?

ghadi16:06:02

clj -Spath shows the classpath, too

credulous16:06:04

because my uberjar does not have the deps.edn in it. When I do what you describe above on localhost, (io/resource “js/main.js”) returns a URL, but only when I execute clj from the project directory

ghadi16:06:30

note that compojure is looking for (io/resource “public/js/main.js”) not (io/resource “js/main.js”)

credulous16:06:16

That will probably be my next hurdle. 😄 Right now, on the server, the classpath doesn’t contain anything project specific at all.

credulous16:06:02

I’m puzzled though: when I run java -cp alexandria.jar (or the unpacked directory) shouldn’t everything there be included in the classpath?

ghadi16:06:37

it's probably in the jar, in the wrong place @credulous

ghadi16:06:49

unzip -l thejar | grep '\.js'

credulous16:06:52

Agreed, which is why I moved to working with the unpacked folder

ghadi16:06:16

if it's wrong in the jar, it's wrong in the unpacked too

credulous16:06:34

But I copied all the resources (which were in root) into a public folder

ghadi16:06:46

be specific

ghadi16:06:01

where do the files exist under unpacked

credulous16:06:09

$ROOT/unpacked/public/js/main.js

credulous16:06:30

$ROOT/unpacked/public/index.html

ghadi16:06:47

something doesn't add up

ghadi16:06:02

mkdir -p unpacked/public
touch unpacked/public/index.html
java -cp unpacked:$(clj -Spath) clojure.main
Clojure 1.10.1
user=> (require ')
nil
user=> ( "public/index.html")
#object[java.net.URL 0x2b4c1d96 "file:redacted"]

credulous16:06:44

Thanks for your help

kenj16:06:37

Having no real experience w/ Java web apps or JEE, what are the advantages of running a web app inside of an app server like Wildfly or Tomcat, as opposed to a standalone jar with an embedded http server?

credulous16:06:29

So, like so many things: simple solution to my woes above: I was including a trailing slash in my classpath when using an unpacked jar file. No slash, no sorrow.

Javier Gonzalez-Compte17:06:36

hey! I have a channel that is a kafka-consumer I want all those messages to be into a sequence

Javier Gonzalez-Compte17:06:04

is it possible using atoms

mafcocinco17:06:59

You could do that but it doesn't seem like the most idiomatic way to do it in Clojure, IMO.

mafcocinco17:06:10

@javiergonzalez7 why do you want to put them in atoms vs. just processing the messages as the come off of the topic?

Javier Gonzalez-Compte17:06:19

cus I want to use different threads for each message

mafcocinco17:06:34

You might want to give this a try: https://github.com/NovoLabs/gregor

Javier Gonzalez-Compte17:06:58

yea been using kinsky but I think its not the way to go with this approach

mafcocinco17:06:16

Kinksy offers an async interface as well.

Javier Gonzalez-Compte17:06:34

yep this method of processing messages is only going to be used for one source

mafcocinco17:06:47

In both cases, you get a channel, which you can then split.

Javier Gonzalez-Compte17:06:47

not for the other ones since the message has a bulk of ids to be processed

Javier Gonzalez-Compte17:06:53

instead of a single id message

mafcocinco17:06:05

I see. So you have 2 different "types" of messages on the topic?

mafcocinco17:06:20

one with a single id and one with a bulk load of ids?

mafcocinco17:06:22

@javiergonzalez7 I would assume 2 different handlers in that case as well, such that you only want one type of handler to see the single id messages and the other to see the bulk load messages?

Javier Gonzalez-Compte17:06:46

Yea. So right now I have a channel with elements that are messages but I want to bulk them so I can do the bulk processing

Javier Gonzalez-Compte17:06:15

cus i will have two different consumers for each method since the message schema is different

Javier Gonzalez-Compte17:06:08

I was thinking of using a go loop to store all those elements into a sequence

Javier Gonzalez-Compte17:06:43

and putting that sequence into a channel

mafcocinco17:06:03

If the messages are different on the topic (i.e. the bulk up process is handled upstream by a producer) then you can use core.async/mult to split the channel, piping the data to 2 different downstream channels. On the first, you can initialize it with a transducer that retains (using filter) only the single id messages. The other channel could be initialized with a transducer that retains the bulk messages. I think that should work.

mafcocinco17:06:18

If you want to build up the bulk message from what is on the channel, that seems more challenging. Basically, that is a reduction to the channel and I'm not sure if that is possible on channels that never close (as would be the case with Kafka).

mafcocinco17:06:58

But I could be wrong about that. Definitely take with a grain of salt my word on what is and is not possible with async channels. 🙂

Javier Gonzalez-Compte17:06:35

Thank you! I think the first one would be the best way

zav18:06:25

Hey all, I'm trying to import a local JAR in a Clojure project as a POC for Clojure-Java interop and am struggling with the process of getting the thing installed, naming, etc.... In Java, I have a class like:

package com.michael;

public class Interop {
    public static int add(int a, int b) {
        return a + b;
    }
}
I created the ~/.m2 path for this using Leiningen via the project.clj by adding the dep [com.michael.interop/HelloWorld] and move the jar into that directory, ~/.m2/repository/com/michael/interop/com.michael.interop/1.0.0

zav19:06:01

Still when I run any command run/deps/test etc... I get the following error,

Could not find artifact com.michael.interop:HelloWorld:jar:1.0.0 in central ()
Could not find artifact com.michael.interop:HelloWorld:jar:1.0.0 in clojars ()
This could be due to a typo in :dependencies, file system permissions, or network issues.
If you are behind a proxy, try setting the 'http_proxy' environment variable.

zav19:06:17

Any ideas as to what I'm doing wrong?

zav19:06:16

Sorry, the dependency includes the version "1.0.0" as well

noisesmith19:06:03

you can use lein install to put the jar and pom into the local cache

noisesmith19:06:07

both files are needed

noisesmith19:06:52

that directory path looks wrong - I'd expect ~/.m2/repository/com/michael/interop/1.0.0/

noisesmith19:06:07

but lein install will put it in the right place

zav20:06:25

What exactly does the pom.xml need? Is it just there to manage dependencies? The actual java project I'll be importing is built using gradle so if I can integrate them without converting to maven that would be ideal

noisesmith20:06:21

it needs the pom for transitive deps, yes - you should be able to generate a usable pom from gradle https://stackoverflow.com/a/17283856

noisesmith20:06:54

but also, if you don't care about deps, lein install can create a pom.xml that's minimal and sufficient iirc

noisesmith20:06:09

I'm wrong, lein install needs an existing pom

You can also deploy arbitrary artifacts from disk:

    $ lein deploy myrepo com.blueant/fancypants 1.0.1 fancypants.jar pom.xml

The repository can be defined in defproject or a profile, or it can be a URL.
Use file://$HOME/.m2/repository to install in the local repo.
(excerpt from lein help deploy referenced from lein help install)

zav21:06:25

Thank you for all of the help! I'm going to go give this a shot!

dmaiocchi19:06:49

Hi all, I have a curiosity question. In your projects when do you have a configuration.edn file, how do you handle the load configuration data.edn to various program functions? I have seen in the wild differents patterns. Some projects use an atom where they load the conf.edn into atom and the pass it to different functions 'Currently I use a helper function where I just load the edn file and then use it in differents functions. (I call mostly the functions without any args) But with this take, I was thinking that I should pas the conf.edn as an argument to the various functions that need the conf, so I could abstract the fact that it is a edn'file and in future I could use conf as env variables. Etc

noisesmith19:06:01

edn is a string format, so I'd definitely parse it and store it somewhere

noisesmith19:06:12

I wouldn't use an atom, as it makes no sense to mutate config at runtime

noisesmith19:06:33

putting it in a top level var should be fine, just access it from the namespace it's in

clojure-berlin 4
dmaiocchi19:06:03

Do you have a project in the wild as example?

dmaiocchi19:06:28

The question I had was also if I should pass the conf.edn or conf as an argument to a function of just don't pass it.. It is more a retrospective matter... But I was curious to see how other folks do

noisesmith19:06:58

the .edn means its a string - edn is a string format

noisesmith19:06:12

if you mean the data object, sure, passing config as an argument makes sense

dmaiocchi19:06:58

Yes I mean the object

dmaiocchi19:06:22

I used. Edn as slang

noisesmith19:06:40

sadly I don't have a good open source example - I have open sourced libs but don't have a full fledged open source app

dmaiocchi19:06:41

Don't focus on my English ti much I know I need to improve 😁 facepalm 😁

noisesmith19:06:23

sure - I actually understand the slang but make the conscious choice to be pedantic about clojure terminology in this forum :D

noisesmith19:06:32

it helps keep things clear

dmaiocchi19:06:37

Yep thx. 😁 👍 clj

PaulGureghian20:06:59

A bit easier to install Clojure than on Windows. is this verification enough before I use Clojure ?

seancorfield20:06:27

@paulgureghian Looks good. Maybe run clojure -Sdescribe just to double-check the clj version (as opposed to the Clojure version) and verify the deps.edn files it will search.

seancorfield20:06:45

You should see something like this

(! 578)-> clj -Sdescribe
{:version "1.10.1.447"
 :config-files ["/usr/local/Cellar/clojure/1.10.1.447/deps.edn" "/Users/sean/.clojure/deps.edn" ]
 :install-dir "/usr/local/Cellar/clojure/1.10.1.447"
 :config-dir "/Users/sean/.clojure"
 :cache-dir "/Users/sean/.clojure/.cpcache"
 :force false
 :repro false
 :resolve-aliases ""
 :classpath-aliases ""
 :jvm-aliases ""
 :main-aliases ""
 :all-aliases ""}

PaulGureghian20:06:11

Yup. That's what I have

seancorfield20:06:27

(I ran that in a folder that doesn't contain deps.edn, else that would appear as the third item in :config-files)

PaulGureghian20:06:05

I ran it from Home

PaulGureghian20:06:33

Looks like Clojure is an interpreted language

hiredman20:06:41

clojure is compiled to jvm bytecode

PaulGureghian20:06:33

If I refer to a Clojure file as "source code file" instead of 'expression file", will I be tarred and feathered ?

manutter5120:06:02

I’ve never heard of an expression file

manutter5120:06:17

“source code” is standard usage

hiredman20:06:24

expressions is there, expression file is not

hiredman20:06:51

you may be confused when it talks about about the unit of compilation

hiredman20:06:24

thinking it must just be a difference in what the file is being called when it says the unit of compilation is a clojure expression

hiredman20:06:33

but it is not just a difference in what the file is called

hiredman20:06:44

a file is not called something different

hiredman20:06:54

the unit of compilation is a single clojure expression

hiredman20:06:12

(regardless of what you call the file)

PaulGureghian20:06:52

Can I call the whole file (which holds expressions) a clojure source code file ?

hiredman20:06:59

a clojure expression being something like (+ 1 2)

noisesmith20:06:03

when this matters is forward references: the compiler doesn't look ahead in the file to find definitions

hiredman20:06:43

I think you are tripping yourself reading a difference (what a file is called) where there is none

hiredman20:06:38

the difference is something else, when the clojure compiling generates bytecode, it does so for an expression at a time, not a file at a time, which has consequences elsewhere, but is also designed so to be the same as how the repl operates

hiredman21:06:15

a file is a file, a file full of source code is a source code file, source code is source code, etc

hiredman21:06:42

you have misunderstood the meaning and place where a distinction is being drawn there

ghadi21:06:38

i think you have your answer @paulgureghian 😂

dog21:06:11

Hi guys, Quick question, what is the difference between clojure.jdbc\execute! and clojure.jdbc\do-db-commands, they seem to be very similar from just reading the docs

seancorfield21:06:09

@slack1224 Do you mean clojure.java.jdbc? clojure.jdbc is a different library.

seancorfield21:06:02

If you mean the former (the Contrib lib), the answer is that execute! builds a PreparedStatement first and may use .executeUpdate or .executeBatch, whereas do-db-commands builds a Statement instead and always uses .executeBatch -- so execute! can have SQL parameters but do-db-commands cannot. TL;DR: use execute! with SQL operations and do-db-commands for DDL operations.

seancorfield21:06:09

FWIW, the next generation of clojure.java.jdbc is seancorfield/next.jdbc and it no longer draws that distinction: execute! can run both DDL and SQL and uses .execute under the hood. Overall, next.jdbc is simpler (and will usually be faster).

❤️ 4
dog21:06:13

oh i see thank you!

PaulGureghian22:06:54

If I already have Clojure cli tools installed on a MAC, does it make sense to also install lein ?

andy.fingerhut22:06:36

It is not necessary to also install lein, but there should be no conflict between lein and the Clojure cli tools if you install them both.

andy.fingerhut22:06:12

I think many people have both installed on their machines, and alternate using them on different Clojure projects, as desired.

andy.fingerhut22:06:00

You may not want to try learning both of them simultaneously, when starting out.

PaulGureghian22:06:57

I didn't see a list of recommended editors - extensions / IDEs for Clojure on the official site. I like Atom and VSC. good choices are they ?

dog22:06:28

i use calva with VSC, it seems really awesome

dog22:06:46

but you do need to rebind the eval hotkey

andy.fingerhut22:06:52

I believe many people find those to be good choices for Clojure development.

dog22:06:52

its really awkward by default

andy.fingerhut22:06:06

I haven't used them myself, but don't take that as a vote against them.

dog22:06:07

cursive is the biggest one afaik

dog22:06:17

for begininers

andy.fingerhut22:06:34

There are people here who should be able to help you through just about any major editor choice you make, including setup recommendations. Most people would recommend that when starting out with a new language and dev tools, sticking with a familiar editor is probably going to be less frustrating.

andy.fingerhut22:06:08

i.e. one less unfamiliar thing to learn.

seancorfield22:06:25

@paulgureghian I have used Atom for all my Clojure development for several years. I like it a lot. Both Atom and VS Code are fine, if you're used to them.

PaulGureghian22:06:43

Me too. I don't want to deal with the learning curves of VIM and Emacs

PaulGureghian22:06:07

And Sublime is not free

PaulGureghian22:06:11

Don't like Notepad ++

seancorfield22:06:26

This is the list of packages I have installed in Atom:

advanced-open-file
atom-clock
busy-signal
chlorine
git-plus
highlight-selected
ink
intentions
linter
linter-joker
linter-ui-default
lisp-paredit
parinfer
set-syntax
tool-bar
I don't use nREPL, I just use a Socket REPL (hence Chlorine), but I gather there's a nice, simple nREPL package for Atom?

PaulGureghian22:06:49

All that for Clojure ?

seancorfield22:06:07

No, I just find they all make Atom easier to use for me.

seancorfield22:06:52

If you're working with clj/`clojure`, you can either start a Socket REPL to connect to with Chlorine, or an nREPL to connect to with the nrepl package I believe?

PaulGureghian22:06:55

I have 'language_clojure' in Atom.

seancorfield22:06:02

Yes, that's built-in.

seancorfield22:06:08

I highly recommend getting used to working with a REPL connected to your editor, so you can evaluate code directly in the editor. That makes you much more productive with Clojure.

PaulGureghian22:06:24

How do you eval code in the editor ? don't I need to run the .clj file in the terminal ?

seancorfield22:06:37

Work your way through all of that guide -- there's a lot of material in it.

seancorfield22:06:22

The guide has lots of pages. Go all the way through all of it.

seancorfield22:06:10

If you're interested in using Chlorine with Atom for REPL integration, https://atom.io/packages/chlorine has some basic information that should get you up and running.

PaulGureghian22:06:35

Is the same flow in other languages like Rust , Go in play here. create a source code file and run it either in an IDE or the terminal ?

seancorfield22:06:02

No, Clojure really has a unique flow. The REPL is central to how we work, integrated into an editor.

seancorfield22:06:49

We can run Clojure one expression at a time in the REPL (and from an editor) or we can load a whole file. In both cases, Clojure compiles expression as it reads it, then executes it.

seancorfield22:06:27

For example, you can have a running Clojure application -- say a web app -- and use a Socket REPL to connect your editor to it and then run code inside the live, running application. That's usually how we work, to build an application. We have a very tight loop between writing a bit of code and running it, and we can build an application up in small pieces, evaluating each function as we write it into the running application.

PaulGureghian22:06:50

Does Clojure have a dedicated shell ?

seancorfield22:06:58

I don't know what you mean.

PaulGureghian22:06:47

Like in Julia for example, I can use it in terminal, and I can also launch it in its own shell / interpreter

PaulGureghian22:06:42

Actually terminal launches the Julia shell

seancorfield22:06:45

Clojure doesn't have an interpreter. It is always compiled. But the compiler operates one expression at a time, just like the REPL.

seancorfield22:06:08

The Clojure REPL is the "shell".

seancorfield22:06:34

But the important point in Clojure is that it isn't separate, like other languages, and it isn't an interpreter.

noisesmith22:06:51

like a notebook? there's gorilla-repl http://gorilla-repl.org/

PaulGureghian22:06:49

Chlorine - Socket REPL client for Clojure and Clojure script ?

seancorfield22:06:49

That's what I use.

PaulGureghian22:06:23

Its just that when I think of expressions being evaluated, I think of interpreting rather than compiling

noisesmith22:06:45

clojure compiles each expression as you go before running it

PaulGureghian22:06:06

How do you compile one line ?

seancorfield22:06:17

One expression. Not line.

seancorfield22:06:58

user=> (* 2
       13)
Clojure compiles that and runs it and the REPL prints
26

noisesmith22:06:05

each top level expression that is - eg. a defn will contain multiple expressions inside it, but they are all compiled together

noisesmith22:06:30

or (+ 2 13) is three sub-expressions making up one compound expression, technically

andy.fingerhut22:06:19

You do not need to do anything special to cause one "top level" Clojure expression to be compiled. It is compiled automatically, just before it is evaluated.

noisesmith22:06:38

but the clojure compiler doesn't compile until there's a full top level form consumed (so you can leave it hanging if there's invalid input but you haven't given a closing brace for example)

andy.fingerhut22:06:28

The compiler creates the compiled version in the memory of the running Java process, usually without writing anything to disk anywhere. (There is an option to write out a compiled version to disk, but no need to ever do that at all)

andy.fingerhut22:06:31

As far as it appears to you, you can't tell the difference between interpreted or compiled, except it runs faster than it would if it were being interpreted.

PaulGureghian23:06:52

So, it doesn't create an executable ?

seancorfield23:06:56

If you want to create an artifact that can be deployed and run elsewhere, you can build a JAR file, which can be run via java.

seancorfield23:06:38

(that's the same as Scala, Kotlin, Java itself)

PaulGureghian23:06:40

Is that the way most Clojurians operate ?

noisesmith23:06:04

for development we use the repl, and then we make a jar to deploy and run with java on the remote host

seancorfield23:06:26

Development (and often testing) is all done via the REPL or just running clojure (or lein or boot). Deployment to QA/CI/Production/whatever can be done via source code (Datomic Ions works that way I believe?) but is most commonly done by packaging the Clojure code into a .jar file and then running it via the java command.

PaulGureghian23:06:08

Andy said that there is no need to ever write out a compiled version ?

noisesmith23:06:37

you can create and run the jar without compiling beforehand

seancorfield23:06:48

At work, we create .jar files using the depstar library for clj/`clojure` and then we run those .jar files with

java -cp path/to/the.jar clojure.main -m entry.point
where entry.point is whatever namespace contains the -main we want to run.

seancorfield23:06:40

(we package up Clojure code as source in the .jar and then when it is run, the Clojure runtime compiles that source on the fly before it executed)

seancorfield23:06:36

Strictly speaking, the .jar files we create are a mix of our Clojure source code, the compiled Clojure runtime (which includes the compiler BTW), and all the libraries that the code will need to run -- Java libraries, Clojure libraries...

PaulGureghian23:06:51

What languages are direct competitors of Clojure ? compiled or interpreted ?

seancorfield23:06:22

JVM languages are all compiled, including Clojure.

seancorfield23:06:15

Some of those languages have a separate interpreter -- even Java has a "shell" now -- but those interpreters are usually not full-featured and/or have all sorts of restrictions on what they can do.

PaulGureghian23:06:55

Like JIT compilers ?

noisesmith23:06:45

the vm itself does the jit

seancorfield23:06:58

So all JVM languages can take advantage of that.

noisesmith23:06:02

the jit is bytecode in, bytecode out, it doesn't operate on higher level code

seancorfield23:06:36

What languages have you programmed in before @paulgureghian? Maybe it'll help if we can relate aspects of Clojure/JVM to your past experience.

PaulGureghian23:06:22

Python, Javs for Android, Rust, Go,

andy.fingerhut23:06:34

Well, the JVM jit is JVM bytecode in, native code out

andy.fingerhut23:06:52

e.g. x86 object code, or whatever the processor is.

4
seancorfield23:06:17

( Clojure, Java, Scala, Kotlin, etc ) compile source code to JVM bytecode; the JVM runs that bytecode and is technically an interpreter but it also has a JIT compiler that progressively turns "hot" parts of that (interpreted) bytecode to native code as it runs. So pretty much everyone calls JVM-based languages "compiled" -- much like C#/F#/etc are compiled to CLR bytecode.

andy.fingerhut23:06:32

I would think that any sufficiently high level programming language is a "competitor" to Clojure, e.g. Python, Ruby, JavaScript, etc., in terms of some of the features they offer a developer for rapid feature development.

PaulGureghian23:06:35

Just wondering why Clojure would call for openjdk instead of oracle java ?

seancorfield23:06:02

Clojure works just fine on the Oracle JVM.

andy.fingerhut23:06:15

What gave you the impression that Clojure calls for openjdk?

PaulGureghian23:06:59

I think I saw it in the official Clojure install instructions

seancorfield23:06:03

Hmm, I can't find any mention of Oracle's JDK on http://clojure.org -- pretty much everything just sort of assumes you already have a JVM installed. I guess the assumption is that if you're trying Clojure, you already know it's a JVM-based language and you know what that entails...?

seancorfield23:06:23

Which JVM you choose is entirely up to you -- and based on licensing issues.

seancorfield23:06:59

Clojure itself is tested on both OracleJDKs and OpenJDKs https://build.clojure.org/job/clojure-test-matrix/

andy.fingerhut23:06:00

If anyone warned you against the Oracle JDK, my guess is that would be based more on recent Oracle license changes for its JDK, rather than any other reason.

👍 4
hiredman23:06:38

openj9 is also a thing (open sourced from the ibm jvm code), and amazon has their own jvm (I think it is just their packaging of openjdk), both of which run clojure

hiredman23:06:46

azul has zing, which is also some kind of openjdk build

PaulGureghian23:06:24

And another thing that I have been pondering. why the name 'Clojure' /. what is the origin of this name ?

seancorfield23:06:20

(took me a while to track down that -- it probably ought to be added to the FAQ on the main site...)

PaulGureghian23:06:23

Richard Hickey ?

seancorfield23:06:00

Yes. Sorry, most people here just refer to him as "Rich" as if he's the only one 🙂

rich 4
seancorfield23:06:33

"BDFL - Rich Hickey is the creator and Benevolent Dictator for Life of what goes into Clojure." -- https://www.clojure.org/dev/workflow#_groups 🙂

PaulGureghian23:06:18

Its open source, but there is still some oversight

seancorfield23:06:48

Strong oversight -- the language is very carefully designed and evolves very deliberately. It's what makes Clojure so stable across all of its versions (and why it's reasonable to run alpha/beta releases of Clojure itself in production, as we do at work).

PaulGureghian23:06:36

Using Java and the Clojure JAR If you have downloaded and built Clojure, you can use Java to launch a Clojure REPL: java -jar clojure.jar You should see output like the following: Clojure 1.9.0 user=>

PaulGureghian23:06:00

This means you installed Clojure from source ?

PaulGureghian23:06:23

ok. I dont think thats what I did

andy.fingerhut23:06:38

You may choose to build Clojure from source code and create your own jar file, but most people download a pre-built JAR file from the Maven Central site. All of the dev tools Leiningen, boot, Maven, and deps/clj/clojure can download JARs for Clojure and many other libraries for you, once you tell it what kinds of JARs you want in your project.

seancorfield23:06:33

(if you build it from source, you can create a single JAR -- which is what that page talks about, although it should probably be updated to show Clojure 1.10.1 since that's what you'll get if you build it from source these days) [Pull request submitted]