Live data from Hacker News

Try Clojure

tryclojure.org

371–380 of 404 posts

Re: Try Clojure

#371

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.

Good to know--I'll do another run through the tutorial sometime and see if I notice anything. I know there are a couple things I need to update in the example repo at least.

Re: Try Clojure

#372
post #370

Earlier 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?

Well, there are objects through interop, and under the hood everything is compiled into one. But when you develop an app, you won't be defining classes and instantiating objects of them, you'll be instead writing functions that return maps or other data-structures.

Re: Try Clojure

#373
post #108

Earlier 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.

[dead]

Re: Try Clojure

#374
post #116

Clojure 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…

The closest to this (MVC framework with all features including migrations, API building, auth...) is Xiana https://github.com/Flexiana/framework/

Re: Try Clojure

#375
post #224

Earlier 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.

[deleted]

Re: Try Clojure

#376
post #224

Earlier 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.

npm, docker, kubectl honestly, you are splitting hairs. I plan to run a process for hours, I think 40 ms delays are something I can live with.

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

#377
post #369

Earlier 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…

Ya, so you'll be working with the DB directly instead of through an Object representation.

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

#378
post #306

Earlier 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.

It's just:

    (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

#379

Earlier 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?

FP in CL is kind of optional, and it's also more in the sense that you can pass functions as arguments or return functions, meaning FP == First Class Functions.

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

#380
post #316

Earlier 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://…

Well, quite a few people already use AOT with PGO from GraalVM to build native executables of Clojure programs. Those start stupidly fast. I never heard of anyone doing so with OpenJ9, how good is the AOT of OpenJ9?

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.

Post reply on HN