This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-28
Channels
- # announcements (6)
- # aws (8)
- # bangalore-clj (1)
- # beginners (249)
- # calva (27)
- # cider (5)
- # clara (8)
- # clj-kondo (11)
- # cljs-dev (14)
- # cljsrn (21)
- # clojars (1)
- # clojure (206)
- # clojure-europe (3)
- # clojure-greece (2)
- # clojure-italy (39)
- # clojure-nl (19)
- # clojure-spec (50)
- # clojure-uk (19)
- # clojurescript (31)
- # clojurex (24)
- # community-development (10)
- # core-async (32)
- # core-typed (4)
- # cursive (8)
- # data-science (15)
- # datomic (42)
- # figwheel (1)
- # fulcro (18)
- # graalvm (6)
- # joker (1)
- # kaocha (1)
- # nyc (1)
- # off-topic (1)
- # reagent (5)
- # reitit (2)
- # remote-jobs (2)
- # shadow-cljs (3)
- # spacemacs (2)
- # tools-deps (65)
- # xtdb (3)
I gotta go to bed, its 2am and I gotta run to work tomorrow! Hopefully I can figure it out tomorrow. Thanks everyone for your help, and good night 🙂
Got the REPL server running and connected. how to run the main.clj file ?
there are some keybindings listed in its package documentation here: https://atom.io/packages/chlorine
Is this where we register keybindings ?
Vim mode would be used if I were using vim as my editor. since I'm using Atom, I need non vim bindings .
I would imagine the keybindings are already hooked up. And vim refers to vim emulation in atom not vim the program
If the bindings are already hooked up, how to load and eval the file ?
Calling commands that Chlorine hasn't registered ?
Ran the Chlorine command "chlorine:load-file" manually.
It is a project folder. look in the top left corner of atom
that's an Atom "project" which is a different thing, I'm not sure what the proper term is in Clojure
basically it expects a certain directory structure to be set up, with e.g. a src/ folder and a project.clj file to declare your dependencies
if you just want to get up and running with the language without dealing with these things, I can recommend https://www.maria.cloud
I guess it would be just 'Clojure project'
Maria DB ?
@paulgureghian Did you install a build tool like Leiningen or Boot? It'll make setting up your project a lot easier. The Clojure tooling really does help with bootstrapping yourself.
Gonna try it with clj first.
Technically, Clojure can be used as a scripting language if you want.
Just not so many people want to for very short-running programs with Clojure/Java. I think a few more might do so with ClojureScript and/or joker.
Am I getting closer to making this all work ?
It takes you to the issue I opened. https://github.com/mauricioszabo/atom-chlorine/issues/75
OK, I looked at the source code of Atom... @paulgureghian Where is your cursor / which panel has focus when you try to load file
? The Clojure source file must be the active panel with your cursor in it. Otherwise Atom has no "current editor" and Chlorine can't load file
-- because your cursor isn't in a file.
In our long DM exchange, I specifically mentioned that you needed to have the cursor in the source file editor, not the REPL panel or elsewhere.
Hi guys quick question:
(->>
(reflect java.lang.Object)
(:members)
(filter map?))
I want to use the reflection API to get all the functions of a Java class, but I saw something werid:
Not sure what the hashtag means in this senario. In the code above, I even tried filtering out only map objects, but the hashtag thing still remained
#clojure.reflect.Method
Is there a name for these #something.something.something
, and why do they behave as if they are maps?
Thanks!;; The full answer I got was
(#clojure.reflect.Method
{:declaring-class java.lang.Object,
:exception-types [],
:flags #{:final :native :public},
:name getClass,
:parameter-types [],
:return-type java.lang.Class}
#clojure.reflect.Method
{:declaring-class java.lang.Object,
:exception-types [java.lang.InterruptedException],
:flags #{:final :public},
:name wait,
:parameter-types [],
:return-type void}
...
Those are Clojure records, defined with defrecord. They were designed to behave very similarly to maps.
They return true when you pass them to map?
, but they are not clojure.core/=
to regular maps. They have their own distinct types, and are immutable, and because they have a distinct type they can be used with Clojure protocols.
Hi, I have the following in my project.clj
:resource-paths ["resources/" "resources/symspell-1.0-SNAPSHOT.jar"]
it allows me to access the symspell library locally and works fine as long as I do lein run
or lein test
. But once I build the uberjar, it tells me that it can't find the classfile, how can I solve this?
not sure how exactly it relates to uberjar but if you want to use local jar you should install it into the local maven repo via lein install
the jar comes from a java project thought, not a clojure one, so I imagine I shouldn't install it with lein but with maven?
I was just trying to write a spec for my re-frame app-state and wanted to spec a Date. I found some code where someone used inst? for that, but I don't quite understand it. Doc says it validates if x satisfies Inst and Inst has just no documentation. I figure it means something like "Instant", i.e. "can be expressed as a timestamp" since Inst defines inst-ms* - is that correct?
I’m taking a quick look at the source code (https://github.com/clojure/clojure/blob/clojure-1.9.0/src/clj/clojure/core.clj#L6717), and it looks like the Inst
protocol is extended to at least java.util.Date
, and also possibly to java.sql.Timestamp
and java.time.Instant
, so if you have any of those three it should satisfy inst?
.
Yes, best to read the source I think.
Other libs may extend Inst
too: https://github.com/clj-time/clj-time/pull/249
That was very helpful indeed, I just never thought of grepping over core to answer such questions
That was very helpful indeed, I just never thought of grepping over core to answer such questions
Slack is having the hiccups today, my work Slack was double-posting things people typed too. Haven’t had any more instances since I restarted Slack at least 🤞
Annd of course Slack tries to double-post that one too, so I guess it must not be a client-side issue.
when creating protocols, do you find yourself using maps often? or do you try to be more specific?
I mean if I have a contract which has the parameters url
and id
would you send in a map instead? to make it more "Future proof"?
e.g
(defprotocol AmountCommand
(get-amounts [context])
(set-amounts [context]))
I don’t create protocols often, but that definitely looks like a good/idiomatic usage to me.
hi all, I have question about associative destructuring. I would like to pass the keys which I need to destructur as an input user vector.
basically, this works
(defn filter-event [{:keys [id type]}] (println (str "---" id "--" type )))
like one could select their own keyword for the data. It might be that destructing isn't the way to go there
destructuring is probably not what you are after. Think of each printed param as some function of the passed in collection. You could use a higher order function
(defn make-event-logger [id-fn type-fn]
(fn [c] (println (str "---" (id-fn c) "--" (type-fn c)))))
(def filter-event (make-event-logger :id :type))
defn apply-filters [user-f event])
(doall (map #((keyword %) event) user-f ))
(defn gh-filter-events [events-json]
(doall (map #(apply-filters user-filters %) events-json )))
Hi!
I am somewhat confused with async. I've got this re-frame handler
(re-frame/register-handler :request-it (fn [db _] (go (let [response (<! (request-all-from-db))] (prn (:status response) ) (prn (:body response))))))
that prints 200 and the expected map to console.
However when I run
(go (let [response (<! (request-all-from-db))] (:status response)))
the return-value is the actual channel. How is that?
If you want to do stuff with the response, it needs to be inside of that go block (or another one)
Well you're no longer inside the context of the original function. You'll need to dispatch another event with the response i believe. Let me try to find an example, I haven't done re-frame in a while
Eeh ... I am no longer within the context of the original function, because actually the go-block transforms into a callback chain?
It kind of does. I tried this but the error Error: No protocol method IAssociative.-assoc defined for type cljs.core.async.impl.channels/ManyToManyChannel: [object Object] seems to indicate that I am still dealing with a channel where I would expect to be dealing with the taken value: `(re-frame/register-handler :request (fn [db _] (go (let [response (<! (request-all-from-db))] (re-frame/dispatch [:process-response (:body response)])))))` `(re-frame/register-handler :process-response (fn [db [_ response]] (assoc db :data response)))`
Yup. I guess I was too preoccupied with being afraid of async to think clearly for a minute there. Thanks for bearing with me.
I have the feeling that clojure lacks a couple of functions that I'd like to see in the core library which have been left out to keep the core small as far as I understand. But I don't want to repeat myself over and over and I also don't want to create my own little personal dependency. What do you personally do about this?
I never stumbled upon one when I was searching for those functions of which I was sure they must exist.
For example map-update
which maps update
😄
In general, I feel like I'm having problems working with maps. I often have the feeling to repeat the same code patterns over and over for general map transformations and generating maps also isn't fun.
What exactly are you referring to?
Yeah, stuff like that. Is there any library you could recommend?
medley has a few things: https://github.com/weavejester/medley but not a lot.
That looks like a good start! Thanks
the older I get the less I like deps like that. I normally copy it out of my last project, or write it fresh. :man-shrugging:
We open sourced our little "Clojure extensions" lib https://github.com/worldsingles/commons/blob/master/src/ws/clojure/extensions.clj
I was forgetting a couple of other similar libraries, but then found that they are linked from the beginning of medley's README.
@linkerfelix I think once you've really internalized how Clojure works, you'll stop wanting map-<something>
and just treat map
as something you use to apply arbitrary transformation functions -- and you'll focus on those instead.
Yes, I also was asking because I had the feeling that I might be missing something about clojure.
The main options are: repeating yourself over and over, creating your own little personal dependency, using someone else's dependency, or petitioning to have them added to Clojure. The last one is the least likely to happen, so I hesitate to even mention it. The Clojure maintainers are very conservative about adding such things.
Stuart Sierra wrote about a similar topic https://stuartsierra.com/2015/08/10/clojure-donts-redundant-map
oh, and Sean's suggestion: get comfortable with small compositions of existing things, without having to give them names.
Yes! I'd be down for that. But for something like map-update
, I currently don't have such nice small compositions
What does map-update
even do tho'?
The thing I struggle the most with is transforming maps and creating new ones dynamically
Transforming hash maps -- reduce-kv
is often what I reach for.
(defn map-update
[m f]
(reduce (fn [m2 [k v]] (assoc m2 k (f v))) m m)
Won't reduce
have first m
as {}
i.e. empty map?
Something like this: (defn map-update [m f] (reduce (fn [m2 [k v]] (assoc m2 k (f v))) {} m)
Your option certainly is a bit cleaner but the semantics don't change. The result will be the same.
Call update
for all keys
think about threading the collection through successive assoc/assoc-in/update/update-in etc. for example
#(-> %
(assoc :foo "bar"
:bing "bam")
(assoc-in [:path :to :deeper] "baz")
(update :counter inc))
@crispin That's a good illustration for ->
but I don't struggle with such use cases.
(reduce-kv (fn [m k v] (update m k f)) m m)
-- but I don't find myself doing that very often so I'm curious as to why it seems like a "core" operation to you?
Well... because I do 😄 I often have maps with uniform data-types and I want to transform those step-wise.
Often, I first create a map from a list of keys where k
should be mapped to some (f k)
. That's not nice for me currently as well although zipmap
seems to be promising.
Interesting. Nearly all my hash maps are heterogeneous, rather than homogeneous. What is the domain you're working in?
I believe that map-update
above is often called map-vals
, and is in the medley library, and many others.
:thinking_face:
Can you use functions like maps?
I mean, if we wanted to be pedantic about it, one would say that maps are a generalisation of the concept of a function.
It's crazy to me that you can add gists as dependencies 😄 Thanks!
Something truly beautiful that tools.deps
allows us to do (I didn't realize you could have multi-file gists until I saw someone do that last year!).
these proposed answers are updating the val not the key clearly I misunderstood something
(we don't use those, I just knocked that up a year ago because someone was asking about map-vals
and map-keys
)
I dont get why you would create a map with values that are all some function of the key
that's not what's being done
update takes a key to know where to run the function
the function runs on the val
"Often, I first create a map from a list of keys where k should be mapped to some (f k)"
oh - then all the answers proposed are wrong
What @crispin sounds very appealing. I will think about whether I can update my code to make use of this because in the end he is very much right
That sounds like the best answer to me because all the time I had the feeling that I was doing something wrong.
Yeah, I knew that. But I will spend some time working more on functions than on maps. Thanks for the rubberducking (at)everyone 🙂
like sometimes I might have (def other-color {:red :blue :blue :red})
and use it like a function
I really like how all the collections are also functions. One that feels most elegant to me sometimes is using sets as functions
Quick dumb questions about Figwheel and repls. I use Atom text editor and have proto-repl up and running well. Getting into cljs
and figwheel
. Do I need two repls, one for figwheel and one for clj?
there's probably a way to avoid that, but it wouldn't make things better
two separate repls is the thing that makes the most sense
How do you go about sending code to the right repl?
I'm not sure how any of that works in atom
Look like Luminus thinks of that with some sidecar
stuff making the switch back and forth pretty easy.
Though I'm having some cider/piggieback
errors.
guys, I'm looking for a cheap/minimalistic way for passing encoded-data(json) to a sh
process which I lunch via clojure/sh.
are you asking how to generate json?
I have been thinking on following options: 1) env variable. 2) pass it as argument to shell
of clojure ( I think that :in
do it)
@noisesmith nope I have already json byte which i decode.
option 2 is the only one likely to break things in weird ways
because there's no quoting layer issues with env or files, there is with command arguments
there's also stdin (unless the process also has to read other input)
yep, I think it could read aother input.. 😞 by env. variable I was thinking if it might a problem if I pass to much data on it?
oh wait, do you mean clojure.java.shell/sh
?
if so, there's no quoting issues, just make it an arg
there's also a clojure
command you can run in shell scripts, I probably got it mixed up
clojure.java.shell/sh doesn't run sh - it directly does a process invocation without using a shell
(confusing name)
so it doesn't do globbing / interpolation as a shell would, which means no escaping needed for args
There are length limitations on the command line, and probably for env variables, that are higher if you use a tmp file instead, but maybe the size limits on command line args is high enough for your use cases.
I hacked a little with stdin and sh but it has some limitations. In theory I want to give the possibility to user to create their own clients with some data .
Looks like the Slack servers are up again.
Anyone here ?
Is this primed correctly for running / evaluating the code ?
@paulgureghian Yup, the load file operation completed -- the REPL shows the result of the last form evaluate, in this case the defn
of -main
(whose result is the Var name). Yay!
Now you can type code into your main core.clj
file and evaluate each form into the REPL!
How to eval and output the "I dont do a whole lot ... yet" ?
I thought it was supposed to also output to the terminal ?
I am not sure this would work, but if you typed in a form (-main)
and evaluated it, I think it should cause the function -main
to be called. Where the standard output goes to in the Atom environment, I do not know.
Note that typing such a (-main)
form into your core.clj
file and leaving it that way is probably a bad idea, because then loading the file itself would cause the function to be called. Often people will have a block of text at the end of a Clojure source file like this:
(comment
;; forms here that I sometimes like to evaluate during interactive
;; development, but do not want to be evaluated when I load this file.
(-main)
)
Does the spoken text part get eval'd and outputted ?
If you mean the lines that begin with ;;
, all text after ;
up to the end of the line are comments in Clojure.
No, not the comments. the stuff between " "
If you cause the function -main
to be called, it should execute the println
calls, which should cause output to appear wherever standard output is configured to go in your setup. I don't know where that is in your Atom environment, as I haven't used Atom.
What do you use ?
I thought since I have the REPL server in the terminal, it would output println there.
I am a becoming-a-greybeard who uses Emacs and vim (and vi before vim existed), and have such muscle memory for them that it will take some odd occurrence to make me seriously consider switching, but that doesn't mean I would recommend it for someone learning Clojure.
Did you try typing in (-main)
and then put the cursor just after the )
in that, and then I assume there is some menu item for your Atom setup that "sends this form to the REPL and evaluate it" (or some similar words)?
Change the cursor position in the "chlorine REPL tab or the core.clj tab ?
Sorry, AFK for a while there. Maybe even more directly, if you click in the REPL tab and type (-main)
and enter that, it should call the function, and maybe you see the standard output in that window.
That should hopefully answer the question of where standard output goes in your setup.
But for long term development, it is highly recommended that you type forms into a file, like the (comment ...)
part of the file core.clj that I mentioned earlier, for long term saving of things that work, and because often when trying things out interactively you find you want to make a small addition or modification to something you evaluated earlier.
I thought that just by having the repl server it would show there as well.
I can't tell you where it will go, as I do not know. Have you tried it and seen what happened?
Your computer won't break.
@andy.fingerhut No, Chlorine's REPL panel is readonly -- you do not type into it.
Ah, my bad. Sorry for being misleading there. I should listen when it comes to Atom, rather than suggest 🙂
If your cursor is just next to either parenthesis in (-main)
in the source code editor then "evaluate block" will run that function (using ctl-, b
if you followed my advice to set up the keymap bindings).
But you type expressions into your source code -- and Andy's recommendation to put exploratory code inside a (comment ...)
form is a good one.
Are those key-map bindings part of the deps-edn or the files and folders in your repo ?
The keymap bindings from the Chlorine package page, that you can install in Atom. I explained how to do that yesterday.
Specifically I said to use the second set of key bindings shown (i.e., not the vim ones, which are listed first).
If you bring up the Atom command palette and type keymap
, you'll see Application: Open Your Keymap
You should be able to copy'n'paste the Chlorine key bindings from the Chlorine package web page (on http://atom.io) into that file at the end, then save it -- and they should take effect immediately.
ok. ill do that. im using the load command and its working, but its outputting to the editor and console. i thought it was also going to show in the terminal as well ?
No, the Terminal REPL is just to get the Clojure process started for Chlorine (although you can play with code in the Terminal REPL outside Atom/Chlorine if you really want).
ok. things are starting to come together now.
I just gotta find clojure stuff to put in core.clj and eval it ?
the bindings from the atom io page has a duplicate and its faulting on the copy paste. can i use a different key-value pair ?
Just remove the duplicate and save the keymap. ctl-, c
-- I'll let Mauricio know.
I submitted a pull request, to change source-for-var
to be bound to ctl-, S
instead. Thanks for catching that!
I have already caught two issues in atom - chlorine
Beginners try stuff that more experienced folks know not to do 🙂
When can I refer to myself as a Clojurian ?
😆 Whenever you feel like it -- you've become a familiar character on this Slack already!
Some good peeps here
Clojure folks are enthusiastic and like to help more folks become Clojure folks.
I am already a Ruster, Gopher, Pythonista, Javer, and now a Clojurian
Just hit the 'ctrl' key then the 'f' key to load file ? doesn't seem to work
All of those key bindings are control-comma then the letter: two separate key presses -- first control + comma together, then release, and then press whatever character is next. That's what ctl-, f
ctl-, b
mean.
OK, I should be listening not typing right now, but for most IDEs at least the definitions of which keys do what in the IDE are in an IDE-specific file, in this case an Atom-specific file. Unless your IDE was actually implemented in the Clojure programming language, they wouldn't be inside of a deps.edn or Clojure source file.
Yeah. I gotta get my hands dirty with the keybindings
Would VSC also need keybindings or can I use its run button ?
I don't know VSC. Does your Atom setup have any menu item anywhere with a description similar to "evaluate block"?
When your cursor is in the source code editor.
Lets see...
I am betting there are a bunch of menu items, but perhaps the ones specific to Clojure are grouped together somewhere.
Nothing. I need to do the binding stuff. or use that Clojure specific IDE
You are right. I found the Chlorine commands.
If one has a name similar to "evaluate block", then if you move the cursor in the source code editor panel to just after a form like (-main)
, or any other expression you want to try to evaluate, and then select that menu item, it might work. The part that I do not know is whether it is important for the cursor to be just after the code you want to evaluate, or somewhere inside of it. Just after is a guess on my part.
thanks
https://clojure.org/reference/compilation When it says "without source" can someone elaborate on what that means? Source files? Wouldn't those be a jar/.class files?
right, if you want to deliver an application without source, you need to aot compile and ship the resulting class files
Or a .clj file
the clj file is the source
and yeah, usually you'd put the class files in a jar, but you don't technically need to
@paulgureghian I mentioned a day or three ago that Clojure compiles each expression just before executing it, and normally the compiled result goes in the running JVM process's memory only, not written to the file system. drewverlee is asking about the capabilities that Clojure has, not needed by everyone, to actually write JVM byte code files to the file system.
It is possible to use Clojure in a deployed application without ever using this capability, if you deploy Clojure source code instead, and have it compiled shortly after the JVM process begins.
So packaging as a jar file or not is on a separate axis from producing class files or not
@paulgureghian I was wrong on another of my guesses about Atom earlier. The Chlorine package does not create any Clojure-specific items in the menu. Creating the key bindings is recommended. If you haven't done that, I now know the steps for how to do it.
I think I'm good on that front. lets see ...