This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-08
Channels
- # announcements (14)
- # babashka (12)
- # beginners (140)
- # calva (2)
- # cider (22)
- # clj-commons (14)
- # clj-kondo (49)
- # cljdoc (34)
- # clojure (92)
- # clojure-europe (41)
- # clojure-france (2)
- # clojure-new-zealand (2)
- # clojure-nl (2)
- # clojure-norway (60)
- # clojure-uk (17)
- # clojured (2)
- # clojurescript (7)
- # community-development (3)
- # conjure (2)
- # cryogen (13)
- # cursive (4)
- # data-oriented-programming (2)
- # datahike (5)
- # datomic (12)
- # defnpodcast (10)
- # events (2)
- # fulcro (20)
- # gratitude (3)
- # honeysql (4)
- # introduce-yourself (3)
- # jobs (10)
- # lsp (58)
- # malli (12)
- # missionary (19)
- # off-topic (8)
- # pathom (18)
- # podcasts-discuss (1)
- # polylith (41)
- # releases (1)
- # remote-jobs (3)
- # shadow-cljs (52)
- # spacemacs (1)
- # sql (37)
- # xtdb (19)
Hi #beginners.
I been diving in hard over the last week or so but when I felt ready to port a neglected but in-production django app, I started getting disoriented
Clojure's approach to web applications is very, very different to something like Django so it's going to depend a lot on what the app does and what features of Django you are relying on.
I think Django is one of those frameworks that are based around an ORM, yes? That's not an approach you see in Clojure (because we favor plain data instead of objects and an associated class hierarchy).
Thanks for reply. I’m experiencing some research fatigue. I’ve read up on Ring and Compojure and the approach seems fine to me
But then I sit down to get started and, oh yeah, I’m gonna need user authentication
and there doesn’t seem to be a consensus on how to do simple password-based auth without doing it from scratch
I’ve come across buddy and friend and they each have some level of disclaimer that they aren’t live projects going forward
Also read about [Kit](https://kit-clj.github.io/docs/clojurescript.html)
Buddy (and Friend) are still fine to use -- but I think the feeling is generally that auth tends to be much more of an app-specific thing than something a generic library can really solve.
Interesting
I guess tomorrow I’ll have to dive in deeper
Also, quite a few libraries get to a "complete" state and then get very little active maintenance and can be used for years "as-is".
As Adrian said in the other thread, if you can frame concrete questions around what you need to get done, that will make it easier for us to provide recommendations.
that is great. If I see a js lib that hasn’t had anything signficant in the commit log for five years I just move on
sounds good
I will surely bee back tomorrow then.
Yeah, that's good advice for JS -- but doesn't apply for Clojure 🙂
which is great
Is anyone present who cares to discuss porting a Django app?
You'll get better information if you go ahead and ask a concrete question. I'd start with a ring based web app, maybe using the luminus template (batteries included template for apps using ring with optional clojurescript frontend)
the thing is, even when using luminus you are going to be using a pile of libraries which provide your features, rather than a single turnkey monolith
Thanks. I expected that I’d be using a pile of libraries, but it’s proving a little overwhelming choosing among them. For instance, password-based auth with a db backend
I read up on luminus; the authors have a new thing, [Kit](https://kit-clj.github.io/docs/clojurescript.html)
If I use something like reaver
which is a thin wrapper for Jsoup
, when I add org.jsoup/jsoup
in my deps.edn
, does that override the version used by reaver
?
I believe so, an explicit version in your deps will override any transitive dependency. You can always check by doing clj -Stree
and examining the output.
Yes, top level dep versions always win
Is there any doc which gives more info while debugging a macro? or which library can be used to debug macro efficiently?
Not aware of any libraries. Do you know macroexpand-1
?
Macros can be tricky to get right because they transform their input and evaluate the result. With the macroexpand
family of functions you can look at the forms produced by your macro before they are evaluated.
In general you might want to do as much as possible with regular functions, and keep your macros small. You can often delegate parts of your macro to a function that is easier to test.
yeah - a good simple rule is to put logic in functions, and use macros for syntax
Have a problem that i currently cannot see any way to solve. I have a vector [:header]
and another vector
[[[:A]
[:B]]
[[:C]
[:D]]]
I know its a bit of a mess. However what i want to do is to merge these two lists into this:
[:header
[:A]
[:B]
[:C]
[:D]]
Anbody who has a clever trick to do so?(into [:header]
cat
[[[:A]
[:B]]
[[:C]
[:D]]])
;;=> [:header [:A] [:B] [:C] [:D]]
Oh wow, thank you. I've attempted so many things such as into and apply, but i've never quite got it. Thank you very much!
cat
seems pretty useful, not sure how I've missed that. flatten
seems to be discouraged so I've been trying to find my own way to do such things.
Hi, should I use func!
if it changes agents/atoms/etc as a side-effect or it’s fine just func
? what’s your preference? thanks
Yes, I would use !
for that. When the (main) responsibility of a function is to change state, then I use !
.
Don’t aim for mathematical purity though. Logging is technically a side effect, but this is an implementation detail and does not warrant !
.
Hi, clj question. I’m trying to mess around with buddy in the repl.
{
:deps {buddy/buddy-core {:mvn/version "1.10.1"}
buddy/buddy-hashers {:mvn/version "1.8.1"}
buddy/buddy-auth {:mvn/version "3.0.1"}}
}
That’s my deps.edn (the only file in the working directory). I run clj
, the libs download, but then I (require '[buddy/buddy-hashers])
and it fails with Could not locate buddy_auth__init.class
I sense I’m missing something basic here.
@james.amberger should that be (require '[buddy.buddy-hashers])
, actully it seems it should be (require '[buddy.hashers])
, so ideally I would use an alias, so really it would be (require '[buddy.hashers :as hashers])
Examples are in the user guide https://funcool.github.io/buddy-hashers/latest/user-guide.html
Thanks john; (require '[buddy.hashers])
did the trick
How to get syntax highlighting and tab completion in my repl?
For syntax highlighing and tab completion • in a terminal repl, use rebel readline • For emacs use Cider and/or Clojure LSP • For VS Code, use Calva (which uses Clojure LSP) • For intellij, use Cursive • For NeoVim, use Conjure, CoC and Clojure LSP
I had rebel readline in my deps.edn before but I did not hvae colors/completion. I tried to look around for necessary additional steps
This is how I use rebel readline https://practical.li/clojure/clojure-cli/repl/
Yeah I have vim-fireplace working
It’s very cool
ahh, much better. Thanks John
When using Neovim, I use the following configuration https://github.com/rafaeldelboni/nvim-fennel-lsp-conjure-as-clojure-ide There may be some ideas you could borrow from it also.
Rebel Readline is a very effective terminal UI to the REPL process and very handy when you dont have an editor connected to the REPL. Obviously it wont have all the syntax highlighting and completion available from a complete Clojure IDE or if using Clojure LSP, but they do require a little more investment to setup.
online help with rebel readline ?
rebel readline has eldoc, so should function arguments as you type. There is also a key binding to show docs - type :repl/key-bindings
to see the current key bindings
If more than that is needed, then either use a web browser or move to an editor / ide connected REPL setup
I used com.github.seancorfield/next.jdbc {:mvn/version "1.2.761"} in deps. call create table sql show error: ; Execution error (ClassCastException) at next.jdbc.prepare/create (prepare.clj:94). ; java.lang.Character cannot be cast to java.lang.String
(def mysql-db {
:dbtype "mysql"
:dbname "bzst_db"
:user "root"
:password "root"
:jdbcUrl "jdbc:"
} )
(def schema-account-holders-table
["CREATE TABLE account_holders (id VARCHAR(32) NOT NULL"])
(create-tables! schema-account-holders-table mysql-db)
character cannot be cast to string usually means you’ve called something that expects a sequence of strings with a single string
you’re using some function called create-tables!
which we don’t see the source of here. I’m guessing it bottoms out in some sort of (doseq [table tables] (jdbc/execute! table)
and i think you should read the doc string of the jdbc function you are calling
Missing closing bracket in schema-account-holders-table
Missing closing bracket for the opening bracket before id
good point. once you can transact your sql syntax will fail, but you haven’t gotten to a point yet where the contents of those strings matter
After NOT NULL and before the "
Some examples here, https://practical.li/clojure-web-services/projects/banking-on-clojure/database-tables.html The official docs are really good too
@U025AG2H55F You need to share your create-tables!
function for us to help.
Thanks everyone, I solved it. like @U11BV7MTK said that I used the String pass to Vector
Umm…so I’m looking around for a clojure way of performing some maths with numbers where numbers could be doubles, ints, rationals, big decimals. Specifically I was hoping for a sqrt (among others) function which would work with big decimals but would not break if called with some other type. Something like:
(with-precision 10
(.sqrt 3M *math-context*))
works for BigDecimal specifically, but breaks if I send in a double etc. The numerical tower lib coerces big decimals to doubles which is not workable for my case. Is there some lib out there which has basic numeric functions for clojure which handle mixed number types?preferably there should be some attempt at retaining types, i.e. if I use doubles it should produce doubles, if I use BigDecimal it should procuce BigDecimal etc
I guess I can implement this myself via a defmulti and delegation to the java methods
I think there is kind of no man's land between enterprise kind of systems where math isn't a huge priority, and machine learning systems where math is a huge priority
like the one is likely to just "solve" this kind of issue by just using bigdecimals, the other is all matrices, possibly off heap, where you want to avoid bigdecimal
where there is a significant interest in math, it seems to fall more on symbolic manipulation of equations
https://github.com/sicmutils/sicmutils kind of thing
@hiredman thanks for that…a lot of good stuff in sicmutils…will need to stare at that code for a while to see if it covers my needs but definitely looks promising
Trying to decode base64
This is proving difficult. I have imported Base64$Decoder
but I can’t seem to call getDecoder
no matter what I do
user=> (import '(java.util Base64))
java.util.Base64
user=> (def s (.encodeToString (Base64/getEncoder) (.getBytes "Hello, world!")))
#'user/s
user=> (String. (.decode (Base64/getDecoder) s) "UTF-8")
"Hello, world!"
In clj or cljs?
(made me look though!)
Ok, the easiest way to decode Base 64 is to use the static method: Base64/decodeBase64
(.decode (java.util.Base64/getDecoder) b)
will work, but you'll want to annotate the type of that param.
ok, looks like I didn’t actually call getDecoder
Yeah, that kind of bug is particularly difficult to spot.
how can I call Base64/decodeBase64?
I don't know where that method exists.
That’s a static method on the class.
Are you referring to org.apache.commons.codec.binary.Base64
?
java.util.Base64/decodeBase64
gets me Unable to find static field
Ah, wait, I’m referring to an old project, and it’s pulling in org.apache.commons.codec.binary.Base64
, yeah
but also
Sorry about that, I forgot I’d pulled that in.
Try the one I posted above. It should work for you.
isn’t this kind of static this, return a ‘Decoder’ that stuff the very sort of thing we hope to avoid by using clojure?
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Base64.Decoder.html is the java docs for the decoder; and you get it from https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Base64.html
It is, and you could find or write your own wrapper function for it. That's what I use. But interop is interop.
so I would have to make a simple function out of it myself, not hard but
gotcha
dev=> (let [decoder (java.util.Base64/getDecoder)]
#_=> (seq (.decode decoder "1234")))
(-41 109 -8)
(edited for readability of the result)Clojure is hosted within a platform, and aims to reuse / leverage all the existing correct code
k thanks, I will
@ghadi can you rephrase that?
last, what’s SIMD acceleration, and what’s that >>> relation mean
SIMD acceleration is a way to improve performance of algorithms like base64: do things a block at a time, rather than byte at a time
>>>
meaning just "way better than"
thanks
@james.amberger FWIW, I used to be a big fan of wrapper libraries when I first got started with Clojure years ago but I've come around to preferring direct interop these days -- unless you are writing .cljc
code and need portability between Clojure and ClojureScript.
yeah, I have seeen ‘cljc’ a couple of times now. What is it?
some kind of precomiled
classes?
.cljs
is ClojureScript, .clj
is Clojure, .cljc
is accepted by both Clojure and ClojureScript
the "c" at the end of cljc == "common"
So you can have conditional (read-time) code in .cljc
files to allow you to share logic between frontend and backend.
that’s appealing
read-time = compile time for cljs?
It's more and more possible these days to write portable code -- see https://github.com/seancorfield/honeysql/blob/develop/src/honey/sql.cljc which only has four conditionals in it (see https://github.com/seancorfield/honeysql/blob/develop/src/honey/sql.cljc#L172 for example).
Read-time means read-time. Parsing. Pre-compilation.
very cool
yeah the more I look at this the more it seems that where in Python or TS I would have been reaching for a library, in Clojure I’m supposed to just do it
clojure.core
is very powerful, and the whole of the Java standard library is also right there "just below the surface". A lot of batteries included.