This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-04-10
Channels
- # announcements (2)
- # babashka (20)
- # beginners (381)
- # calva (16)
- # chlorine-clover (21)
- # cider (1)
- # clj-kondo (18)
- # cljs-dev (107)
- # cljsrn (2)
- # clojure (161)
- # clojure-dev (5)
- # clojure-europe (2)
- # clojure-losangeles (3)
- # clojure-nl (3)
- # clojure-uk (35)
- # clojurescript (22)
- # conjure (48)
- # cursive (8)
- # datascript (11)
- # datomic (6)
- # figwheel-main (10)
- # fulcro (85)
- # hoplon (112)
- # jobs (1)
- # kaocha (5)
- # luminus (5)
- # malli (1)
- # off-topic (96)
- # onyx (1)
- # pedestal (1)
- # perun (1)
- # reagent (5)
- # reitit (1)
- # shadow-cljs (34)
- # specmonstah (1)
- # sql (6)
- # tools-deps (3)
- # xtdb (23)
is there a version of pr-str
that emit full versions of qualified keywords in maps instead of short forms? Something like {:foo/bar 1}
instead of #:foo{:bar 1}
That can be controlled with https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/*print-namespace-maps*
I need to debug some edn and it's impossible to jump to the desired keywords if they're in the short forms
Does anyone happen to have a good way of getting the path to a file relative to another file?
works wonders
(def foo ( "/var/tmp/foo.txt"))
(def parent (.getParentFile foo))
(def sibling ( parent "bar.txt"))
(def sibling2 ( foo ".." "bar.txt"))
(.getCanonicalPath sibling2) ;; "/private/var/tmp/bar.txt"
(.getCanonicalFile sibling2) ;; #object[.File 0x1d74ad00 "/private/var/tmp/bar.txt"]
(def multiple-levels ( parent "abra" "cadabra" "log.txt"))
(.getAbsolutePath multiple-levels) ;; "/var/tmp/abra/cadabra/log.txt"
could this be helpful too? https://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html#relativize(java.nio.file.Path)
Hmm, I'm not sure I understand phronmophobic. There already exists two files in the filesystem and I want to calculate a path from one of them to the other. But that http://java.nio.fi
how to explain this line https://github.com/richhickey/clojure/blob/04764db9b213687dd5d4325c67291f0b0ef3ff33/src/clj/clojure/core.clj#L184 Is it some sort of recursion?
Also, FYI this is not the official Clojure source, which is at https://github.com/clojure/clojure
Execution error (ClassNotFoundException) at http://java.net.URLClassLoader/findClass (URLClassLoader.java:382). com.braintreegateway
IIRC Clojure doesn't have a direct analog to import x.*
. You will have to provide each class' name.
(import '[com.braintreegateway BraintreeGateway])
(import 'com.braintreegateway.BraintreeGateway)
(import [com.braintreegateway BraintreeGateway])
Nothing worksWorks for me. Are you using it by itself or in an ns
form? Are you sure you have added the dependency to wherever you add dependencies?
doesn't work == what happens?
Ahh, Braintree integration. Much fun lies ahead. You will probably need this subset for a reasonable minimum:
(:import (com.braintreegateway
BraintreeGateway Environment Result
ClientTokenRequest CustomerRequest AddressRequest PaymentMethodRequest SubscriptionRequest
SubscriptionSearchRequest
Subscription
Subscription$Status
WebhookNotification)
Using deps.edn, how can I access resources of a dependency library. Say I have project-a that has {:deps {project-b {:local/root "/my-projects/b"}} :paths ["src", "resources"] }
When running project-b in a repl it has access to files in resources
of its directory, but when running repl with project-a, project-b will not be able to access its own resources
.
it should be able to
all :paths of dependency local libs should be on your classpath in a
if you do clj -Spath
you should see it in there
@alexmiller Thank you, you're right. I'm not sure what went wrong before, I'm using cider, but now it's there too.
trying to swap! a map into an empty atom but get trailing nils.
user> (def foo (atom {}))
user/foo
user> (swap! foo assoc {:a 1 :b 2})
{{:a 1, :b 2} nil, nil nil}
assoc takes keys and values, not a map. you're using it like merge which does take a map
(swap! foo assoc {:a 1 :b 2}) doesn't compile for meā¦
ā¦but (swap! foo assoc :a 1 :b 2)
does the job.@dgonsalves22 what you want to do seems more like reset!
than swap!
e.g. (reset! foo {:a 1 :b 2})
(swap! foo merge {:a 1 :b 2})
and
(reset! foo {:a 1 :b 2})
both worked for me. Thanks guys
@dgonsalves22 note that reset!
will overwrite, if foo contains something important your merge version will be better.
@bbss Iām glad I have both of those to work with because im still not sure whether I want to be overwriting every time or not.
I mostly use reset!
when I don't care about the state being lost anyway (or explicitly want to clear it) often in clojurescript when reloading re-running some parts. swap!
is usually what you want I'd say.
Can you recommend articles on how to structure Clojure programs? Both in the small and in the large. My programs always become such a mess.
In my experience (20+ Clojure apps, small and big-ish) things like Component are incredibly helpful to separate "application" structure from the biz logic
@U08716WQP If you like, you could post a github link to your code, and I can leave some comments when I have time.
Interestingly enough - I cannot recall many articles about structuring Clojure applications
I donāt know of any great articles on it. The best general advice I could give is: Flatten your logic. Stop creating functions.
@U07S8JGF7 Iām intrigued. What do you mean by stop creating functions?
But itās very important that every name you introduce carries a cost: the cost of remembering what it means. Clojure often allows you to be so concise, that inlining those functions is both more precise and less overhead.
When you stop creating nested function calls, your logic naturally gets pushed to the top level.
Again, this is the opposite of a lot of OOP advice. But when youāre dealing primarily with immutable values, longer functions become easier to manage.
Because, for example, you cannot silently tweak state on line 27 that affects a switch on line 124.
hereās an example: https://github.com/potetm/advent-of-code/blob/master/src/advent_2019/day_5.clj#L15-L106
But I heard multiple people complain about this state machine during advent of code, and, for me, it was extremely easy to make changes because all of the logic was bundled together.
Note that I could have broken this up and used multimethods or something. But 1. the op codes are a closed set and 2. that would have required figuring out how parse a bunch of values and pass them into the multimethod.
You can avoid all those problems by cheating: Just putting everything you need in one scope.
@U07S8JGF7 I wouldn't have thought to ask this question, butI like appreciate this insight - thanks
regarding the organization of clojure code in general, I know of nothing better than Elements Of Clojure https://leanpub.com/elementsofclojure
Elements of Clojure does a good job of putting words to this. I hesitate to recommend it because itās so abstract I think it would be hard to understand if you donāt already have a pretty good idea.
Interesting thread. I am at a stage where I'm re-designing my application for the 5th or 6th time, as I discover new better ways to structure the code. One interesting thing I found is that the split into layers (UI, Application, Business Logic, Infrastructure) doesn't work that well. Specifically, Business Logic (which I call Domain) should not be a "layer" above infrastructure, but something entirely separate, because it is useful both in server-side Clojure and client-side ClojureScript.
But I'd love to read some books about designing large systems with Clojure. I recently read "Domain-Driven Design" by Eric Evans and found out that I've been practicing Domain-Driven Design all these years. Good ideas in that book, although it gets somewhat mired in the object-oriented tarpit.
Well, any efforts to sneak Clojure into our Scala shop probably went out the window with this tweet being passed around: https://twitter.com/jamie_allen/status/1248019842877145089
Itās one person whoās obviously very, very biased talking about his own feelings. No reason to count it as anything more than that.
Is he really joking? If so, it went over my head, lol. And pleasantly soā¦.
are you saying typing has no tradeoffs? :)
True, but that led to an article by a scala āheavyā who I respect, Haoyi, so I didnāt want to dismiss it out of hand.
Clojure is getting updates though, which seems like the opposite of "dead", and although I'm not looking at them now I remember the stack overflow stats being favorable. Also lisps don't tend to be mainstream, but that doesn't make them less useful š¤·
Reports of Clojure's death are common, and false :)
Itās the exact same as when a gamer claims that some other game is dead. People are playing the game. People are enjoying the game. The statement says more about the speaker. Itās both a feigned superiority and an attempt to reassure themselves that their decisions are The Right Decisionsā¢.
I know Jamie, and he knows better than this
We all do this. To be absolutely clear: nothing I said was an attempt to say, ānever listen to him,ā or āhe is bad.ā
When using defspec
from test.check is there a way to cleanup after the tests have run? I can wrap my props/for-all
in a let
for setup, not sure how to cleanup though.
If you use test.chuckās checking macro (https://github.com/gfredericks/test.chuck#alternate-clojuretest-integration) you should be able to use normal clojure.test fixtures
Nice, yeah I was thinking of using a fixture but good to know that it doesnāt work out of the box
I'd be surprised if it doesn't work out of the box
what is even being mreasured in this graph?
alternative source: https://snyk.io/blog/kotlin-overtakes-scala-and-clojure-to-become-the-2nd-most-popular-language-on-the-jvm/
"For this survey, we teamed up with conferences and communities across the JVM ecosystem" - an incredibly biased data source.
I'm a bit confused here. Given these definitions:
(defrecord langStr [s tag]
Object
(toString [_] s))
(defmethod print-method langStr
[literal ^.Writer w]
(.write w (str "#langStr \"" literal "@" (:tag literal) "\"")))
This works as expected:
> (def gaol (langStr. "gaol" "en-uk"))
gaol
> (prn gaol)
#langStr "gaol@en-uk"
>
But in the REPL:
> gaol
{:s "gaol", :tag "en-uk"}
>
Two questions:
- What function/method is serving as the 'P' as REPL?
- How can I get it to be equivalent to prn?the repl doesn't use to-string, it uses the system underlying prn
, which is based on a multimethod
iirc `*print-method*` but it shouldn't be hard to verify
yeah, print-method
(ins)user=> (source pr)
(defn pr
"Prints the object(s) to the output stream that is the current value
of *out*. Prints the object(s), separated by spaces if there is
more than one. By default, pr and prn print in a way that objects
can be read by the reader"
{:dynamic true
:added "1.0"}
([] nil)
([x]
(pr-on x *out*))
([x & more]
(pr x)
(. *out* (append \space))
(if-let [nmore (next more)]
(recur (first more) nmore)
(apply pr more))))
nil
(ins)user=> (source pr-on)
Source not found
nil
(ins)user=> (source clojure.core/pr-on)
(defn pr-on
{:private true
:static true}
[x w]
(if *print-dup*
(print-dup x w)
(print-method x w))
nil)
nil
usually you want to override both print-method and print-dup
So print-dup is being called when I use the REPL rather than the print-method I've defined?
you didn't define print-method, you defined toString
I didn't read carefully
OK, so here's the complete definition:
(defrecord langStr [s tag]
Object
(toString [_] s))
(defmethod print-method langStr
[literal ^.Writer w]
(.write w (str "#langStr \"" literal "@" (:tag literal) "\"")))
(defmethod print-dup langStr [o w]
(print-method o w))
(defn read-langStr [form]
(let [langstring-re #"^(.*)@([-a-zA-Z]+)"
m (re-matches langstring-re form)
]
(when (not= (count m) 3)
(throw (ex-info "Bad langString fomat"
{:type ::BadLangstringFormat
:regex langstring-re
:form form})))
(let [[_ s lang] m]
(langStr. s lang))))
Plus I have
langStr defined in my data_readers.clj
But when I evaluate it I still get the original reader defined for a defrecord:
> #langStr "jail@en-us"
{:s "jail", :tag "en-us"}
@alexmiller is there something else I need to do to override the defrecord print-method?
Youāre using langStr there - might want to check thatās evaluating to the full class?
In the dispatch value
Well my data_reader has this clause:
langStr ont-app.sparql-endpoint.core/read-langStr
Data readers switch on the tag symbol
Printing switches on Java class
def jail #langStr "jail@en-us")
#'ont-app.sparql-endpoint.core/jail
(class jail)
ont_app.sparql_endpoint.core.langStr
Also ont_app.sparql_endpoint.core.langStr shows up in the output from (methods print-method)
I tried this:
(prefer-method print-method langStr clojure.lang.IRecord)
Execution error (IllegalStateException) at ont-app.sparql-endpoint.core/eval13294 (form-init4216778243462303189.clj:139).
Preference conflict in multimethod 'print-method': interface clojure.lang.IRecord is already preferred to class ont_app.sparql_endpoint.core.langStr
So there's just no way to get the REPL to print a defrecord except as {<k> <v>, ...} ?
Ah. Sure 'nuff deftype fixes the problem
Thanks guys!
you can totally do this with defrecord - you may need to add a prefer-method though
$ clj
Clojure 1.10.1
user=> (defrecord Rec [a])
user.Rec
user=> (prn (->Rec 1))
#user.Rec{:a 1}
nil
user=> (->Rec 1)
#user.Rec{:a 1}
user=> (defmethod print-method Rec [^Rec r ^.Writer w] (.write w ^String (str (:a r))))
#object[clojure.lang.MultiFn 0x5b022357 "clojure.lang.MultiFn@5b022357"]
user=> (defmethod print-dup Rec [^Rec r ^.Writer w] (print-method r w))
#object[clojure.lang.MultiFn 0x6ceb7b5e "clojure.lang.MultiFn@6ceb7b5e"]
user=> (->Rec 1)
1
user=> (prn (->Rec 1))
1
nil
Anyone here who uses intellij with shadow-cljs? It seems that my cursive plugin doesn't work with shadow-cljs. Anyone know how to fix this?
I got it working a while back by using deps https://shadow-cljs.github.io/docs/UsersGuide.html#deps-edn
so just moving dependancies to deps.edn will make cursive work again?
The problem I had was that cursive doesn't recognize shadow-cljs.edn
as a project configuration file. It does recognize deps.edn so if that's the problem it might fix it. Otherwise I suggest bringing up the question #cursive
Ah I see! Ok I will check it out! Thanks!
Unfortunatly it doesn't work. š I am just getting this: https://gist.github.com/ShakoFarhad/4b73a62b2ed1dfe054473faa12d6e67e
@U0121V7FXG8 The Shadow documentation has a section on how to work around this: https://shadow-cljs.github.io/docs/UsersGuide.html#_cursive
I am getting this problem: https://gist.github.com/ShakoFarhad/39ab6314891431f540e2ccbac2c351d7 It talks about the http://java.erxe not being found. It is weird because it is at the given path. Nothing is missing. :s
This is how my project.clj file looks
And this is the shadow-cljs.edn file
do you have a package.json
with the same version of shadow-cljs installed into node_modules
?
I will just keep using shadow-cljs and keep updating the project.clj file whenever I make a dependancy change in shadow-cljs.edn. That way cursive will keep working and I can still use shadow-cljs for building. It is perhaps a bit inefficient to keep two files up to date with one another, but at least everything works now š
I fixed it! Apparently I needed a specific version of jdk. I had 13.0.2 but it complained about not finding 13.0.1. So I installed 13.0.1 and it works now. š®
Is it possible to create a browser extension to that makes the browser devtools understand transit encoded edn?
ātransit-encoded edn?ā You mean you serialize to EDN and then serialize to transit? Surely not.
https://github.com/binaryage/cljs-devtools does this for EDN. Iām assuming you can use the same approach for transit.
Oh right I use that one, but it doesn't affect the network panel, so normal transit requests/responses are hard to read. Not sure if that is possible in a browser extension.
No, it doesnāt support transit. But Iām pretty sure it could, if you made it do so š
ah I see, thanks @U4YGF4NGM