This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-08-15
Channels
- # announcements (1)
- # beginners (101)
- # boot (13)
- # cider (38)
- # cljdoc (10)
- # cljs-dev (37)
- # cljsrn (6)
- # clojure (74)
- # clojure-dev (8)
- # clojure-europe (3)
- # clojure-italy (36)
- # clojure-losangeles (2)
- # clojure-nl (5)
- # clojure-spec (15)
- # clojure-uk (49)
- # clojuredesign-podcast (2)
- # clojurescript (52)
- # cursive (6)
- # datomic (19)
- # fulcro (35)
- # graalvm (16)
- # graphql (4)
- # kaocha (1)
- # leiningen (26)
- # luminus (3)
- # re-frame (10)
- # reagent (14)
- # ring-swagger (37)
- # rum (2)
- # schema (4)
- # shadow-cljs (148)
- # spacemacs (13)
- # specter (1)
- # sql (46)
- # tools-deps (3)
- # vim (4)
I'm slightly confused by namespace, specifically ns-all. I put a dependency on my project.clj for lein, I would expect ns-all to show some namespace corresponding to the dependency, but it doesn't? Is ns-all (and dir) the correct way to know what namespace/functions are available to me? Many thanks.
I think I mean all-ns actually! :)
Hi, I am new to clojure, can someone suggest me link/blogs to learn how to write tests in clojure.
@markgdawson ns-all shows the namespaces that are currently loaded, usually via require
, in your current session. It does not show what is available. For that the best way is to look at the documentation for the package for what it recommends require'ing, or if the source is available, examine that for the namespaces available.
Thanks @andy.fingerhut, that's very useful. On a side note, are you able to enlighten me on what the :require line in project.clj actually is? Is this a label for the package on some central repository? Or does it have any relationship to the source code as it is on disk? I often that it's hard (or impossible?) to predict the likely namespaces from the :require line, which seems to be an odd inconsistency to me....
Maybe it's just that I'm new to clojure and there's a lot to take in for a beginner compared to some other languages I've used! đ
I am not sure what you mean by the :require line in project.clj, as I don't recall seeing one that has that.
To find out what libraries exist and are useful, ask places like here for what kind of functionality you are looking for, or there are web pages with some lists of useful libraries. (I will find a link to one in a minute here)
To find out what namespaces are in a library, again, look at the README for the library to see if it recommends require'ing one (or several), and what functions or macros are intended to be useful to you.
https://www.clojure-toolbox.com is one list of Clojure libraries, by category
Thanks @andy.fingerhut, it's great to have support as someone starting out. I looked into the source code, and found the ns headers and that worked. Quite simple when you know how đ
Another silly question (sorry!). The brave clojure book describes namespaces as labelled shelves with functions in them. It seems a very simple mental model, does this mean that in theory two libraries (if we're not careful) could be unwittingly dumping functions into the same namespace? I've tested it and it seems (to me as a beginner) to behave just like that.
Yes, two libraries could easily include the same namespace names. People tend to try to avoid that by picking a short prefix that is unique, and naming other namespaces as suffixes of those.
Just as two Java, Python, Perl, etc. libraries could use the same names for packages/namespaces/whatever-the-language-calls-them, and that would not be useful to do.
Sure, OK. Thanks again @andy.fingerhut đ
you are welcome
Let's say I have an if
expression that returns true. In the true part, I want to eval a series of functions that write into different tables in a db, one after the other. They don't eval to anything (well, I suppose, they eval to nil. Would a do
form be sufficient, or is there a better "wrapper"?
This is the only way inside an if
branch. Do note that there are many functions that create an implicit do
, like when
, let
and defn
. In those cases you can do side-effects without adding a do
.
(if (some-truthy-evaluation)
(do
(write-into-table-1)
(write-into-table-2)
(write-into-table-3))
(log/info "oh nooooos"))
Nope, nothing better. Thatâs one of the main things do
is designed for.
The only caveat would be to think about whether, in context, it would make sense to pull those writes out into a update-tables
function so you can do
(if (something?)
(update-tables)
(log/info "Whoops"))
Sometimes that makes for more readable/maintainable code, because the function name serves as a kind of âexecutable documentationâ for what youâre doing.
Heh, I donât actually follow that convention very often.
and a side koan to ponder - why does using do
in an if
mean side effects must be involved?
Ok - noob here, I'll bite. Since do
only returns the value of the last expression in the list, if the other expressions are pure functions with no side effects, there's little point to them being there. This would seem true regardless of if the do
is in an if
or not.
Thatâs what Iâd say too.
right, I just always think that's an interesting observation to come across, esp if you're not coming from fp
Silly question....in what cases are side-effects not some kind of mutation?
so purely on concept, and ignoring any terms + any implications that might come along with certain terms,
the "mutation" i was referring to was more about the style of "immutable values" that Clojure has. {:last "Doe" :first "Jon" :age 40}
That map can't be mutated in Clojure. You can stick the map into an atom, then swap! updated values into the atom. So that's the typical kind of "mutation" that can happen in Clojure, and that's the kind of mutation that the bang !
is used to warn against ------ at least this was my impression. Caveat: I'm a Clojure noob.
So yes, sticking some (prn ...)
statements in a do
technically causes side effects, and side effects by definition mutate something in the universe. But they don't mutate Clojure values.
Yeah, I assumed that was the implication. I'm not arguing with what you said, just thought it was an interesting statement. Cavear: also a noob.
I read the exclamation mark as "do not use inside an STM transaction (like inside swap!)", not that it has side effects. If it has side effects, but is safe to use inside a swap! (like an idempotent operation) I leave the bang off.
the bang convention isn't really a thing, most people use it to indicate side-effects but there's no strict rule
even agents are more "aware of" than "involved in" transactions, it's primarily refs
Hey! So I asked in re-frame
but maybe its not typically a re-frame question.
Does anyone have any idea on how to take the user to a different page without using href links? So I have an event that retrieves data from a server, and I want to send the user to the page the data corresponds with.
(rf/reg-event-fx
:post-submission-success
(fn [_ [_ response]]
(let [postid (:new-post-id response)]
(if (pos? postid)
(do
(println "Submitted post: " postid)
;; @TODO: Send user to /posts/<id>
{:dispatch
[:new-notification
[ "Post submission successful!"
""
"is-success"
"fa-file-check"]]})
...
I'm using re-frame-routing
to handle changing the app's appearance when the URL changes, but now I want to force navigate the user when postid
is valid, and take them to the post they just submitted. Any ideas? Using reagent and reframe đa common thing is to use https://google.github.io/closure-library/api/goog.History.html to manage navigation and history
if you are using cljs, all of goog is available by default
yeah I've seen a lot of goog in my error messages
I can imagine this means going forwards and backwards through your history
and also sending the user to a new URI under the same parent
(while also adding the item to your history etc.)
is that new history
as in, adding to your new history list and as a side effect taking you to the new item?
I'm realizing we attached the history object to the page to capture navigation (so that the back / forward buttons would work) that wasn't what did the actual navigations
@ashley correcting myself: the way you make the navigation happen is to mutate window.location.href
if you initialize a goog.History object you can do other nice things so your app doesn't seem broken to the user
ah I see! Well allow me to correct myself too, I'm using re-frame-routing
but thats built on top of bidi
, so I'm not looking to see if bidi
offers anything similar to what you're talking abotu
bidi watches window.location.href
I was under the impression a router was about matching routes to pages and it wasn't able to control the URL bar itself
changing it triggers bidi
does bidi
/ any router change the URL bar? Is it the job of the router?
no, the url bar makes bidi run
I'm still kind of learning the roles of these packages and their alternatives, still learning the ecosystem
okay, so what I'm looking to do is most likely not a function of bidi
the big picture is that your code (or a user, by typing or pushing a button) can rewrite the href in the window bar, bidi is automatically called when that happens, it uses its router to pick some js to run (which is code you wrote, you can make it do whatever to reflect the new location)
if only the part after an optional #
is changed, this all happens without needing to load anything from the server, the html spec says that part of the URL is only for things local to the page view
okay gotcha, so how would oyu go about mutating window.location.href
, is it trivial or does it require another package?
if anything before # changes, you can override it in hacky ways, but otherwise you are loading a new page from the server, and all js runs from your main again
@ashley this is probably the best description of the API - it's doable without any other libs
it's an object that's basically a string, you overwrite it and it makes the browser navigate
okay, I'll do some searching as to how I actually do this
oh did I mention the api but not link it- here https://developer.mozilla.org/en-US/docs/Web/API/Window/location
I need to learn how to do this with clojurescript though đ
im browsing /js
to see if its in there somewhere
the interop to adapt those examples should be simple
yeah, I think you're correct
interop only seems hard if you haven't used it IMHO, I'd make an exception for concrete inheritance in clj, but that doesn't apply in cljs world
you can use simple classes that are nearly data (like Date) to get a feel for it
@noisesmith this is very easy and I can't believe something so powerful has only just come to my knowledge, thank you!
haha, glad it's working out
it opens up a lot of possibility to be able to use all of js / js libs - though in some rare cases you really do want a proper wrapper
in my experience people use wrappers more than it's really needed
I guess the only thing I can ask, is that my app switches pages instantaniously when clicking href links, but because this function is changing the URL bar the webpage seems to reload. I imagine there's not much I can do about this but I guess I'd ask haha
hmm... - if you adapt your app to use the "fragment" for all navigation (only changing past the optional #
), then it doesn't need any reload, it just triggers your router
but there could be multiple things going on, really depends on how you app works
yeah - I'm not using jump links as I want my URL bar to look like a normal website. I think with reframe routing
the term pushy-init
allows for the changing of the URL bar without reloading
to be honest its only a minor inconvenience in this case but it would be nice to have that consistent, no load time feel đ
the one cljs app I really developed in anger we did everything via fragment routing, so I can't provide any more info personally
(defn- pushy-init
[routes]
(fn [_]
(let [history (pushy/pushy #(re-frame/dispatch [:router/set-route %])
#(bidi/match-route routes %))]
(listen-for-navigation! history)
(pushy/start! history)
(re-frame/dispatch [:router/initialized]))))
I found this inside the sourcecode for @oconnâs re-frame routing if this helps?Yeah don't worry thank you for your help with everything else!
@ashley https://github.com/oconn/re-frame-routing/blob/master/src/re_frame_routing/events.cljs#L69 I think this event will help you with what youâre looking to do (navigating from effects / events)
I'm afraid I don't quite understand what the function does from the source code does, but do I just :dispatch [:router/nav-to "/post/whatever"]
Thank you!! I wish I had gone through the source code earlier
I was going through bidi but didn't realise you had a nice solution
SOLVED. command in tutorial is
boot serve -d target
but boot serve -d target wait
must be used.
---
Hello. I'm going through modern-cljs tutorial no. 2 https://github.com/magomimmo/modern-cljs/blob/master/doc/second-edition/tutorial-02.md
Jetty stops right after it is started without my interference. Has anyone experienced this behavior? What am I doing wrong? I'm new to all, java, clojure and cljs so except solution, I'm also interested in how would one debug this.
$ boot serve -d target
2019-08-15 22:43:57.585:INFO::clojure-agent-send-off-pool-0: Logging initialized @6570ms
2019-08-15 22:43:57.622:INFO:oejs.Server:clojure-agent-send-off-pool-0: jetty-9.2.10.v20150310
2019-08-15 22:43:57.644:INFO:oejs.ServerConnector:clojure-agent-send-off-pool-0: Started ServerConnector@11f4bbdb{HTTP/1.1}{0.0.0.0:3000}
2019-08-15 22:43:57.645:INFO:oejs.Server:clojure-agent-send-off-pool-0: Started @6630ms
Started Jetty on
Stopping Jetty
2019-08-15 22:43:57.660:INFO:oejs.ServerConnector:main: Stopped ServerConnector@11f4bbdb{HTTP/1.1}{0.0.0.0:3000}
My build.boot follows. Please let me know which files / logs / cmd outputs could be helpful, so I can provide.
(set-env!
:source-paths #{"src/cljs"}
:resource-paths #{"html"}
:dependencies '[[org.clojure/clojure "1.7.0"]
[adzerk/boot-cljs "1.7.228-2"]
[javax.xml.bind/jaxb-api "2.3.1"]
[pandeiro/boot-http "0.8.2"]
[org.clojure/tools.nrepl "0.2.12"]])
;; makes cljs task visible to the boot command
(require '[adzerk.boot-cljs :refer [cljs]]
'[pandeiro.boot-http :refer [serve]])
$ boot -V
#
#Thu Aug 15 22:51:06 CEST 2019
BOOT_VERSION=2.8.3
BOOT_CLOJURE_VERSION=1.7.0
BOOT_CLOJURE_NAME=org.clojure/clojure
$ java --version
openjdk 12.0.2 2019-07-16
OpenJDK Runtime Environment (build 12.0.2+10)
OpenJDK 64-Bit Server VM (build 12.0.2+10, mixed mode)
edit: format