Earlier quoted context omitted.
Mind sharing the parts of the tutorial you had trouble with, if you remember?
I'll see if I can go back and figure out where I lost track of things. I believe it was right around when making the message entry box functional. I ended up having to dig into the repo to see what I was missing.
Try Clojure
371–380 of 404 posts
Re: Try Clojure
#372Earlier quoted context omitted.
There's no object in Clojure, so there's no need for an Object Relational Mapper. You just work directly of the query result sets, which the SQL library itself can conveniently turn into rows of maps if you prefer (over rows of lists).
No object is kinda mind blowing since it has java interop. I guess everything just becomes maps?
Re: Try Clojure
#373Earlier quoted context omitted.
While I share your perspective on go, I do prefer developing in a bottom-up way myself: I just do so with the intent of iterating my way to a higher level abstraction. Sometimes I see the abstraction right away and start with it, but I don’t want a language that gets in my way in either direction.
The thing is, in Go you can develop bottom-up, but you can't always end up with a an appropriate abstraction, because of the lack of tools to achieve that.
Re: Try Clojure
#374Clojure looks productive. What frameworks libraries do people use to build web apps? Like, replacement for Django view layer and ORM (not looking to debate orms thanks)?
There is not a batteries included framework a-la Django or Rails for Clojure. I would argue that is one of the biggest pitfalls to the language/ecosystem. If you are building a web application, you will need to invent the entire thing yourself. There are micro frameworks and tools that exist standalone to deal with HTTP, DB ORM, etc... but that will be an exercise left to the reader. Some will say this is a good thin…
Re: Try Clojure
#375Earlier quoted context omitted.
>>The JVM cold-starts, loads a Hello, World program from a compressed JAR, runs it and shuts down in 40ms. Im yet to reach the X-men level super qualities that can detect, and work in 40 ms chunks. Or at least even notice a 40 ms delays. I envy the humans who can notice such small chunks of time.
I don't like how this issue is constantly dismissed out of hand. It very obviously is actually a massive glaring issue which severely limits what clojure can reasonably be used for. Nobody would ever accept a 1 second startup time for CLI applications that we use all the time like git, kubectl, npm, docker, etc.
Re: Try Clojure
#376Earlier quoted context omitted.
>>The JVM cold-starts, loads a Hello, World program from a compressed JAR, runs it and shuts down in 40ms. Im yet to reach the X-men level super qualities that can detect, and work in 40 ms chunks. Or at least even notice a 40 ms delays. I envy the humans who can notice such small chunks of time.
I don't like how this issue is constantly dismissed out of hand. It very obviously is actually a massive glaring issue which severely limits what clojure can reasonably be used for. Nobody would ever accept a 1 second startup time for CLI applications that we use all the time like git, kubectl, npm, docker, etc.
git- I take more time to write the commit message to worry about 40 ms.
I mean sure optimise code to run it fast. But its not something that a human notices.
Re: Try Clojure
#377Earlier quoted context omitted.
In Clojure you'll have to write the queries yourself unfortunately. People always ask, where is the fully fledged web framework in Clojure? There isn't one. Why there isn't one is hard to answer, but it's partially because the people who could write one, don't find they need one themselves. There's definitely a preference in Clojure for not relying on frameworks, because the current people in the community like to be…
> I implemented the small website you were talking about Thanks, that's neat. I'm not even talking about the framework part. Just db access. Let's say I have a Posts with a managed_by property that points to a list of User which have a ManagedProfile. In Django's ORM (or any good ORM), I could do: if post.managed_by.contains(user.managedProfile)... or I could do: post.managed_by.add(user.managedProfile) also all thes…
And I agree with you, it's less features, and maybe it would be nice to have something similar in Clojure, but there's a reason the feature doesn't feel as needed, and nobody bothered building it.
In OO langs, one of the major pain points the ORM solves is mapping the result back into an Object. Otherwise, you have to manually go:
post = new Post();
post.title = queryResult[1];
post.content = queryResult[2];
...
In fact, some ORM keep to that only, I think are normally called micro-ORMs. All they do is data mapping to/from between the DB and your object model.In Clojure, you don't have this pain point, the DB query returns a list of maps, and you work with those maps directly.
I suspect this is the main reason why no one bothers implementing an ORM-like in Clojure.
That means, for your example, you would create a function that queries the DB to check if a post is managed by a particular user. And you'd call that for your condition:
(if (is-managed-by? post-id user-id) ... ...)
Or to add one you'd do something similar, create a function that adds a user to manage a post: (add-manager-to-post post-id user-id)
You're working directly with IDs, because there are no Objects here. You're working with data directly, and that data is similar to the data in your DB, the representation is much closer between what your code uses and the DB.That means, in OO langs, you think of your state as being those object models, and then you try to sync them back/forth to the DB, after you've mutated it a bunch, you call .save() on it for example. But in Clojure, you think of your state as the DB itself, if you want to change state, you just run a query on the DB to change that state directly, you don't modify some in-memory model and then try to sync that back to the DB.
Re: Try Clojure
#378Earlier quoted context omitted.
What's so different to Clojure's ? (let [a 1 [b c] (list 2 3) [d e] [4 5]] `(~a ~b ~c ~d ~e)) ;; => (1 2 3 4 5)
But what would be the equivalent of: (let ((quotient remainder (floor x y))) (+ (* quotient z) (* remainder (floor z y)))) Where floor is a function which returns multiple values rather than a list or vector of results? Also, but this is entirely on me being an absolute dullard, I like having the brackets around each binding as a kind of guardrails for my mind to not lose track of where I am and what belongs where.
(let [[quotient remainder] (floor x y)]
(+ (* quotient z)
(* remainder (first (floor z y)))))
Because in Clojure there's no multiple value bind, when you want to return many results from a function, you wrap it in a vector, and that means you than just destructure that vector. That also means, it's not smart enough to know if it's used in a single value context or multi value context, so you need to always get the value out of the vector, which is why I call first in that second call to floor.Re: Try Clojure
#379Earlier quoted context omitted.
Clojure also teaches you functional programming, where-as CL only teaches you the LISP beauty. Clojure teaches you both Lisp and Fp. So the FP part should still be worth it even though you got the Lisp part from CL.
How does fp in clojure differ from fp on common lisp?
But in Clojure, FP is kind of mandatory, there's no OO for example, and it's more than just first-class functions, it's also immutability.
Re: Try Clojure
#380Earlier quoted context omitted.
Can you talk more about these?
AOT compilation with PGO, available for free on GraalVM and OpenJ9. Also available since around 2000 from comercial vendors, of which, Aicas and PTC are the main survivors. https://www.aicas.com/wp/products-services/jamaicavm/ https://www.ptc.com/en/products/developer-tools/perc OpenJ9 also does JIT caching across executions, https://eclipse.dev/openj9/docs/aot/ OpenJDK also does caching but at higher level, https://…
AppCDs in OpenJDK currently has terrible ergonomics. Clojure can't really offer it. Each user must go out of their way to leverage it. So you can't really release an app that automatically leverage it, the user needs to launch it with all the command incantations, etc. And it's so sensitive to class path changes, etc. It kind of sucks to be honest. But some people still use it for prod release, since you can set it up in a docker easily. But the use-case for fast startup are desktop apps, CLIs, scripts, etc. And for all those, AppCDs are super annoying to setup. See: https://ask.clojure.org/index.php/8353/can-we-use-appcds-to-...
Still, AppCDs don't fully solve the startup issue, because all the static initializations stuff takes a considerable amount of time, and that does not get cached by AppCDs.