This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-25
Channels
- # announcements (1)
- # beginners (338)
- # calva (41)
- # cider (19)
- # cljdoc (10)
- # cljsrn (6)
- # clojure (116)
- # clojure-europe (15)
- # clojure-italy (25)
- # clojure-nl (5)
- # clojure-spec (19)
- # clojure-uk (52)
- # clojurescript (99)
- # clojurex (14)
- # cursive (47)
- # data-science (1)
- # datomic (5)
- # duct (1)
- # figwheel (13)
- # fulcro (58)
- # graalvm (93)
- # jobs (3)
- # joker (9)
- # luminus (4)
- # nrepl (21)
- # off-topic (41)
- # pathom (25)
- # re-frame (7)
- # reitit (8)
- # ring-swagger (13)
- # tools-deps (13)
Use a Clojure set, e.g. #{:foo :bar :baz}
nb this works with any plain values, except false or nil (I know the question was only about keywords)
like this example from https://clojure.org/guides/spec: (s/def ::suit #{:club :diamond :heart :spade})
So you want a map that can have an arbitrary subset of the keys ::north ::south ::east ::west, and the type of the values associated with them will be the same for each?
You never want to allow a subset of the 4 possible keys, i.e. you want spec to check that all 4 are always present
I guess that is fine, if some of them are walls 🙂
If you had 100 keys all with the same type, I would definitely agree. 4 seems on the edge of "eh, it gets the job done" to me, personally.
That seems pretty important when they have a large variety of specs for each of their corresponding values, doesn't it?
My understanding is that a spec key name is intended to be used throughout a possibly multi-process multi-machine system, and you want the name of that key to have the same kind of contents wherever it appears, in any map where it appears.
e.g. :com.mycompany/customer-id will always have the same kind of associated values, no matter where it is, no matter what it is combined with in whatever maps it ends up in.
I do not know if I understand your use case well enough. Are you saying you might have 10 different kinds of cells, and for each of those 10 kinds, you want to constrain the set of allowed values differently for their :north key?
Sure. I do not have enough spec time under my belt to say whether it was designed to be bent in that direction, or whether you are stretching it unnaturally against its design.
@deleted-user If you go in a direction you get to a (type of) cell, yes?
(assuming that direction is available to you)
When you are in a cell, each of the directions has a wall/door/passage/etc that determines whether you can go that way (and how you do it), yes?
If you had only 2 types of grids, with different sets of values of things you wanted to allow in the north direction for those 2 types, it seems worth asking whether having a :grid1/north and :grid2/north spec might be useful?
And then there's the actual motion from cell to cell, so each direction takes you to a new type of cell...
What are the different types of grids?
All these intermediate steps don't necessarily need a spec. Or, not necessarilly a very granular spec
I'm saying that, because if your goal was validation, or generative testing, the choices for how and what to Spec might be different than other reasons to have the Spec
So, I don't necessarily want to suggest that, because it gets hairy. And I'd wonder if it is really necessary, but you can obviously write spec generating code.
I'm trying to use Luminus to make a POST request, but whenever I try to access the body I get a #object[io.undertow.io.UndertowInputStream
back. I've been trying to figure out what to do with that for like an hour and I still have no idea.
Hum... are you saying the same key will have different type of value in different context?
They allow you to specify that a particular thing is one of many things, with multi-spec letting you define what based on a function.
Alright, I didn't fully understood exactly what you're trying to spec, but I'm glad my pointers helped
@brandon149 hum... this is a wild guess, I've never used Luminus, but try calling it with an @
in front
@didibus I'm still a total n00bie, what's the @
do?
I remember using it with atoms, is that going to be the same kind of thing?
Well, normally it does a thing called deref. Which normally just mean get the value out of a thing.
That gives me an error java.lang.ClassCastException: class io.undertow.io.UndertowInputStream cannot be cast to class java.util.concurrent.Future
It's some kind of stream, but I'm not sure how to read it
most of the java code has something like while (stream.read() > -1)
but that doesn't really translate to clojure as far as I know
i want to start my program with a function other than -main, how do i do that without starting the repl first?
lein run -m your.namespace/the-function
-- see lein help run
for more information
i am using lein
That's an IllegalArgumentException
No matching field found: read for class immutant.web.internal.ring.LazyMap
The real source of my trouble is that I can't figure out how to read an UndertowInputStream
I tried reading the docs for Undertow, but they weren't particularly helpful
which isn't surprising, given my lack of Java experience
@didibus you and me both, man
haha, I'm just wondering if you are calling something lower level that returns the raw stream, and maybe there is another way to make a POST request that returns it parsed?
Given that I'm attempting to add a new ns
of routes, it's probably that I forgot to add something required
I know the original one included some middleware, but I didn't include it
I tried that, it gives me an error something about how it's not a file
Your problems looks a lot like this: https://stackoverflow.com/questions/38120418/convert-bufferedinputstream-to-string-in-clojure
lein run -m your.namespace/the-function
-- see lein help run
for more information
So, after using
, I end up having errors about not being able to JSON encoding a ByteArrayInputStream
which, again, seems pretty similar
Something is weird, when you called (.read body) you got: immutant.web.internal.ring.LazyMap ?
You should be able to call .read
on the UndertowInputStream. The issue is that it seems to be a byte stream. So you will just get a bunch of bytes, and then you need to know the encoding, so you can decode the bytes into whatever they represent
Variations on a lazy maps are used in a number different ring adapters for the request or the headers map
aleph does this, I haven't used undertow in a long time, so it looks like they do this too
Lazy map being a map that doesn't have it's values filled in yet because the adapter is built on some kind of asyncy server that doesn't get the entire request at once
I think you are probably missing a middleware which should decode the undertow stream or something. I really doubt Luminous doesn't handle the byte stream for you
I'm getting weirdly inconsistent results in CIDER and I'm not really sure why
now, I call .read
on (:body req)
and it comes back with 123
Well, that's good, I guess
at least the results making sense now
My guess is you were confused earlier and called in on the request map or the header map
slurp is working now, but I don't understand why
Something weird is going on, because I get different results from the POST call, but they're not consistent
The code I have written right now is identical to something I wrote earlier
but the results aren't the same
it's possible, I'm not particularly familiar with Luminus, and especially not Undertow
I think what was wrong with my debugging
was that, for reasons I don't understand, I need to evaluate the function I'm looking at
and then (restart)
the app
I did not consistently do those things in that order
Hum.. could be. But, it might be you just accidentally were calling slurp on the wrong thing.
It's possible. I'll ascribe the whole thing to my newbie status and hope to learn from it
I'm playing around with the AWS API, so far I've been using amazonica, but I can't make head nor tails of how to set up a client, so I thought I'd try out Cognitect's AWS lib (https://github.com/cognitect-labs/aws-api). However, I'm completely failing to convince lein to download it, and there are only instructions for using deps.edn
😕 Any pointers?
Where it shows this in the README, to use for deps.edn
:
{:deps {com.cognitect.aws/api {:mvn/version "0.8.305"}
com.cognitect.aws/endpoints {:mvn/version "1.1.11.568"}
com.cognitect.aws/s3 {:mvn/version "722.2.468.0"}}}
In a Leiningen project.clj file, that would become the following lines in that file:
:dependencies [
[com.cognitect.aws/api "0.8.305"]
[com.cognitect.aws/endpoints "1.1.11.568"]
[com.cognitect.aws/s3 "722.2.468.0"]
]
HI! have you ever done 2 projects in the same git repository with lein? :thinking_face: e.g I'm doing a client/server project, and I would like to have both on same repository instead of creating an organisation
you can probably do it in one file, i have in the past just used the cljs-build options to differentiate the 2. If you need more separation, eg diff dependencies etc (idk why you would) you can use profiles and the lein with-profile +whatever ...
command
you would just run 2 different commands to start up each ones repl in develop, and make a command that builds both for deploy
It is maybe not super beautiful but I didn't want to spend all the time researching it. The leinigein doc didn't have doc for that. And I think in JVM is possible to do it but I'm not the JVM expert 😁
make a new project doing lein new chestnut app-name
and look at it, it is a template that serves up a routes and compiles a frontend https://github.com/plexus/chestnut

I'm looking currently if I can do it with only 1 project.clj file only or if i need to create directories with 2 project.clj
Hi. I'm trying to create a random matrix. I'm using the matrix.core library...
(clojure.core.matrix/add (rand 5) (clojure.core.matrix/new-matrix 2 2))
But this gives me a matrix where every element is the same random number e.g. [[3.928259253657548 3.928259253657548] [3.928259253657548 3.928259253657548]]
I tried using repeatedly
but the library doesn't handle it the same way normal clojure vectors handle it, so I haven't been able to make use of it
(`(clojure.core.matrix/emap + (repeatedly #(rand 2)) [ 1 1 1 ] )` this actually causes a crash, whereas normal map
is fine)
(clojure.core.matrix/emap #(rand 2) (clojure.core.matrix/new-matrix 2 2))
may be what you are trying to do
Not sure that's a "good solution", but last time I needed to generate a matrix, I relied on clojure.spec + generators...
(def MATRIX-SIZE 100)
(s/def ::image-pixel #{0 1})
(s/def ::image-row (s/coll-of ::image-pixel :count MATRIX-SIZE))
(s/def ::image (s/coll-of ::image-row :count MATRIX-SIZE))
(gen/generate (s/gen ::image))
I've slightly modified @U0C7D2H1U code and it does indeed produce the expected matrix (clojure.core.matrix/emap #(+ % (rand 2)) (clojure.core.matrix/new-matrix 2 2))
I will stick to this for the time being since it accomplishes the task and it's moderately readable. Thanks guys
Hi! I am looking to get some help on getting my installation of clojure working correctly. I am running Ubuntu 18.04 and have installed the prerequisite bash, curl, rlwrap and java, with the latter being
$ java -version
openjdk version "11.0.3" 2019-04-16
OpenJDK Runtime Environment (build 11.0.3+7-Ubuntu-1ubuntu218.04.1)
OpenJDK 64-Bit Server VM (build 11.0.3+7-Ubuntu-1ubuntu218.04.1, mixed mode, sharing)
Some basic functionality works fine, like (def x 7)
or (* 8 8)
, but while working through the official guide (https://clojure.org/guides/learn/syntax) I often walk into java exceptions for code that does work on https://repl.it/languages/clojure, like
Clojure 1.10.0
user=> (def anex (try (/ 1 0) (catch Exception ex ex)))
#'user/anex
user=> (clojure.stacktrace/root-cause anex)
Execution error (ClassNotFoundException) at java.net.URLClassLoader/findClass (URLClassLoader.java:471).
clojure.stacktrace
Does anybody know what exception is actually occurring and how to fix this? I could only find an SO thread mentioning java 8+, but I think I have that installed (I am unsure, I'm not a java programmer). Thanks in advance.How do I require that library?
it is a namespace, and it is part of clojure, so you just need to (require 'clojure.stacktrace)
some of the namespaces that ship with clojure are required elsewhere so end up being sort of implicitly loaded, but the set of namespaces that get loaded like that have changed overtime so it is a best practice to require them if you need them
Right, that clarifies a lot.
The example I gave also works when I require the library, so thanks for helping!
I guess http://repl.it just autoloads a bunch of namespaces then. 😛
That seems reasonable.
in javascript, i can say cost game = new Game(); let card = new Card(game); game.cards.push(card);
, which creates a recursive relationship between the two objects. It's useful so inside the Card
class, you can say if (this.game.method()) { do_stuff(); }
. Is that possible in Clojure? If not, what are the best idioms to handle that kind of relationship?
usually instead of recursively nested values, I'd use a flattened non-recursive structure that describes both relationships
there's no construct or shortcut to create mutual nesting, so you need to use some trick with laziness or mutation
and it's not worth the headache or complexity IMHO
(by flattened non-recursive structure describing relationships I of course mean adjacency list)
to reiterate what noisesmith said: you can do this using mutable values but it is very un-idiomatic
so foo.bar.parent_foo = foo
is instead {:foo {:bar :bar} :bar {:parent_foo :foo}}
hm! that's an interesting idea!
the drawback is that instead of indexing the adj-list directly, you need a function that knows how to walk it
the advantage is you can describe complex recursive relations in immutable data, and the editing operations are much less error prone than the mutable version
also you don't run into stack overflow errors printing it naiively :D
heh That is a benefit!
Another option: let Game and Card instances have unique IDs so they can store references to external instances
in practice it's more complex than my example above - more like {:edges {:foo #{:bar}} :nodes {:bar {:parent-foo :foo}}
right
that's another interesting idea, @john. i'll have to think about that!
@john yeah - the adj-list stores the references and the data in one immutable structure for example, but can use unique ids instead of symbolic names
then it's effectively the same thing
as background: i've been playing with porting a pipeline/queue system from a game engine written in javascript to clojure, for potential use in a card game i maintain. the idea is that the pipeline queues "steps" (which themselves can contain pipelines), and they share common interfaces such as being able to say pipeline.continue()
which will then grab the first step in the queue and call that step.continue()
which then looks to see if it has it's own pipeline or whatever
i feel like i'm going about this the wrong way, but i still feel very new to functional/immutable programming, so trying to make stuff like this work has been kind of breaking my brain lol
@nbtheduke another thing to look at for this kind of game state manipulation are Entity Component Systems, which translate very nicely into immutable data in hashmaps
That's pretty close to what the javascript engine does, and is definitely not what the clojure engine does, lol
and for simple mechanics of queues, use clojure.lang.PersistentQueue/EMPTY
which sadly doesn't have a nice looking data literal
of course nothing prevents you from doing (def | clojure.lang.PersistentQueue/EMPTY)
lol |
, that's pretty clever
@noisesmith do you think he could model his game on core.async machinery? Sounds like he wants to put channels in channels, or some similar abstraction
channels are an io mechanic, and queues are a data structure
they often go together but not always - I'd hold off on async until the domain requires it honestly
(cmd)user=> (def | clojure.lang.PersistentQueue/EMPTY)
#'user/|
(cmd)user=> (-> | (conj :a :b :c) (pop) (conj :d) seq)
(:b :c :d)
right - it's an IO framework not a functional abstraction
I looked into the PersistentQueue, but my issue with it is there's no easy method for prepending things
you need a double ended queue?
I mean, usually queue means fifo, which PersistentQueue does
potentially! i'm not quite sure
Like, I perform an action that then requires reactions, so i'd like to put the reactions before the rest of the queued actions
there's DeQueues built into the vm, but none immutable, and none in clojure itself
of course via into and concat you can force it
(ins)user=> (def q (-> | (conj :a :b :c) (pop) (conj :d)))
#'user/q
(ins)user=> (seq q)
(:b :c :d)
(ins)user=> (into | cat [[:a] q])
#object[clojure.lang.PersistentQueue 0x736d6a5c "clojure.lang.PersistentQueue@298384c8"]
(ins)user=> (seq *1)
(:a :b :c :d)
the prepends are more expensive, but they are possible, and if they are rare it might be worth it(?)
they would not be rare
you could look into finger-trees if you are stuck on immutability https://github.com/clojure/data.finger-tree or use a built in Deque https://docs.oracle.com/javase/7/docs/api/java/util/Deque.html
there's no issue with data safety in concurrency in js
js has no "at the same time"
it's via returns / callbacks
so it's cooperative, there's no interruption
there are concurrency frameworks, but they are driven by providing and returning from callbacks, they don't interrupt code
in jvm clojure where we do have arbitrary interruptive context switches, the combination of immutable data structures and safe containers like atom / ref / agent are sufficient if used correctly
but there's a whole class of errors (all the data integrity stuff) that just doesn't happen in a single thread like js
so that data.priority-map linked above - another thread can't corrupt it because it's immutable, and the workings of atom would ensure that the replacement of one reference to an immutable map by another is done safely
right
@deleted-user precisely, it's classic cooperative concurrency
right, and using an atom correctly prevents this
and in js, it's simpler because it suffices to not return until the data is "coherent" by your definition
@deleted-user the tl;dr version is your function passed to swap! is written so that it does all the operations for an update in one go, and either returns a valid state or errors
even swap! suffices, but swap-vals! is useful sometimes as well
What's the difference between swap!
and swap-vals!
?
is it just that swap-vals! returns both old and new?
I didn't mean to offend. I enjoyed studying the code and linked paper. I thought i identified a small bug and sent a patch to fix it. Didn't mean to annoy
Hi. I’m doing something boneheaded with jdbc.next. Everything works fine when going against a local database, but when I try to connect to a remote I get exceptions saying my connection string is probably wrong. I’m creating a datasource by doing something like this:
(->> { :user "myuser"
:password "very-secure-pw"
:dbname "energy"
:dbtype "mysql"
:host ""
}
jdbc/get-datasource
(reset! datasource))
I can connect to mysql using the command line just fine at that host: mysql -u 'myuser'@'machinename' -p -h
works fine
I’ve tried changing the user in the config map, using “myuser”, “myuser@machinename” and “‘myuser’@‘machinename’”
@credulous I'm not sure how get-datasource
can return nil
at all here. It should either throw an exception or return a javax.sql.DataSource
object. It would also really help us to help you if you could share the exact exception you are getting for "my connection string is probably wrong"... Lots of exceptions are possible if you don't have things set up correctly 🙂
Thanks Sean. This is the exception I’m seeing: (the first line is just from a (println @datasource)
in my code)
19-06-25 20:44:02 MacBook-Pro.hitronhub.home INFO [alexandria.services.mysql:95] - Executing sql against datasource next.jdbc.connection$url_PLUS_etc$reify__1548@3ea730b3
19-06-25 20:44:03 MacBook-Pro.hitronhub.home ERROR [alexandria.services.mysql:98] - SQLException The connection string may not be right. Please visit portal for references.
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException (SQLError.java:129)
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException (SQLError.java:97)
com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException (SQLExceptionsMapping.java:122)
com.mysql.cj.jdbc.ConnectionImpl.createNewIO (ConnectionImpl.java:832)
com.mysql.cj.jdbc.ConnectionImpl.<init> (ConnectionImpl.java:456)
com.mysql.cj.jdbc.ConnectionImpl.getInstance (ConnectionImpl.java:240)
com.mysql.cj.jdbc.NonRegisteringDriver.connect (NonRegisteringDriver.java:207)
java.sql.DriverManager.getConnection (DriverManager.java:664)
java.sql.DriverManager.getConnection (DriverManager.java:208)
next.jdbc.connection/get-driver-connection (connection.clj:78)
next.jdbc.connection/get-driver-connection (connection.clj:74)
next.jdbc.connection/url+etc/reify--1548 (connection.clj:145)
next.jdbc.connection/make-connection (connection.clj:162)
next.jdbc.connection/make-connection (connection.clj:152)
next.jdbc.connection/eval1564/fn--1565 (connection.clj:181)
next.jdbc.protocols/eval1358/fn--1359/G--1349--1366 (protocols.clj:24)
next.jdbc.result-set/eval2004/fn--2012 (result_set.clj:449)
next.jdbc.protocols/eval1390/fn--1421/G--1381--1430 (protocols.clj:33)
next.jdbc/execute! (jdbc.clj:165)
next.jdbc/execute! (jdbc.clj:155)
alexandria.services.mysql/execute! (mysql.clj:96)
alexandria.services.mysql/execute! (mysql.clj:91)
alexandria.services.mysql/query (mysql.clj:102)
alexandria.services.mysql/query (mysql.clj:101)
alexandria.services.mysql$eval11520.invokeStatic (:105)
alexandria.services.mysql$eval11520.invoke (:105)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.load (Compiler.java:7636)
user$eval11516.invokeStatic (:1)
user$eval11516.invoke (:1)
clojure.lang.Compiler.eval (Compiler.java:7177)
clojure.lang.Compiler.eval (Compiler.java:7132)
clojure.core/eval (core.clj:3214)
clojure.core/eval (core.clj:3210)
clojure.main/repl/read-eval-print--9086/fn--9089 (main.clj:437)
clojure.main/repl/read-eval-print--9086 (main.clj:437)
And the remote MySQL instance is running... where?
Looks like Azure, based on that error.
Ah, OK, this is due to Azure's slightly weird username rules. Which version of next.jdbc
are you using? (1.0.0 "gold" should print something more informative for the reified datasource but it will depend on how, exactly, you are printing it -- I would have expected the datasource to print the actual URL being used.
For example, with next.jdbc
1.0.0 (as opposed to the RC):
(! 573)-> clj -Sdeps '{:deps {seancorfield/next.jdbc {:mvn/version "RELEASE"}}}'
Clojure 1.10.1
user=> (require '[next.jdbc :as jdbc])
nil
user=> (def ds (jdbc/get-datasource {:dbname "mydb" :dbtype "mysql" :user "admin" :password "secret" :host ""}))
#'user/ds
user=> (println "this is the datasource" ds)
this is the datasource #object[next.jdbc.connection$url_PLUS_etc$reify__397 0x2a415aa9 jdbc:]
So I would expect to see the URL in the output from your println
call.Based on the Azure docs, I would expect :user
to need to be myuser@machinename
(which I know you said you tried but perhaps you could try it again?)
Thanks, Sean, I really appreciate the help. The issue was indeed the username. Your deduction skills are amazing.
And sorry for not replying right away, my tranquil home suddenly turned into a toddler-bedtime warzone
you might get a better answer on #sql, but my first instinct is that a db spec and a datasource are two ways to get a connection, and you are asking for the datasource out of a db spec
so I'd expect get-connection
which would work on a map like yours, or a datasource
hmm, this makes it look like that should work https://github.com/seancorfield/next-jdbc/blob/master/src/next/jdbc/connection.clj#L171
maybe it is about ssl etc.
clojure.java.jdbc
and next.jdbc
make no assumptions about SSL or not -- they leave that entirely up to the JDBC driver.
@credulous I'm happy to dig into more detail about this in #sql but if you can tell us exactly what error you're getting when connecting to remote, that's going to be a good starting point.
In next.jdbc
, you can (and should) create a datasource from a hash map (unless you're building your own pooled datasource via Hikari/c3p0 etc), so the code is correct in that regard.
(then you -- or next.jdbc
-- can create connections from the datasource, via get-connection
)
ahh- that was my confusion, I thought of a datasource vs. connection config as alternate inputs to get-connection, I guess this taxonomy makes more sense
It was kind of muddy in clojure.java.jdbc
since everything was a hash map. next.jdbc
works on the Java types (`java.sql.Connection`, javax.sql.DataSource
)
can anyone explain why
(into #{})
is faster than (set)
? If both are the same, why ever use (set)
?hey all, wondering what the idiomatic way to traverse a tree and build up a seq of the results of meta
calls on each node. kind of like reduce combined with postwalk. I’m sure there’s a simple solution, but I can’t quite wrap my head around an idiomatic way to do that
@mayanaze I'd have to see some specific code to comment on that. I just ran a few quick tests and didn't much difference between (set coll)
and (into #{} coll)
...
Based on the source, both will use reduce
with conj!
over a transient collection...
@seancorfield thanks for the reply. the test was i was running is pretty simple. run both a couple of times and into is consistently faster
the def is so the repl doesn't need to print 10000000 times
Did you use that actual code? nums
will be realized the first time it is used, but then it will be a fully-realized sequence in the second call.
It might not be relevant, but what OS, JVM version, and Clojure version are you running?
and what kinds of run time results are you seeing?
When I run both of those def
s several times with macOS 10.13.6, Oracle JDK 1.8.0_192, Clojure 1.10.1, the first one was about 21 seconds, but after that both of them varied between 7 to 10 seconds on different runs, where the longer times are likely due to more GC time when the JVM needed to free up some memory. The first time being much longer is likely due to the JVM byte code not being JIT'ed yet.
oh, yes, and the reason that Sean mentioned -- range and take do not actually create the sequence until you force them to, which will happen the first time you run one of the last two def's.
i understand, which is why i run both tests multiple times and ignore the first one
And you see one of those two being consistently faster than the other on your system, across multiple runs? More than the variation in times of the same expression across multiple runs?
here's a more robust test
So regarding your original question, I would think that some people might prefer (set ...)
over (into {} ...)
for code readability reasons, although the difference is minor. I would say that while there are differences in the run times there, and there might even still be with Clojure 1.10, they are within about 10% of each other, so nothing I would lose sleep over. If there is a straightforward root cause that one of them really is consistently faster than the other, a performance-enhancing patch for the other one might be interesting.
@hiredman have the functions changed?
I think the big shake up of fast path reduce implementations, fast iterators, and faster range implementation are all post 1.6
another example:
(time (dotimes [_ 100] (vec (range 100000))))
(time (dotimes [_ 100] (into [] (range 100000))))
Unless you are looking for history of performance changes, the latest Clojure version is probably of most interest here.
so into is generally faster?
unfortunately faster is better
for my case
thanks everyone who helped out
I mean, if some code is in the hot spot of your system or program, and 10% differences there are important to you, measure a few variations and go for it. There are definitely some constructs in Clojure that make a much bigger difference than 10% on performance, and those are worth profiling for and improving -- where it actually matters to you.
Hi. Trying to install Clojure on Win7. I changed the script to use "Tls" but now I get this error and I have tried some fixes but they didn't work.
@paulgureghian is your goal specifically to use the clojure / clj command line tools, or to use the clojure language?
because iirc with windows leiningen is much more mature, and it can load and run the clojure repl / compiler (as long as you have a jvm available)
@paulgureghian If you're determined to get the PowerShell alpha installer working on Windows 7 (which I think would be great), the #clj-on-windows channel will probably be a better place to ask for help since that's where the folks who've worked on that PS script hang out.
Can I do both ?
If you just want to try out Clojure on Windows 7, I agree with @noisesmith that Leiningen is probably going to be the easier path right now.
you can use both - but lein is more likely to just work out of the box, and using lein won't be a blocker to following tutorials you'll find online
whereas deps.edn (the basis for clj / clojure commands) is newer, and less documentation assumes you would be using it
Whats the url ?
this is all you actually need: https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein.bat
you can download and run lein.bat
Is it like a modern distribution of Clojure ?
it's a package manager that assumes you are going to run clojure
you can use the latest clojure version with lein, and it knows how to pull in other libraries, run tests, create a standalone jar for distribution, etc.
clojure itself is a java library, and lein uses a config file to arrange some set of dependencies from a cache, and start the process
Leiningen has been around for a long time so it's the most battle-tested option on Windows, right now.
I can use Clojure in the terminal and the language ?
right, that's what lein is for
(with a focus on configuring individual projects)
eg. once you install lein.bat
you can use lein repl
to get a clojure interactive repl
(in a terminal)
Using the language means using Atom or VSCode with the Clojure extension ?
there are extensions to atom and vscode to connect to nrepl, which is the network repl process lein starts
Yup. Thats what I have
yeah, that actually assumes you are using lein and wouldn't work with clj out of the box
I assume Clojure on Mac / Linux is better ?
somewhat - but since clojure is all java, and java is portable, it all just works once you get a jvm and lein running
(with some gotchas around eg. emacs which prefers to run under linux / mac, but it doesn't sound like you'd have that problem)
there's some cool things going on with clj / deps.edn but especially with windows, it's probably not the right starting place for a beginner
What is the right starting place ? lein ?
yes, use lein to start
I'll let ya know how it goes.
Will Oracle Java be ok ?
yes, as long as you use 1.7 1.8 or newer
The very latest Clojure (1.10) now requires Java 1.8 or higher.
oops!
but really you should probably use 1.11 if you can, right?
1.8 is still pretty solid, but for production use I expect 1.8 will start getting harder and harder to find support for. For personal use, no problem.