This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-15
Channels
- # announcements (2)
- # aws (1)
- # beginners (200)
- # calva (136)
- # cider (32)
- # clj-kondo (1)
- # cljs-dev (14)
- # cljsrn (19)
- # clojure (147)
- # clojure-argentina (1)
- # clojure-dev (144)
- # clojure-nl (2)
- # clojure-spec (14)
- # clojure-turkiye (1)
- # clojure-uk (1)
- # clojurescript (7)
- # data-science (1)
- # datomic (5)
- # duct (6)
- # figwheel (2)
- # fulcro (4)
- # graalvm (10)
- # graphql (1)
- # immutant (1)
- # joker (4)
- # off-topic (30)
- # om (1)
- # re-frame (11)
- # reagent (2)
- # reitit (4)
- # shadow-cljs (63)
- # testing (1)
- # tools-deps (7)
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L47 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L7104
the docs are so so good. I need to spend a weekend just reading them. I always try to go to some authoritative source when i'm wondering or answering a question.
That’s true. I think the only real difference is that fn allows for restructuring. Fn* is the actual primitive though. Check the sources I linked and you can see
Several of the forms described as "special forms" are actually implemented as macros in terms of a *
version of the form.
fn
is a macro in terms of fn*
, let
is a macro in terms of let*
.
my question is, fn* cannot be accessed in repl., but can be access in a clojure file, i.e., clojure.core
fn*
and let*
etc are part of the compiler. They're not actual symbols.
That's why, technically, fn
, let
, etc are considered the "special forms". Just assume they are magic in the compiler, rather than macros 🙂
If I'm relatively new to Clojure (have done a few months of Clojurescript), is Duct a good library to use for building a web server / api? I like the config/data-driven approach, but seems like a lot of modular pieces to keep track of
Sure, start with Duct and see how you get on. There are lots of good ways to build a web app with Clojure.
No, never used it.
But it's solid.
Mostly at work we use Ring, Compojure, Component, Selmer... and dozens of other libraries. One of our apps uses Bidi instea of Compojure. Most of our apps use the built-in Jetty adapter but one uses Netty.
Clojure's way is to compose a whole bunch of libraries into an app -- so pick whatever speaks to you and see how you get on.
I feel some people have a harder time understanding how libraries would be stitched together. But really, a lot of these are small targeted frameworks And I've had some encounters where somehow by calling them micro-frameworks, it clicked more in people's head.
Like library makes it sound like you'll have to do a lot on your own. When really, it's just that the glue logic is expressed in Clojure instead of say XML
Libraries in Clojure/ClojureScript are more like DSLs. Or micro-frameworks as you mentioned.
I disagree. Frameworks call your code. With libraries, you call their code. Clojure has libraries almost universally.
That's how I define it as well. But I think there's a new kind of distinction that seems to help understanding what some of those libraries do. Like application frameworks of yore, such as Rails, Spring, etc. They clearly are the main entry point, and call into all your code, and are in control of it all. But something like Compojure, is more of a hybrid. You call it, but it also calls you. It'll call your routes handlers for you. It's still in control of a subset of the order of execution and context of execution of some of your logic in that sense.
If all compojure did, was parse a route string against a URL, it would be different. But by adding that extra orchestration, it acts as a micro-framework of some sort.
And then I looked around, and it seems in other languages, libraries like Compojure have also started to show up, and they're calling themselves micro-frameworks
And I mean, the names don't matter much, but trying to explain some of this to others, I've noticed somehow, if I describe them as micro-frameworks, it seems to help them have a better mental model, and they follow along more easily.
Compojure is just a higher-order function. Nothing more, nothing less.
"micro-frameworks" is just buzzword b.s. 🙂
Haha, ya I know. And they stem from languages where to just inject some code into a function, you need a gazillion of setup and a whole support DI framework 😛
But for some reason, when I switched from answering: "What framework should I use for web development?" - You don't need a framework. In Clojure you just put libraries together yourself such as Compojure and Ring... TO: Oh yes, Clojure favors micro-frameworks, Compojure and Ring are the two most popular of them, try them out.
It seems like the reception was way better. Like people are like... Oh awesome! I'll go try them out right away!
I still think people should learn the right terms (libraries) instead of b.s. 🙂
I think most of the people you're trying to teach aren't trying hard enough.
Clojure is hard to learn if you're coming from a "bad" place.
There's a lot to unlearn before Clojure's simplicity makes sense.
The obsession with "frameworks" must be unlearned. The "normality" of state and mutation must be unlearned. Assignment, mutable loops. All must be unlearned.
You can't just map this stuff down to other languages' terms and practices. Clojure really is different.
Where do re-frame stand between libraries and frameworks?
I never quite got the "frameworks call your code and you call libraries' code". Take integrant (or equiv.) for example, is it a library because I call it to initialize/halt systems, or a framework because it calls my multimethods to initialize/halt my components? Any way you slice it, at the end of the day, it seems like there is some subjectiveness involved in calling something a framework/library. No matter what you call them though, these things are way more simple in Clojure than other ecosystems I've seen. Any thoughts on this highly appreciated.
First, a library is just a packaged piece of code that you can link against. So it's not really framework vs library, but just, some libraries are packaging framework like code, and others are not, thus some people say: this is *just a library; in the sense, I didn't include framework like code in here. This often is due to the assumption that a framework comes with a lot of machinery, and new mechanisms of interaction which you have to learn, understand and start using to leverage any reuse from the library. Where-as just* a library, means that it uses the existing known mechanisms of whatever language you use for code reuse, like simple function calls for example.
Now, certain language lack simple mechanisms in order to re-use orchestration code. Like, you can call a method on an object, and it returns a result or performs an action. But what if you want to reuse a sequencing logic and override some of its steps? Some language make that difficult to do, so you need a lot of machinery to make it work. That's kind of where the crux of frameworks came from.
And they started as Application Wide framework. The idea was, what if you want to reuse an entire financial application? And just customize pieces of it to a new use case?
Take Django for example, a Web Application Framework. It's pretty much a full web stack, and then it started giving you more and more hooks into swaping pieces of it so you can re-customize it to implement different websites with it.
Big monoliths, all encompassing, application level orchestrators, which have custom configuration mechanisms and extensibility mechanisms.
Now, there are much smaller scoped frameworks. Very lightweight machineries, which take over only a very small portion of your application. So you still have to integrate them in your app, and call them yourself, like you would with things that are *just* libraries.
You can call it a micro-framework. That's what other languages are starting to call them. But I think Sean's point here was that, at that point, calling it a micro-framework is maybe a stretch. Especially in Clojure. That's because, the machineries used are all normal Clojure machineries. Either simple function composition, higher order functions, macros, or data-driven interpreters.
One of the few commonly-used libraries in Clojure that might be loosely categorized as "framework lite" is Ring, because it plugs in "above" your application code and it calls your functions. But that's a bit of a stretch given that you are specifically giving it a function to call.
Frameworks tend to follow conventions or have specific configurations around "registering" your code to be called by the framework.
Even with Ring, you are calling Ring functions to kick the whole thing off and passing your function to be called.
Ya, to me, it boils down to two things: 1. Is it at the application level? Does it take over your whole application? Or like Sean said, is it above your application? 2. Does it use non-standard and custom configuration and extension mechanisms? As opposed to using common language features.
Exactly this.
Makes sense. My intuition almost exactly lines up with this. I don't call my app an "integrant app" because I'm using that, but I do call it "Django app" when I'm using that.
The special forms are always available. They're the only thing you can use from a namespace that did not require clojure.core for example
There’s a book called lisp in small pieces that you would enjoy. It details exactly this. And you make several scheme interpreters and compilers along the way
But in general you look up the first form in an environment if it’s not a special form
You probably already do this with your if implementation. It gets hard to see when your implementation language and implemented language are similar
It does. I think it’s because they execute sequentially and can modify the environment
There's also: https://github.com/kanaka/mal
And this one is free online as well: http://www.buildyourownlisp.com/
But classically, let can be a macro expanding to anonymous function application, but that also doesn't work for clojure because it breaks the only constant space recursion mechanism
(let [_ nil]
...)
is like (do
...)
(assuming ...
doesn't contain _
Yeah, what he said.
If you are writing your own language, you can just make tail recursion work properly, so who cares about recur
If you look at the old chat logs it’s conversations like these with Brandon bloom and ztellman and probably hiredman about clojure like this.
It is a degenerate behavior of the = function. It isn't terribly useful in many cases, but it does mean that you can, for example, take a collection foo and do (apply = foo)
and you will get back true
if all of the elements of foo
are equal to each other.
Similarly reasoning for why many functions that normally take 2 (or more) args can in some cases also take 1, e.g. (apply + coll)
also works to add up collections of only 1 number.
Hi all, anyone out there using NATS Streaming with Clojure? Are you just using the official Java library?
had no idea what nats even was, had to look it up .... br what's a good usecase for it ?
ok ... read up a bit ... smarter now ...
we have been using rabbitmq instead of kafka for the very same reason
Yes but we can't use pub/sub for this, we need persistent event log and topics (ala kafka)
we use the message queue just for reliable communications between microservices ... and there's so much chattery that long term storage would be out of the question anyway 😄
We may use it for this also, but the more importing thing for us is the persistent event log
for the stuff we want to persist we have a consumer that dumps stuff directly into s3
i could never afford to keep it on amazon's gp2 or even magnetic drives 😄
I do not understand why being data driven would lead to a preference of one over the other. Both maps and records are similar, but not identical, ways to represent data.
At least until recently, maps could not participate in protocols, but records can. There are a few other differences between them that sometimes lead to a decision to use one over the other, but I do not think any of them involve "one is data, the other is not"
somewhat fuzzy on the authentication/authorization world... is it possible (or does anyone have experience with) using firebase for authentication and then the result of that for authorization on a non-google server?
I have the authentication with firebase part understood in a react app... just not sure how that all works with routes on one's server.
this could be relevant: https://firebase.google.com/docs/admin/setup
I am trying to get logging to work when i run tests with this style
clj -A:dev:clj-tests --watch
if i have println or timbre/log they don't show up .. trying to find out what will show up ? ! > ?
I guess a more specific question is: how does your server know when a firebase authenticated user is invalidated?
I’m looking for a nice way of sorting stuff based on some predetermined order. ClojureDocs comes up with https://clojuredocs.org/clojure.core/sort-by#example-542692cbc026201cdc326c2f, which seems nice, but doesn’t it recreate the lookup table for each comparison?
ha... getting warmer: https://firebase.google.com/docs/auth/admin
If so, how would you fix it? Pre-define the lookup table, or memoize? Pre-defining isn’t as self-contained (you need a def
), so I’m thinking of memoize. Wrapping everything in a sort of (defn sort-by-order [order, key-fn coll])
interface also doesn’t seem nice, since it does not compose with eg juxt
the callback from firebase will send you a user object. You can get jwt tokens from that. you can check them with buddy that the tokens are 1) not expired, 2) signed by google. These will have user details which can then be trusted
ah ok... so buddy sits on my server and communicates with firebase's servers somehow?
I'm understanding my client sends a callback object and then a jwt token (all this in the client) and the jwt token is send with requests to my ring app, which then checks with firebase directly.
you've confirmed that buddy will be what I want to look at.
or maybe the jwt is created on the server... at any rate I shouldn't be thinking aloud like this.
if the frontend sends you a jwt you don't need to talk to firebase you just need to look at the token. Firebase has a java sdk as well though so you can use that if you like as well
google puts out a rotating list of signing keys somewhere and you check that the jwt was signed with those keys and then you can trust the jwt payload
ah ok... shapes emerging in the fog... basically, I have a ring based server of my own, but love firebase.
I should clarify, love firebase authentication.
i'm not advocating one over the other but use both. Frontend sends credentials to firebase, gets authenticated. this gives a firebase user object in js. you ask that for a token which you can include in chatter to your backend. You backend can inspect the jwt, ensure its signed by google, and if it is, can trust the user info contained in there. Email, time logged in, when it was issued, etc
this is all fantastic news... I was getting worried I'd get locked into their firebase friendly services... sweet!
I never quite got the "frameworks call your code and you call libraries' code". Take integrant (or equiv.) for example, is it a library because I call it to initialize/halt systems, or a framework because it calls my multimethods to initialize/halt my components? Any way you slice it, at the end of the day, it seems like there is some subjectiveness involved in calling something a framework/library. No matter what you call them though, these things are way more simple in Clojure than other ecosystems I've seen. Any thoughts on this highly appreciated.
First, a library is just a packaged piece of code that you can link against. So it's not really framework vs library, but just, some libraries are packaging framework like code, and others are not, thus some people say: this is *just a library; in the sense, I didn't include framework like code in here. This often is due to the assumption that a framework comes with a lot of machinery, and new mechanisms of interaction which you have to learn, understand and start using to leverage any reuse from the library. Where-as just* a library, means that it uses the existing known mechanisms of whatever language you use for code reuse, like simple function calls for example.
One of the few commonly-used libraries in Clojure that might be loosely categorized as "framework lite" is Ring, because it plugs in "above" your application code and it calls your functions. But that's a bit of a stretch given that you are specifically giving it a function to call.
Ya, to me, it boils down to two things: 1. Is it at the application level? Does it take over your whole application? Or like Sean said, is it above your application? 2. Does it use non-standard and custom configuration and extension mechanisms? As opposed to using common language features.