This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # announcements (2)
- # beginners (169)
- # boot (11)
- # cider (11)
- # clj-kondo (7)
- # cljdoc (1)
- # cljsrn (5)
- # clojure (120)
- # clojure-dev (21)
- # clojure-europe (3)
- # clojure-france (1)
- # clojure-italy (62)
- # clojure-nl (8)
- # clojure-spec (26)
- # clojure-uk (40)
- # clojuredesign-podcast (1)
- # clojurescript (3)
- # cursive (2)
- # data-science (2)
- # datomic (10)
- # emacs (2)
- # figwheel-main (1)
- # fulcro (17)
- # graphql (5)
- # hoplon (5)
- # jackdaw (15)
- # jobs (2)
- # juxt (1)
- # luminus (5)
- # off-topic (1)
- # onyx (11)
- # pathom (4)
- # pedestal (1)
- # re-frame (4)
- # reagent (11)
- # reitit (1)
- # remote-jobs (5)
- # shadow-cljs (48)
- # spacemacs (2)
- # specter (4)
- # sql (24)
- # tools-deps (25)
- # vim (82)
i think i already know the answer to this, but are there any conventions or mechanisms for organizing clojure code in the same file?
What is the idiomatic use of
loop? I mean, where would you use this instead of just calling the function recursively itself?
Every time you call a function you allocate a new frame to the stack and might run into StackOverflowError but loop-recur mechanism uses tail call optimization which creates only one frame during the whole recursion
Typically you prefer
loop because it doesn't consume the stack. Clojure does not have tail call optimization, so to compensate it includes the loop/recur macros that convert recursive looking forms into loops. Now, the target of
recur can be the 'current' function, but often it's inconvenient to have to write a whole function form to create a possible recur context. The
loop is useful for this.
Aaah, I see—so does that mean the preferred way of writing recursive functions in Clojure in general is to use loop/recur? I’m playing with the language for some time now and have mostly seen calling the function itself by name or using recur, that’s why I’m surprised
Depends on the problem. In some cases, it's cleanest to recur to the function callsite, in other cases it's cleaner to recur to a loop target. In general, it's best to avoid recursive calls unless you're returning a lazy sequence, which will produce values without consuming stack.
there's a nice, short talk on loop/recur here, which covers some of it's details, as well as its weaknesses. Hopefully some of these problems will be addressed in a future clojure release: https://www.youtube.com/watch?v=SJmK1R0ADnc
I am using reagent/re-frame to build some FE. After a while of development my browsers starts to eat up all the memory. What is usual the issue here?
Use your memory profile dev tools to capture a memory profile and see where the RAM is being used
One problem I keep running into is not being able to decide what the best way of writing a piece of code. For instance, I have a date that I need to get into the
YYYY-MM-DD format from a regular UTC time stamp. I came up with 3 different ways to do this with each IMO having their pros and cons.
The first one is more descriptive and I believe tells you exactly what I am doing.
(the nested threading I am not too fond of tho)
(->> (-> decision :updated_at tco/from-string) (tf/unparse (tf/formatters :date)))
The second and third one seem straight forward
(first (clojure.string/split updated-at #"T"))
I am pretty sure you can avoid nesting thread in this case
I didn't test it but I think it should work
(->> decision :updated_at tco/from-string (tf/unparse (tf/formatters :date)))
Yea I agree. Plus if the format of date changes then I have to remember to come inside this function and change the regex. Whereas in this case it should handle most changes.
I think the first one is the best solutino for "parse", but maybe put (tf/unparse (tf/formatters :date)) in it's own function to remove the nesting
After some thinking I think the first one is the better solution. Its less brittle IMO
so I'm making a program that is going to have a server and a client and some sort of database for the server to communicate to. I want to use vagrant and ansible to develop locally for now. Is having two programs under one project as simple as dividing the code base between server and client, or do I have to do special things in deps.edn to build server code and client code?
deps.edn doesn't even build - in this case do you mean constructing separate classpaths or a separate build tool?
I would assume you'd have one deps file for the client process, and another for the server
This is kind of what I was getting at, I'm very new to all this so I'm trying to get the 'hello world' of setups with ansible and deps.edn, but struggling to figure it all out you know?
deps.edn is a tool for constructing a classpath, so I assume it would be useful for the ansible build for that specific usage. Often when packaging people want to set up a persistent cache of external artifacts on CI, and point the dep resolution to that cache
in the jvm, the classpath is the list of locations used for finding resources, code, or class files
okay, and deps.edn is a way of saying 'here's a package, heres a list of files it brings to the table so use these
what deps.edn (or lein, or boot) do is take a list of dependencies, resolve their tree of transitive deps, download all the ones you don't have already to a cache, then point your java classpath to all those artifacts
it's not unusual in my experience for a clojure program in production to have ~20 explicit deps that are used directly, and hundreds of deps total once they are transitively resolved
in a running clojure program you can see your starting classpath with
> (System/getProperty "java.class.path")
the reason I'm a little confused is because I've never done server/client applications in any language so I'm learning the theory and the practice slowly
right - so in theory your server and client could be 100% independent codebases and share nothing but an implicit agreement to use the same resource paths on some protocol
in practice, with clojure, one advantage is we can share the same data functions and configs between front end and back end code, to simplify that distributed interaction
I don't mind having a
client folder to seperate the codebases, but it would be nice to keep it all under the same project I guess?
The goal today is to just have some data on the server, just a string, and simply get it sent to the client to be displayed. Then stage two would be storing that in a database and learning how to get info out the db to the server, then serve it to the client
in my experience this structure was good:
src/clj/foo/bar - everything under this path is server code,
src/cljs/foo/bar - everything under this path is client
src/cljc/foo/bar - everything under this path is code used by both client and server (custom data logic that both ends want, in particular)
for example a data validator would go in src/cljc so that client and server would implicitly agree on data format
with deps.edn I'd use one deps file to build deps for the jvm process that compiles the cljs to js, and another to build the deps for the server process
I'd probably write server / client to make it easier for me but I take your point
that's fair, but breaking it up by file suffix simplifies things in the case where cljc can be loaded by both cljs and clj
I was wondering about this article: https://semaphoreci.com/community/tutorials/how-to-set-up-a-clojure-environment-with-ansible
It talks about setting up two roles,
lein. how exactly do the two differ other than one is using a REPL and the other is just the program?
Or will they mostly do the ssame things? (I'm just thinking, how I'm going to do this when I'm not using leiningen so)
lein is a build tool - it constructs a class path, runs dev tasks, builds artifacts, etc.
java is the vm that actually runs clj code (even lein uses java to carry out the task you ask it for)
you'll need to find some replacement for the lein uberjar task (which constructs an artifact to deploy), but otherwise deps.edn can construct a classpath and run a repl
okay thats great, so while the building the artifact isn't something I can do, I can still replace lein (I know I can do a repl so hopefully I can hook this into that?)
well lein is doing multiple roles, and the premise of deps.edn was to specialize away from that - so you've replaced some lein usecases but not all the lein usecases in that blogpost
oh wait - that blog post is doing a bad thing - using lein to run a server process :/
which is good news for you because deps.edn is actually OK for running a server, lein isn;t :D
I assumed they would be using lein to build an uberjar - that's the sensible way to do ops with lein, but they are instead using the build tool to run the process in prod
it's the equivalent of shipping source + Makefile to your server, then running gcc before startup :P
im still trying to get my head around roles.. so, a role can do tasks, and sometimes you can have a common role to do common tasks. But in this post, the
lein role just installs leiningen.. I don't really see where the magic happens
--- # config/roles/lein/tasks/main.yml # Install leiningen - name: Copy lein script copy: src=lein dest=/usr/bin/lein owner=root group=root mode=755
They store a copy in the configuration and just copy it over, so I'm not really sure where in this post it starts the server? Like that's what I'm looking for at least
by the way thank you for talking about this with me I should have asked rather than bombard you with questions like I have 😞
nothing here looks specific to that codebase though: no matter how you code your app, you will end up running
-main in some namespace to start a service
oh, I accidentally answered your question above: the convention is for program entry points to be named
-main, so that is what starts the service
you can pass an argument to clojure.main to start the -main in a specific ns instead of a repl, and this is how one runs a clojure service if they aren't crazy like whoever put together this blogpost
there's a few reasons not to use lein to run on a server: lack of concrete redeployable artifact, useless parent process that starts up only to create your classpath, the wrong jvm settings for running a server
using deps.edn is luckily better behaved (but I'd still recommend making an uberjar or similar that allows recreating a specific deploy)
okay.. I'm trying to connect the dots as there's a lot of buzzwords but not much connection, or at least, its not so clear to me.
Vagrant fires up some virtual machines. You give it a file name as a playbook which is a set of tasks given to a set of roles.
Why is there a need for the
leiningen role if it is just a single task. I assume when you switch from local to a server, you would edit your playbook and change the role from
java, but I'm trying to connect the playbook to the tasks
NB: often you'll get a much better deploy setup with clojure itself by finding the instructions for setting up a java project, then using an uberjar using clojure.main + your source where they would use a java fat jar
I know nothing about ansible roles - based on how they cargo cult the clojure stuff I wouldn't be surprised if they were using ansible weirdly too
So in his example,
common role has a task called
Install motd. I can see it, it places some data somewhere I assume for the program to grab.
However, the playbook is also a list of things. What are these things? So, the only one I have is named
Apply common configuration and looks like this:
So, to all the hosts in the vagrant the common role is.. applied? And in doing so all of common's tasks are completed automatically?
--- # ansible/provision.yml # Provision development environment - name: Apply common configuration hosts: all sudo: yes roles: - common
I might actually go and write my own tutorial after I crack this as without a background in networking it's not so easy to get into this
I mean - maybe they have their own slack or IRC or whatever - big parts of what you need to figure out are not clojure related
it should be possible to break this up into domain specific parts: a generic ansible setup with a spot for "construct the artifacts your program needs on deploy" - an ansible expert could help there
Finding itweird that it's going to require an expert to show me these things, I'm going through the ansible docs for a bit I think
I think one systemic issue is that at most one person needs to sort this out for a given project in most cases, and the task is done once per project and rarely needs to be updated
A role isn't what I thought it was. A Role is a self-contained playbook, so a playbook can contain tasks as well as the roles, and the reason I didn't see the tasks get called before is purely because they're called not by the playbook but by the role
Hi, i'm using the
clj-http library to perform a POST request and I'm receiving this error
the payload is no that big in order to reach some kind of overflow, however I imagine that this is the case
i googled this error and it seems to be related to teh default tls tranpsort on java 1.8
@iagwanderson there have been a few issues with the TLS1.3 stack on 11 -- some fixed in 11.0.4
I would look into either disabling TLS1.3: SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setExcludeProtocols("TLSv1.3"); or bumping to 11.0.4
@ghadi do you have any idea of how to disable the protocol on the
clj-http library? I've beein searching for this
but I still don't get how this is associated with the size of my payload. If I send less items in the request, I get no errors
I' getting a really strange error running my starter project here, from lein new compojure to tryna throw in HTTP-KIT...
xception in thread "main" Syntax error macroexpanding clojure.core/ns at (clojure/tools/namespace.clj:15:1). Call to clojure.core/ns did not conform to spec.
` [ring/ring-devel 1.1.8] [ns-tracker 0.2.1] [org.clojure/tools.namespace 0.1.3]`
yeah, that's way old - if you explicitly ask for 0.2.11 before ring-devel in the deps list that error will go away
(there might be a newer version still, but I have proof locally that 0.2.11 does not have that error)
Who are you, who are so wise in the ways of science? Arthur, King of the Britons! /holygrail