beginners

Melody 2025-06-12T16:42:36.009099Z

Does anyone have a good recommendation for learning about asynchronous programming from the ground up? Most of my experience learning about async stuff has been in a context where I feel like people just assumed a lot of knowledge from me and I think that there are gaps in my knowledge and I don't even know what they are. I first learned about async programming in C# and feel like I have a strong conceptual grasp around sync vs async vs parallel and I understand general ideas like a core orchestrating threads but I get really lost in the syntax of it all particularly, especially back when I did do C# await and promise never really made sense to me and now I am working on something that definitely is going to require async tools and I am kind of going around in circles. I have the loop I want to process working synchronously but inefficiently and I can get the server to process data but am struggling to get the server to pass the data to the front end and having trouble and I think a good foundational reference would be helpful for me but most of the things I found in looking seem to assume knowledge like I said (or at least that is how I perceive it). Java async always seemed even more complicated than C# to me and so I feel like I should probably understand that at least a little bit more too if I am really going to understand it in Clojure well.

2025-06-12T16:48:17.179829Z

you don't need the java async stuff, what clojure offers works much better. my experience is that immutability makes async and parallelism a lot easier and the java async stuff won't really engange with that I recommend checking out the core.async docs and the official tutorials for it - there are a few gotchas to learn but overal it's a very straightforward model that said, you can get a lot done just by understanding the difference between agent and future and using those as needed you meantion server and frontend so I assume you are doing web dev, the mechanics of your web frameworks are going to influence how you do async much more than clojure

πŸ‘ 2
dpsutton 2025-06-12T18:40:06.915939Z

i’ve heard good things about https://pragprog.com/titles/pb7con/seven-concurrency-models-in-seven-weeks/ I know we have a @paulbutcher here. not sure if that’s the author or not. But i’ve heard very good things about the book

πŸ‘ 1
βž• 1
dpsutton 2025-06-12T18:40:52.711369Z

it does seem to be the author! I know him as a race car driver πŸ™‚

2025-06-12T18:45:54.913409Z

I mentioned previously that you don't really need to learn java async stuff, but if you want to learn how java really works, or want a low level intro to how concurrency works on hardware, JCIP is an excellent book (it's part of rh's recommended books he recommended to understand how he designed clojure) https://jcip.net/

Krishnansh Agarwal 2025-06-12T19:42:35.457639Z

@dpsutton thanks for mentioning this book, I read the preface and it looks an interesting read considering as same as OP, I feel confusion when using Promises in JS at my day job. I have tried Go Routines, but I haven't really understand difference between them and more- what problem are they trying to solve.! This book seems a promising read πŸ™Œ

1
paulbutcher 2025-06-12T21:50:24.971169Z

Thank you for the kind words @dpsutton, much appreciated!

1
dpsutton 2025-06-12T21:50:49.024359Z

recognizing good work and a nice person is very easy to do

πŸ’― 1
πŸ™ 2
Krishnansh Agarwal 2025-06-12T19:30:57.056329Z

Clojure is a compiled langauge yet dynamic. I have a small doubt. Adding 2 variable, which types are String and Array, and I do (+ a b) will it compile ? Or will it crash at Runtime (?)

Reut Sharabani 2025-07-21T10:18:13.161769Z

The most important points IMO are that types don't give confidence, and that to properly assess Clojure you need to use a REPL integrated to your editor (not python style).

gaverhae 2025-07-21T11:14:31.324779Z

Very slightly tangential topic: we've been discussing why you may not miss types as much, but I think it's also worth addressing why you'd want to give types up in the first place. When working in Haskell, I have found types to be an extremely useful tool to structure my own thoughts and help me think clearly about how to decompose my program, and sometimes checking just the type signatures of many undefined functions can already give you some level of confidence that the system you're designing is at least somewhat consistent. A type checker is also very useful for large-scale refactoring. That is to say, I do believe types are good, and have value. But they also have a cost; I choose to use a dynamic language rather than a statically-typed language because I value the benefits of dynamicity more than the safety of types, and that is a tradeoff that can be deeply personal, and somewhat problem-domain-specific. Specifically, I do not know of any programming system that is both dynamic (notice I am not saying "dynamically typed") and statically typed. https://www.youtube.com/watch?v=3HxVMGaiZbc is, I think, a very good example of what you can do with a dynamic language that, as far as I know, is impossible to do in a statically typed language. The TL;DR: is that with a dynamic system you can change your application code while maintaining its state, which, for applications that have complex, non-transient internal state, is a huge deal for interactive development. Think fixing a bug in Excel, and compare having to recompile / relaunch / recreate the situation versus changing the code on the fly while the application stays open. For mostly-stateless (or at least transient) applications like compilers, the benefit of dynamism is somewhat less obvious, and types can help a lot more.

😎 1
technosophist 2025-07-22T11:21:11.018519Z

This is the difference between a system paradigm and a language paradigm. One sees a system as an living organism made up of cells, and the other as a mathematical transformation that preserves semantic meaning. Perlis hit on this in his foreword to SICP. The former is a REPL and the later is a compiler. The former is alive and the later is dead.

1
2025-07-22T22:30:15.577769Z

As for the other question. I will say it's partially true. Most of the quirks you'll encounter are due to trade offs made due to its hosted nature. For example, exception handling is done in the style of Java. You'll also be doing a lot of interop, and using those Java APIs will be similar to using them in Java just that you'll have a nicer syntax and access to the REPL. But they might have that same overly verbose and enterprisy Java feel to them. That said, it's also going to all feel very much like Clojure, and I'd argue almost more so than Common Lisp, because Common Lisp leans heavily imperative, and that's going to make it feel a lot more like Java in a lot of ways. Clojure kind of sits at the intersection of Haskell's heavy purity and lazy feel, Scheme's/Racket's heavy functional and higher order function feel, Common Lisp's heavy macro DSL and polymorphism, Go's concurrency style, and Java.

Christoph 2025-06-13T07:17:29.621759Z

Coming from a couple of years in strongly typed functional programming, I've learned that types are a very poor substitute for tests. If you have to test anyway, type-checking becomes redundant as both the type checking and logic checks are captured in the tests.

πŸ‘ 1
exitsandman 2025-06-13T07:24:25.299679Z

They're also an especially poor substitute to validating inputs and consistent naming.

2025-06-13T09:18:57.432419Z

@krishnansh710 don't forget Clojure's alterntive hosts: JavaScript (browser or Node), Dot Net, Dart, and to some degree Bash... By the way, I do not notice much discussion of other Lisp variants here, except in cultural or etymological contexts. Clojure is not in competition with them. Host interop indeed trades elegance for access to the host ecosystem. Often we encapsulate it in an interop-intensive "wrapper" around a host-specific feature so our main program can remain elegant. A dynamite example of this is Zach Tellman's wrapper for the Netty webserver. Check out https://aleph.io/ for the elegance and then (if you dare) go look at aleph's implementation.

😍 1
βž• 1
technosophist 2025-06-13T10:51:45.759459Z

It is not true that Clojure code ends up looking like Java code.

βž• 2
gaverhae 2025-06-13T12:19:06.239149Z

As a Clojure enthusiast who spent a few years in a primarily-Haskell team, here are my thoughts: β€’ From my experience, you're much more likely to miss pattern matching and clearly-defined variant types than the type-checker itself. Also possibly the built-in notation for monads, and Haskell's fairly unique return-type semantic significance. β€’ It's sometimes hard to appreciate, for people coming from a static typing background, how much variation there is between "untyped" languages. Specifically, Clojure throwing a run-time error (rather than a compile-time error) when running (+ 1 "hello") is perhaps annoying, but if you have your tests running in a file-watch loop, that's not experientially different from ghcid catching the issue. It is, however, worlds apart from JavaScript's "hello" + 1 returning "hello1". And that kind of behaviour percolates through all of the library ecosystem. β€’ Just because you don't have a type checker does not mean you don't need to think about your types. It does put an extra mental burden on you, but you also have vastly fewer types to think about. In practice, new types are very rarely defined in Clojure, so you end up working mostly with vectors, maps, and the occasional set. It can be a bit intimidating at first, coming from Haskell, but it's actually pretty rare in my experience for type errors to be significant in Clojure development.

πŸ‘ 1
βž• 2
mloughlin 2025-06-13T13:29:38.901139Z

According to the blog post, for Clojure being hosted on a VM is a con and for Elixir it's a pro

🀨 1
2025-06-13T17:11:16.527429Z

A Haskell program with zero types will still look quite different to a Clojure one. In Haskell you'll model your data with ADTs and GADTs, which you won't do in Clojure. In Clojure you'll use standard data-structures to model your data. And for behavior in Haskell you'll use monad chaining, typeclasses, and effect systems. Those you most likely won't use in Clojure either, though you kind of do with protocols, monad-like macros or full on monadic libraries and effect systems exist if you really want them. But even these will feel very different and have a more of a leaner feel to them. The rest will differ a lot more too. So even ignoring static types, programs will look dramatically different.

πŸ’― 1
dpsutton 2025-06-12T19:34:30.160729Z

it will compile and crash at runtime

Bob B 2025-06-12T19:34:31.042799Z

Did you try it? It will compile and throw an exception when executed.

Krishnansh Agarwal 2025-06-12T19:39:41.213789Z

Hm, this gives me the ick that I hate at my job when writing JS. Are there work-arounds for it ?

Krishnansh Agarwal 2025-06-12T19:40:42.566889Z

@highpressurecarsalesm no, I am just exploring the language, haven't even setup dev env or written first lines for Clojure. I was reading the web pages on its side and it's written in a easy to way to understand stuff πŸ™Œ

2025-06-12T19:45:41.338789Z

you can use run-time validation libraries like clojure.spec or malli or plumatic schema, but there is nothing built in

Krishnansh Agarwal 2025-06-12T19:54:50.128729Z

Okay! Is there a way to embrace dynamic programming?! Because I write Haskell/Go in my part time and it feels like I can't live without types.

2025-06-12T19:56:35.902019Z

hmmm i do not have a strong background in languages like Haskell, so it's hard to make a good recommendation except exposure

oddsor 2025-06-12T20:13:14.488699Z

Since you mentioned that you haven’t set up a dev environment I wonder if maybe a good first step to embracing dynamic programming would be to try to get started with something like https://calva.io/. The important part is to be able to start up a repl, https://calva.io/connect/#jack-in-let-calva-start-the-repl-for-you and then open up a clojure-namespace (file). The way we usually work is to write code in a file and then evaluate either the entire file, or parts of the code to test things out rapidly. So where a type system would save you from silly type errors, we discover those kinds of issues by just running our code frequently. Not sure if that made sense?

πŸ‘ 2
βž• 2
Bob B 2025-06-12T20:25:33.840289Z

I'd say the thing to do is maybe watch a talk or browse Clojure's HOPL paper to get some idiomatic context, and start playing with it. Just to make the distinction, Clojure has types, it just doesn't do static type checks at compile-time (at least, not to the extent done in languages like haskell and go). "types" is quite a broad topic, and many of the aspects commonly associated with "types" (e.g. polymorphism) are available in Clojure, sometimes via "types", sometimes in other ways. A lot of it comes down to trade-offs - the notion of being unable to live without static type checking is maybe not super-compatible with a language that doesn't do them. There's typed clojure (<https://typedclojure.org/guides/getting_started>), which provides some type checking, but you're almost certain to run into lots of library/platform code that doesn't use it, so it's not a universal thing. Perhaps a thing to consider is not only what static type checking gives, but also what it takes away. For example, there's a saying in Clojure circles: "just use maps". Especially for aggregates, the flexibility that comes from dynamism can open doors to making app changes less global/invasive.

seancorfield 2025-06-12T20:28:35.735339Z

@krishnansh710 In my experience -- 40+ years in various languages, including building compilers and runtime systems -- whether folks prefer static or dynamic typing is exactly that: a personal preference. Some folks are very attached to static types and really cannot program without them. Some folks really don't like static typing and find it very frustrating and restrictive. To "get" Clojure, you really have to be ready to let go of types, learn to work interactively and incrementally with the REPL, and you'll either like it or not.

seancorfield 2025-06-12T20:30:19.529369Z

Maybe watch some of Rich Hickey's talks where he talks about static typing and why he doesn't like it (and why Clojure doesn't have it)?

seancorfield 2025-06-12T20:33:05.052599Z

https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/EffectivePrograms.md covers some of this (about halfway through) but searching that repo for static typing will find several other references in other talks.

seancorfield 2025-06-12T20:36:55.091739Z

There's a section further on where he talks about Simon Peyton-Jones and "The Joy of Types" and Rich says: The biggest errors are not caught by these type systems. You need extensive testing to do real-world effectiveness checking. Names dominate semantics, a to a, list of a to list of a, it means nothing, it tells you nothing. If you take away the word "reverse", you don't know anything, you really don't. And to elevate this to say, "oh this is important thing, we have all these properties", it's not true, it just isn't true. There are thousands of functions that take a list of a and return a list of a. What does that mean? It means nothing. And checking it...I mean, if you only had a list of a-s, where you gonna get something else to return? I mean, obviously you're going to return a list of a-s, unless you're, you know, getting stuff from somewhere else, and if you're functional, you're not.

πŸ‘ 1
2025-06-12T22:50:53.210229Z

To repeat the above, but succinctly, we avoid the JS "ick" in Clojure by not writing a program and then seeing whether it runs. Instead we run forms incrementally and accrete them into functions and functions into programs. By the time the program exists, it works.

☝️ 7
1
2025-06-13T01:27:28.259499Z

1. The JS ick is compounded because it won't always error at runtime either, so at least here it errors at runtime 2. When you code, you are at runtime, this is unlike in other languages, my code is first ran in the Repl, and after I see that it works, it is saved to a file. So you still get to know about the issue almost immediately. This also lets you know almost immediately about even more subtle issues, like that it might not even be adding to what you expect 3. If you try to walk through a bushy forest with uneven ground, wet marshy areas, thorns, etc. You are going to want protection. I would say JS is like that, so you'd really want it to have types to protect you. But Clojure, at least the one I write and the teams I've been on have written, is like walking through a manicured Japanese garden, you'll even want to take off your shoes to feel the soft ground under you. (Ok I might exaggerate, but at least it'll be more like a bushwhacked maintained hiking trail), bottom line, you don't need as much protection to manage the code base.

Krishnansh Agarwal 2025-06-13T04:49:22.164639Z

Guys the idea above are very new to me. I am always open for new stuff as I my favourite topic of computation is PLT. Reading above statements, Clojure approach to handle shit is very different. I will have to try for myself and make opinions, regardless one thing I am sure is I will learn something new and may open my brain 😁 Another doubt, a language like Haskell, you can go on and write it without any type notation, as it has 10p% type inference, I think many modern langauges have it. Roc-lang, I am looking forward to it a lot, has it too. So a Haskell program with 0 types will look similar to Python/Clojure ?, as all 3 of them are types. Python is strongly typed as is Clojure. So Python and Clojure, compiler/interpreter are just escaping the "The Type Checker" .. Guys can you point me to some resources ? Preferably, a intermediate stuff as I have been programming for a while, so I will be able to get up paired with http://Clojure.org excellent articles (I gotta say it's written by a poet 🀨) and an idiomatic resource about how to think the Clojure way or solve software problems in a Clojure way. Much thanks πŸ™

Krishnansh Agarwal 2025-06-13T04:54:24.450169Z

Btw, another question is eating my brain alive. I recently came across a very simple and fascinating blog (https://monkeyjunglejuice.github.io/blog/best-programming-language-for-beginner.essay.html), how is Clojure different from 2 other modern lips like Common Lisp and Racket (Racket has the best Typography and UI I have seen in a while) The author of the blog mentions that Clojure is the most programmatic and practical Lisp as it has the backing of JVM, but he goes on to mention that most of your code starts looking Java then. Q1) Is it true? Q2) If yes is this by design and choice, or is just a drawback to use VM hosted langauge ?

exitsandman 2025-06-13T06:49:10.846329Z

Clojure being a hosted language was a very deliberate choice, it meant having access to a highly optimized, always updated and portable platform and of course a lot of libraries. However idiomatic Clojure doesn't look like Java at all, not least because even if you do use Java libs the general approach stays the same.

πŸ‘ 1
βž• 1