This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-12-05
Channels
- # adventofcode (138)
- # announcements (1)
- # babashka (4)
- # beginners (71)
- # biff (2)
- # calva (7)
- # cider (20)
- # clj-kondo (4)
- # cljsrn (4)
- # clojure (36)
- # clojure-europe (37)
- # clojure-nl (2)
- # clojure-norway (27)
- # clojure-portugal (1)
- # clojure-uk (4)
- # clojurescript (8)
- # emacs (3)
- # graphql (1)
- # hugsql (4)
- # humbleui (6)
- # hyperfiddle (1)
- # jobs-discuss (18)
- # joyride (2)
- # malli (17)
- # meander (7)
- # membrane (8)
- # off-topic (16)
- # pathom (14)
- # portal (4)
- # rdf (36)
- # reitit (4)
- # releases (2)
- # remote-jobs (1)
- # scittle (15)
- # shadow-cljs (13)
- # tools-deps (40)
how do i use tranducers
have you read the https://clojure.org/reference/transducers on transducers?
https://lambdaisland.com/episodes/transducers Is a great tutorial
@U11BV7MTK i read it but couldn’t understand nvm i read it again and got it thanks anyway
When transducers came out, Rich Hickey gave two talks: 1. https://www.youtube.com/watch?v=6mTbuzafcII 2. https://www.youtube.com/watch?v=4KqUvG8HPYo If you want to really simplify them, the first explains "why" and the second "how". Perhaps they will help you as much as they helped me. :]
The transcripts are also here, if you prefer: https://github.com/matthiasn/talk-transcripts/tree/master/Hickey_Rich
I also find Fred Overflow's videos on Youtube great to learn about transducers: https://www.youtube.com/watch?v=TaazvSJvBaw If you happen to be doing Advent of Code as well, many times he ends up refactoring his solutions to use transducers and I think that may have helped me understand them the most since I had solved the problems as well.
A styling question: There are a number of methods that one can use to wrap many-arguments functions with in named facades, namely,
1. With def + lambda (def specialisation #(generic-fn "val1" "val2" %))
2. With partial (def specialisation (partial generic-fn "val1" "val2"))
3. With defn (defn specialisation [last-arg] (generic-fn arg1 arg2 last-arg))
I have looked in https://guide.clojure.style/ and didn’t see this being addressed. Alex has https://ask.clojure.org/index.php/8373/when-should-prefer-comp-and-partial-to-anonymous-functions?show=8374#a8374 that he’d prefer anonymous fns to partials, but that answer was in a pretty different context. This is quite a subjective question by I would still love to know if someone has already written down some thoughts on this that I missed. Otherwise what would you personally prefer and why?
defn > #() > partial because top level functions much easier to refactor and work with (kudos to clojure-lsp and cider) i prefer anonymous functions over partial because it is easier to read and understand which argument guess where
Importantly here , partial captures the value of generic-fn at definition time so won’t see redefinition at the repl (as it doesn’t use the var)
And I would agree with that preference for defn over the others
Another big plus for defn
is docstrings and parameter name metadata. Once you define something with defn
, your editor can provide this documentation to you automatically when using the function.
It is possible to get at this metadata, and thus theoretically pass it on for consumption by tooling. But the straightfoward solution is to just wrap up what would be def
'd function inside a defn
'd function that provides the docstring and names for the parameters.
Hello, am getting started for first time trying to use Calva with Windows 10 and VSCode. If I run the Calva ' getting started REP' from the VSCode command prompt it works fine and the interpreter runs. However, if i create my own local files and try to run a REPL on it using jack in nothing happens. I spoke to the calva developer but no dice! Have searched Youtube and the web for a basic getting started demo and frankly it's all pure 'geekdom'. There appears to be no entry level explanation.
Are you using wsl2 or Windows directly?
Calva dev here. I wouldn't summarize the talk as ”no dice” :smile: but indeed, this can be tricky to get working, for reasons unknown to me. I suggest to try these two things, regardless if the first one works or not: *1. Try without `clojure*:` a. Remove your install of `clojure` from your computer. b. Check that the Getting Started REPL still works c. Check that you can use Calva to start the repl (jack in) to a basic deps.edn project. ”Basic” meaning it has this structure: ```. ├── deps.edn └── src └── hello.clj``` Where `deps.edn` has this content: ```{}``` `src/hello.clj`: ```(ns hello) (defn hello-world [] (println "Hello World") "Hello World") (hello-world)``` After jack-in, open the `src/hello.clj` file and use the command *Calva: Load/Evaluate Current File and its dependencies*. You should see this in the output/REPL window: ```; Evaluating file: hello.clj Hello World "Hello World"``` *2. Use `clojure`, without Calva* a. Install `clojure` per <https://clojure.org/guides/install_clojure#_windows_instructions|these instructions> b. With a terminal in the project root of ^that^ simple project, issue the command `clj` c. Try the following: ``` % clj Clojure 1.11.1 user=> (load-file "src/hello.clj") Hello World "Hello World" user=> (in-ns (in-ns 'hello) #object[clojure.lang.Namespace 0x5bb8f9e2 "hello"] hello=> (hello-world) Hello World "Hello World" hello=>``` Your output should look very similar to mine. If experiment 2 fails, then something is up with how `clojure` is installed on your machine. It is the same on my two Windows machines, so I think it might be quite common. There is a channel for <#CFN4QDHPS|> where you might get tips on how to proceed. One way is to use the Windows binary of deps.clj from here: <https://github.com/borkdude/deps.clj/releases/tag/v1.11.1.1200> and rename it to `clojure` somewhere in the PATH. (Instead of the ”official” command.) It's what I do on Windows (which I don't use often at all, so I am a bit at loss trying to help you, unfortunately.) In any case, experiment 2 must succeed for Calva to be able to use the `clojure` binary. If 2 works, but you can't jack-in with Calva, then we have a bug (or you might need to start VS Code from a terminal where the `clojure` command works). Please also feel welcome to ask for help in the <#CBE668G4R|> channel.
One more thing. @U04CGV9PKQD, there is a channel where we try to figure on ways we can improve the starting ramp for Clojure. Please add your experience and thoughts about it there: #C02CPM2R1KK
Hi, thanks for feedback. Am using Windows directly. I finally found an idiots guide on Youtube for Calva and VSCode (for Windows) and managed to install Leiningen. Am assuming that Leiningen sets up new projects with correct directory structure so that my source and deps.edn files can be read correctly by VSCode. Unfortunately too little knowledge is a bad thing!
Leiningen is another tool for launching Clojure (and more). Generally speaking, it is clojure
or lein
. Where clojure
is from the same team as provide Clojure, and Leiningen is a community contribution, which has been around for much longer than clojure
has (I think). Leiningen has a better Windows story, I also think. You probably won't start with using deps.edn
for dependencies, because Leiningen has its own system for that, which will go into project.clj
, the project file for Leiningen projects.
Leiningen is wonderful, if that works for you, that is great. When you really need to use clojure
, e.g. you want to contribute to some deps.edn
based project, you can solve this mystery on your machine then.
I followed Pez's instructions above and on running the jack-in command VS code asks me which project type..'Babashka, nbb or joyride?', none of which work and the jack-in fails.. The idiots guide for Windows and Calva on Youtube i am following is using Lein to set up the project so I will follow that religiously and see where it gets me.
I think that you must have missed something in the instructions, because in addition to those project types you mention, it should offer the project type deps.edn
.
VS Code is project folder based. So you need to have window with that basic project's root opened as the folder for the instructions to work.
ok thanks for the info. No DEPS.EDN offered as project. Got it working now using Leiningen. At cmd prompt I use lein new project, then in the created project directory typed code . and the project opened in VSCode. I opened the core.clj and ran the jack-in command, which asked for the project type ( which is leiningen) and all works fine... Going to go through the tests in th LISP book, familiarise with VSCode and come back to the deps.edn issue later. Thanks again for all your help
So, sorry for nagging, but if you place a deps.edn
file in that Leiningen project root. And you jack-in, you don't get offered to jack-in to the deps.edn project type?
If dealing with a huge EDN map, is it possible to do lookups without loading the whole thing into memory?
I'm not aware of any built in way to do this. Postgres can import data from arbitrary sources (e.g. CSV files). It's called foreign data wrappers and I think edn files are can be supported
If your edn files are so big that they don't fit in memory, maybe it's better to put them into some kind of a database anyway. If you can't do that you could split them into multiple files and run something like a bloom filter on each to find which contains the key you're looking for. I'm afraid I don't have any clojure-specific solutions though
Thanks, @UEQPKG7HQ. I too suspect a DB is the way to go. I was looking at using some lazy-map implementation like https://github.com/originrose/lazy-map, but it looks like you still have to have an actual map at some point. It would be cool if you could evaluate maps in Clojure and only go a level deep or something so lookups could be light on maps with heavy values.
Oh, I assumed you wanted to split the map laterally, are you more worried about the depth of the map than it's width?
Not that I have any insights to offer based on this new information, lol
Maps aren't necessarily eager, if one of the nested values is a lazy sequence it will still not be evaluated unless you explicitly realize it. If you can represent all the values as lazy computations I think that you can have what you want :thinking_face: Interesting idea for a library 😄
All you need is to reimplement all the clojure.core functions that operate on maps (assoc, merge, etc) and establish a mapping between files and key paths, easy peasy!
(merge {:a "a"}
(when (= 1 1)
(when (= 2 2)
(if (= 3 3)
{:foo "bar"}
{:foo "nax"}))
(when (= 3 3)
(if (= 4 4)
{:zzz "bax"}
{:zzz "naz"}))))
this returns {:a "a", :zzz "bax"}
but I want it to return {:a "a" :foo "bar" :zzz "bax"}
can anyone explain why it behaves the way it does and apart from repeating
(when (= 1 1))
what would be the alternative way to write this? (it’s kind of nested so once I’ll get it working it’ll be separate functions)You need to barf that last when
expression out of the first when
expression. Right now, the first when
has two forms in its body and ignores the result of the first form, as you'd expect.
okay, but then I have to repeat the (when (= 1 1)
part like this,
(merge {:a "a"}
(when (= 1 1)
(when (= 2 2)
(if (= 3 3)
{:foo "bar"}
{:foo "nax"})))
(when (= 1 1)
(when (= 3 3)
(if (= 4 4)
{:zzz "bax"}
{:zzz "naz"}))))
is there a way I can achieve the same without doing it?a when
contains an implicit do
which will allow you to have side effects before returning the last value in it's body. So your when (= 1 1)
will be true, and then evaluate the when (= 2 2)
block for side effects and throw away the result, and then continue on to the when (= 3 3)
block and return the result. You could re structure the code to pass the result through. Maybe something like this?
(merge {:a "a"}
(when (= 1 1)
(-> {}
(cond-> (= 2 2) (assoc :foo (if (= 3 3) "bar" "nax")))
(cond-> (= 3 3) (assoc :zzz (if (= 4 4) "bax" "naz"))))))
or you could use a let
block to name some of the values so you're not repeating them?
(merge {:a "a"}
(when (= 1 1)
(merge ;; new to combine the two subforms
(when (= 2 2)
(if (= 3 3)
{:foo "bar"}
{:foo "nax"}))
(when (= 3 3)
(if (= 4 4)
{:zzz "bax"}
{:zzz "naz"})))))
{:a "a", :foo "bar", :zzz "bax"}
you’re familiar with merge
obviously. So I’m just using it to merge two maps. It’s the same strategy you’re using at the top level but at a lower level
There’s also
(apply merge [{:a "a"}
(when (rand-nth [true false]) {:b "b"})
(when (rand-nth [true false]) {:c "c"})])
;;=> {:a "a", :b "b"}

Hey Everyone, Need some help with Java Interop, Trying to write Clojure version of this class --> https://docs.amazonaws.cn/en_us/neptune/latest/userguide/access-graph-gremlin-java.html Mainly the Cluster and GraphTraversalSource. I also had a look at Orge, Tinkerpop library for Clojure. But Couldn’t find any examples to connect to remote Gremlin Server. Any help will be much appreciated. Thanks!
I don’t have the appropriate class to work with, so I’m just typing raw text, but this should be along the right path:
(ns your.nmspace
(:import [java.util.function Function]
[org.apache.tinkerpop.gremlin.driver Cluster]
[org.apache.tinkerpop.gremlin.process.traversal.dsl.graph GraphTraversalSource]
[org.apache.tinkerpop.gremlin.process.traversal AnonymousTraversalSource]
[org.apache.tinkerpop.gremlin.structure T])
(defn ^Function jfn
[f]
(reify Function
(apply [this arg] (f arg))))
(defn do-the-thing
[your-neptune-endpoint]
(let [builder (doto (Cluster/build)
(.addContactPoint your-neptune-endpoint)
(.port 8182)
(.enableSsl true))]
(with-open [cluster (.create builder)]
(let [^GraphTraversalSource g (doto (AnonymousTraversalSource/traversal)
(.withRemote (DriverRemoteConnection/using cluster)))]
;; Add a vertex.
;; Note that a Gremlin terminal step, e.g. iterate(), is required to make a request to the remote server.
;; The full list of Gremlin terminal steps is at
(-> g
(.addV "Person")
(.property "Name" "Justin")
(.iterate))
;; Add a vertex with a user-supplied ID.
(-> g
(.addV "Custom Label")
(.property T/id "CustomId1")
(.property "name" "Custom id vertex 1")
(.iterate))
(-> g
(.addV "Custom Label")
(.property T/id "CustomId2")
(.property "name" "Custom id vertex 2")
(.iterate))
(-> g
(.addE "Edge Label")
(.from (.V g "CustomId1"))
(.to (.V g ("CustomId2")))
(.iterate))
(let [^GraphTraversal t (-> g (.V) (.limit 3) (.elementMap))]
(.forEachRemaining t (jfn #(println (.toList %))))))))
Apparently, I have been out of Java for too long, because I don’t recognize the syntax of __.V()
. I figured the __
would be a variable in scope somewhere, but I can’t find it. However, the only thing I can see that has a .V()
method is the GraphTraversalSource, so I guessed it was that.
Some of this is going to use lots of reflection, which is why I brought in some type hints (there are one or 2 left though)
@U051N6TTC thank you! I’ll give this a try.
You might want to take a look at Koacha. It has such a feature. https://github.com/lambdaisland/kaocha
bin/kaocha --watch ✔ 2314 21:37:31
Execution error (FileNotFoundException) at java.io.FileInputStream/open0 (FileInputStream.java:-2).
--watch (No such file or directory)
calling it with arguments should work though, right? If I try calling without --watch I just get a clojure repl
I think there's an issue with how bin/kaocha
is set up in your project.
You might be missing the -m kaocha.runner
part
I copied it from the github readme, same error message when trying clojure -M:test advent_of_clerk/day_06.clj --watch
, but clojure -M:test src/advent_of_clerk/day_06.clj --watch
works (at least it runs the tests once, but then exits and doesn’t continue watching)
Right, I forgot we did it with an alias in the README
. Did you add the :test
alias?
I tried at least, did I maybe get something wrong in my :aliases?
:aliases {:nextjournal/clerk {:exec-fn nextjournal.clerk/build!
:exec-args {:index "src/advent_of_clerk/index.clj"
:paths-fn advent-of-clerk.index/build-paths}
:main-opts ["-m" "babashka.cli.exec"]}}
:test
{:extra-deps {lambdaisland/kaocha {:mvn/version "1.71.1119"}}
:main-opts ["-m" "kaocha.runner" "unit"]}}
:aliases
looks fine. is advent_of_clerk/day_06.clj
in your bin/kaocha
? You don't need to put any paths there. Test paths are handled by tests.edn
and you can use --filter
to select a particular namespace.
If you don’t want to move to a new test runner you could use lein Auto
https://github.com/weavejester/lein-auto
And run lein auto test
and it will run all your tests when the files change.
I normally use leiningen, so I’ll check it out next time, thanks! is there something similar for deps projects?
@U043ZD1K5TL I was a little unclear what you're saying about running clojure -M:test advent_of_clerk/day_06.clj --watch
. Happy to help further, but I think I would need the contents of bin/kaocha
or clarification that you're using the README
's version as-is.
@U01FJUDL57C thank you, the content of my bin/kaocha are the two lines described here: https://github.com/lambdaisland/kaocha#clojure-cli-toolsdeps