This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-26
Channels
- # announcements (10)
- # aws (5)
- # babashka (27)
- # beginners (175)
- # boot (1)
- # braveandtrue (2)
- # calva (11)
- # cider (13)
- # clj-kondo (91)
- # cljs-dev (54)
- # cljsrn (20)
- # clojure (164)
- # clojure-gamedev (3)
- # clojure-uk (43)
- # clojurescript (185)
- # core-async (6)
- # core-typed (1)
- # cursive (1)
- # docker (2)
- # emacs (2)
- # figwheel-main (78)
- # fulcro (69)
- # off-topic (20)
- # pathom (30)
- # planck (3)
- # re-frame (6)
- # reagent (70)
- # reitit (26)
- # ring (1)
- # shadow-cljs (120)
- # tools-deps (6)
- # vim (9)
Thank you all for being available for my first day of Closure. So far I am finding that the things I expect to be difficult are simple and it is a joy to be discovering that. Sorry Emacs users, but it just does not feel right even with all the nice integration. Five years of nvim/tmux feels like a fast and maneuverable sports car that gets you there immediately.
(let [out (f args)]
(doseq [_ (range (count args))]
(prn (<! out))))
I'm new to clojurescript
and I'm trying to write above function (not the whole function but the gut of it) that given a list of args
that I want to apply f
(f returns a go block which is a channel) to each of the arg
so instead of prn
how can I exhaust out
channel and return materialized list of values?
Also I need to close
the out
channel at the very end what's the best way to do it?
Thanks.Hi! Does someone have example simple frontend-backend CRUD project with reitit? I cannot understand how to interact from frontend to backend rest api. May I just use simple http requests from frontend route handlers to bakend?
There is apparently a #reitit channel that might have more people who have used that library who may know
@J I am not sure I understand what you are looking for. Could it be something like this?
(defn foo [args]
(doseq [arg args]
(prn (<! (f arg)))))
Thanks, will take a look.
Is this similar to merge
?
https://clojure.github.io/core.async/#clojure.core.async/merge
I tried merge as I could not close the channel before producing a result, however I needed throttling and merge
for some reasons, with cljs
, buf-or-n
didn't seem to work.
Looks like into
only works once a channel is closed.
In particular, note that creating a range over the count of args is unnecessary -- you can just as well traverse over the sequence args
itself.
trying deps.edn. Umm.. dumb question but how do i get it to acutally download the dependencies?
It should download any that you do not already have by running clj
or clojure
commands, automatically
and print messages about the ones it is downloading, as it does so
I just typed clj and the repl prompt showed but it did not download limo or any of the selenium jars
And you believe those are in your deps.edn
file as dependencies?
If you are willing to publish your deps.edn
file contents somewhere public and link to it here, I can look at it.
Or you can copy and paste it here, if it is short
When I create a new directory with a deps.edn
file with the same contents as that, and run the clj
command in that directory, I see about 50 lines of output about dependencies being downloaded, before I see the REPL prompt appear. The first 2 lines of output look like this:
Downloading: limo/limo/0.2.11/limo-0.2.11.pom from clojars
Downloading: org/seleniumhq/selenium/selenium-api/3.141.59/selenium-api-3.141.59.pom from central
What command did you try, and did you run it from the same directory where that deps.edn
file exists? What is the output of clj -Sdescribe
command on your system?
clj -Sdescribe
{:version "1.10.1.489"
:config-files ["/home/ben/.clojure/deps.edn" "deps.edn" ]
:config-user "/home/ben/.clojure/deps.edn"
:config-project "deps.edn"
:install-dir "/nix/store/5v3qrsa7mkx433b35yglw146krbnzyil-clojure-1.10.1.489-prefix"
:config-dir "/home/ben/.clojure"
:cache-dir ".cpcache"
:force false
:repro false
:resolve-aliases ""
:classpath-aliases ""
:jvm-aliases ""
:main-aliases ""
:all-aliases ""}
Do you get a REPL prompt when you run clj
or clojure
commands?
Very likely something else you did before running those commands already downloaded those dependencies and put them inside your $HOME/.m2 directory. For example, if you ever used a Leiningen project that used those same dependencies, they would have been downloaded then, and the clj
command is finding them there already, and not downloading them again.
If you really want to, you could force it to download all needed dependencies again by deleting your entire $HOME/.m2 directory. Do not do that if there is anything in there that you have any doubts about being able to retrieve again, but if it is all open source stuff available from public sources, there is unlikely to be any problem with doing so, except for the extra time to download dependencies again.
But using existing dependencies inside of $HOME/.m2 is the reason they are put in there, as a local cache on your system.
I am experimenting with using Kakoune as a text editor and i wired it up to the klipse-repl (which I did fire up before running clj)
It is not as intuitive (yet0 to see all the downloads (as opposed to something like cursive)
I am not aware of any record kept of the reason that files were put into $HOME/.m2 stored there, except perhaps your operating system's date and time stamp on the file, but that still doesn't tell you which software caused it to be downloaded.
For clojurescript, is there another way to shift code to compile time besides macros? I have a function that updates an atom multiple times to construct a final hashmap. the input is pre-determined. I honestly don't need to optimize this....just curious 🙂. I'm basically constructing map to represent groups of items, where the groups have names and use keywords to reference the actual items.
If it isn't doing fresh downloads, then as long as your $HOME/.m2 files don't get corrupted or in some weird state, it is there to make things go faster.
It is a Java/Maven thing that Clojure/Java uses, too.
Either way
Error: Could not find or load main class clojure.main Caused by: java.lang.ClassNotFoundException: clojure.main
As output from running clj
command with no arguments, in the same directory where that same deps.edn
file is? Or from doing something else?
Doing what?
Hmm. I am getting the same messages when I try removing the $HOME/.m2 directory on my system. I have not encountered this before. Doing some experiments to see if I can figure out why that happens.
Never had that problem when using Leiningen or Maven for Clojure things, so didn't expect it to be any different for clj
I use Nixos so I can just roll back my system, but wanted to see if using this exotic OS might be the cause...I guess not
Ah, I know. I forget sometimes that there is another kind of caching going on by clj
that is stored in a .cpcache directory in the same directory where your deps.edn file is.
Files in the .cpcache directory often contain full path names to files in your $HOME/.m2 directory, so if you delete $HOME/.m2, but not also .cpcache, it will believe what is in .cpcache and give that error.
Should work if you also delete .cpcache directory.
The next clj
command should rebuild its contents.
Or clj -Sforce
Is conjoining a vector of 2 elements with a hashmap , such as (conj {} [:1 2])
, defined behavior and will continue to operate this way in the future?
Ah, seq can be used as sort of the inverse of this operation, so seems to be planned out this way.
Anyone know how I can leave the debugger for cider emacs? After I do <f9> (I have doom emacs), there is a red rectangle around the functions and I cannot turn them off. This also happened after I pressed 'q'
ask at #cider
If you type q does it say it's recording a macro? Does doom also have a "run next command as emacs"? Sometimes the evil bindings take over and I have to type \
to have it recognize q as the quit command.
@U012BEGBECC Evaluate the (defn ,,,)
expression you instrumented with cider debugger from within the source code buffer. Evaluating the defn expression will remove the breakpoints that cider debugger creates and removes the red boarder from the defn name.
I recommend getting used to evaluating within the source code buffer rather than using a repl buffer directly, its much more efficient in the long run.
thxs! That works. This has been making me quite annoyed... Also.. are u the practicalli? If you are, I love your website and your youtube channel. 😄
Hello all, is it possible to use clojure for computer graphics and computer vision? Thanks.
tbh I don't know any clojure libraries or ways that u can do those stuff, but I just found this website and maybe this will help https://www.clojure-toolbox.com/
it doesn't reflect changes that I make to a given function, but instead acts as if it was never changed
@irabicoff you need to reload the file so that the changes can get picked up
to see command for that look at keyboard shortcuts “Load current file and dependencies”
do you have advance for quick shortcuts for things like 'load ... dependencies' and evaluate form?
main ones I use are connect to repl, load file/deps, and evaluate form you can evaluate form in repl, as a comment, or in Calva terminal output (which is what I mostly use) also there’s a #calva channel
ah wonderful -- just figured out how to 'load current namespace in REPL..' which is what I think you mean by 'calva terminal output'
do you know how to open terminal in vscode? in that same panel there’s an “output” tab and to the right there’s a dropdown with a list of extension that print their output, see “Calva says”
@irabicoff There's a #calva channel where you'll be able to get in-depth help on Calva. I would have expected that you can eval each top-level form as you edit, without even saving your file, to get updated function definitions into the REPL. Nearly all Clojure editors support that -- I'm sure Calva does too.
thanks! It turns out that you do need to reload before evaluating again, but this can be done upon save
That really doesn't sound right. All the Clojure editors I know let you evaluate the current (top-level) form into the REPL without saving the file. No reloading is needed.
And with Calva, no need to evaluate the whole file also, if you don't need it. To quickly eval something and test, I first evaluate the ns form at the top and the needed form. Of course if that form has a dependency that dependency needs to be evaluated first.
@seancorfield is that meant to apply to definitions outside the evaluated form? not sure what ideal experience should be but I find that I if I change code in the file I have to reload it so that evaluate form can get latest definitions
@alidcastano Every time you make any change in the editor (to a defn
), you can evaluate that top-level form (definition) into the REPL without needing to save the file. Assuming you're doing Clojure, not ClojureScript.
I make a change, hit ctrl-; B
in my editor, it evals that whole form into the REPL.
I go back and forth between files, making changes, hitting ctrl-; B
(eval top-level form), running tests (`ctrl-; t` for a single test, ctrl-; x
for all tests in a single ns). No file saving needed.
so to be clear, the evaluate form is always its latest version, but other definitions in the file might not be.
I think it would be a bit difficult to create a Clojure editor where it is not the latest evaluated definitions of things that are used. It is how Clojure works. Calva does not by default evaluate saved files, a lot because of this. The workflow is supposed to be that you edit a form and then re-evaluate it, and then use it. It is not file based, but rather form based.
One thing to understand is that Clojure does not operate over files. Source files is often an abstraction in other languages. In Clojure, code is at the form level. A form is any unit that can be compiled and evaluated on its own. So a string is a form, a symbol, an S-expression, etc.
You can see this at the REPL. The REPL isn't just for development, the REPL is also how programs are ran
I wouldn’t say the REPL (read, eval, print, loop) is how programs are ran. 1. programs aren’t typically printing at each read and eval. 2. after your program starts, it’s uncommon to keep reading in expressions to keep your program going. while it’s technically true that your program is still processing whatever forms its already read, I think it gives the wrong intuition to you’re program is still “running via the repl”
Clojure reads some form, then evaluates it, then it prints it (that's the step it wouldn't do for a real program) and then it loops back to waiting for the next form to read
So when you run a script, meaning some Clojure code stored in a file. All that happens is Clojure will read the file from top to bottom and it will read and eval each form one by one as it encounters them in the file
When you run Clojure with a main and add libs, it does something similar. The point is it is all a convention. By convention, Clojure reads and evaluate forms in a file from top to bottom.
By convention, if it encounters a "ns" form, it will pause the reading and evaluating of the current file, and go read and evaluate the required libs defined in the ns
, etc.
It’s not “pausing”, it just another expression that it evaluates like any other
Well, I mean that it'll take a detour, like the next form to evaluate is not the one after ns in the current file, but the ones in the require libs. But you're right, in theory that's just part of the evaluation of ns.
When you are at the REPL, you are in charge of choosing in what order you want forms read and evaluated by the REPL
This confuses people a lot at first. But there are good reasons to want to skip over some forms or change the order when you are at the REPL, often so you can prevent state from being overridden which you were currently using to test things, or when you want to explicitly create some temporary state only for the current REPL session
So the editor you use should give you at minimum three features: (1) A way to send a single form to the REPL. (2) A way to send all forms from top to bottom in a buffer to the REPL. (3) A way to send all files in the project to the REPL starting from the main entry if there is one. Additionally, some editor will also give you a way to clear the REPL state for some or all namespaces. The reason for this last one is that when you send forms to be evaluated, they don't replace the old form that was previously sent. They simply add a new one. So old functions of the same name still exist in memory. If you want to remove those you need to explicitly remove them.
I dont understand what 3 means or why you would do that?
I might not have explained that well. But it reloads the file that depends on the file you are on
I think, anyways, I don't actually use that one very much :p, but I've seen editors have a third thing. Cursive calls it sync files in REPL, and forgot what's the name for it in Cider
You can run Sync file in REPL and it'll do it for you, somehow figuring out in what order based on their requires
So my thought was that it'll find every root of the namespace trees of the files in your src folder, and then do a load file on those
So my thought was that it'll find every root of the namespace trees of the files in your src folder, and then do a load file on those
^ @pez i think Calva is missing (3) ? i.e. as opposed to reloading all of a file’s dependencies manually though maybe I just need to get used to re-evaluating forms as I make changes
I think it's best to just get used to controlling it manually. Once you start to setup state that you depend on for your REPL session, the fine grained control comes in handy
Some people like to rely heavily on defounce instead, but I find that kind of weird, cause then once you want to force the defounce to reevaluate it gets tricky
@alidcastano Every time you make any change in the editor (to a defn
), you can evaluate that top-level form (definition) into the REPL without needing to save the file. Assuming you're doing Clojure, not ClojureScript.
I'll give an example:
(def items (atom []))
; At the REPL, not in your code:
(swap! items conj 1 2 3)
;; Back in code:
(defn process-items [items] ...)
Now imagine you are working on process items, and as you implement it, you want to keep calling it with your list of items. If you Load file, you will re-evaluate the (def items (atom []) which will reset the list to empty. And you will lose your test lost that you were using to call process-items with.Why switch from the editor to the REPL? Why not just have
(comment
(swap! items conj 1 2 3))
inline in the source file and eval that code without even leaving the editor!Just to keep my example to the point. I wouldn't actually switch. But I mean to say, here's code that you won't commit to git, (or which will be commented when committed). So like, code you don't actually intend to be part of your program
Though sometimes I switch to the REPL still, because the REPL can be in a different namespace.
Sometimes I want to test calling my thing from the context of a calling namespace for example. Maybe because my items list is in that other namespace
And part of that is because Cider does some magic that makes it I can't just do: (comment (in-ns foo) ... (in-ns bla))
But probably I should get used to having the other namespace open on a separate buffer as well :man-shrugging:😝
Stu Halloway talks about this in one or two of his presentations: don't type into the REPL, type into your editor and eval forms as you go.
I wouldn’t say the REPL (read, eval, print, loop) is how programs are ran. 1. programs aren’t typically printing at each read and eval. 2. after your program starts, it’s uncommon to keep reading in expressions to keep your program going. while it’s technically true that your program is still processing whatever forms its already read, I think it gives the wrong intuition to you’re program is still “running via the repl”
Well, I'm reducing the details a bit. A program won't print, and won't read from the command line. But you can think of it as reading a recorded REPL session from a file. Where it'll replay things in order from top to bottom.
The important bit is that it is always read a form, eval the form. That's the basic. Files don't really exist. Everything is just forms that are read and evaluated one after another in some order. And then, around this mechanism, there are conventions and tooling build for different use case.
I agree that having read
and eval
are the important bits. I think it’s also worth emphasizing that read
and eval
are distinct, separate steps (which is different from most non lisps).
It's hard to explain the machinery, but it is all much simpler in some way, and the primitive is read and eval, and everything else are things that you could have build yourself. While other languages have them as a part of their compiler and run-time, and you can only change if you change the code for the compiler and run-time
I would be careful about explaining read and eval in terms of a “repl” since the “repl” has connotations of a command line program that’s connected to stdin and stdout that the programmer is typing directly into (which is how the repl is used in other languages).
People at my work new to Clojure seem to understand it better when I phrase it like that
fair enough
If I say, when your program runs it's literally doing exactly the same thing as if you had typed it in at the REPL in order from top to bottom
how is that different than python/javascript
Hum.. well it's not really different then those I don't think. But it's very different from Java, which is often the background people at my work have.
I guess most of the people I talk to have a js or python background
Ya so they might not have this problem. In Python/JavaScript, can't you use a function defined after from before it?
in js, there’s hoisting, but it’s not good to rely upon it
your program should run the same as if you had typed into the repl, but you can do some funky things if you want
Maybe by convention it isn't good practice, but it still would be different, because it now operates at the file level and has concept of files
The next question would be about how modules are handled and if they are tied to files, and if hoisting is at the file level or module level
so while those are technical differences, I’m not sure they highlight why clojure might be a good option compared to dynamic alternatives like python and js
It doesn't. I'm not trying to make a judgement call. Just that this is how it works, and it works in a way that often doesn't line up with people's expectations coming from other language. Like why is the REPL not automatically in-sync with the files? Why does it say it can't find the function foo when I run my script even though it is defined in the file?
:thumbsup: that makes a lot of sense if you’re coming from a java, c++
The REPL is a tooling around this to allow you to send code to be read/evaluated on command in the order you choose. clojure.main is another tool which will send forms from a set of files or libs you specify to it which it will use to read/eval from
At least this holds for Clojure, when you hit Java things change, and you hit limitations.
After a couple of previous failed attempts to understand transducers I sat down today to try and get my head round the concepts. After a few passes through the docs and a couple of videos, I came up with this as a possibly correct and hopefully easy to understand summary. Putting it out here because a) any feedback or corrections would be appreciated and b) maybe it will be useful to others. https://redpenguin101.github.io/Notes_Clojure/transducers2
And reducing functions don't need to produce a smaller output. Like you can do what you do with map with reduce as well. The output can even be larger
Thanks! I get your second comment. Your first one I will have to noodle on for a bit... > a way to compose reducing functions together
Its like, the transducing function takes a reducing function as argument, and can choose to call it or not and when on the element to process. And in turn, it will return a reducing function, which can be passed to the next transducer for which it too will choose if it wants to call it or not, etc.
So what happens is you get a chain of reducing functions calling one another recursively and finally returning the transformed value
The transducing functions are used to create this chain for arbitrary reducing functions
For example, you can write a reducing function which will increment all elements. And another one which will filter even elements. But what if you want to now increment all elements and filter them? You can perform both reduce one after another. But there is another way. You could have the first reducer increment the element, and then call the second reducer to have it filtered. So now one reducer calls the other. But, if you do it like that, everytime you need to compose two or more reducers, you have to write a custom reducing function that calls each other inside themselves. With transducer, you generalize this so you can have the transducer return you a reducing function that calls the others for you.
@allaboutthatmace1789 awesome! while no expert, i look forward to reading it momentarily