It feels like anything is mowed down on the internet. I’ve been a dev for a long time too, and I never feel sure when I chose a stack for a new toy project (in my day job I rarely get to chose, so that’s a non issue there)
There is a good quote from Bjarne Stroustrup for that “There are only two kinds of languages: the ones people complain about and the ones nobody uses”. I think for hobby projects it’s the best to use languages that interest you
There are two types of programmers, those who write buggy code and those who never do anything.
This for sure. At work (fe dev), I need to get things done quickly and reliably, so I use Svelte. At home, I’m just playing around, so I’ll try things that are out of my wheelhouse or strange, eg rn I’m rebuilding the site I always rebuild in Qwik, Go, and Surrealdb - why? Because they seem neat. (Though I might just rm rf that to build something on Bun, because is there anything is can’t do?)
There are only two kinds of languages: the ones people complain about and the ones nobody uses. - Bjarne Stroustrup
I think people criticise every language. I’ve generally got 5 languages that I use personally and for work: Rust, Go, Python, JS, PHP. I can complain about all 5 of them at the drop of a hat. No one likes everything about any language.
Haskell, because nobody knows haskell
Unfortunately, no one can be told what a monad is. You have to see it for yourself (then you won’t be able to explain it to anyone)
The problem is people constantly try to explain it using some kind of real world comparison to make it easier to visualize (“it’s a value in a context”, “it encodes side effects”, “it’s a way to do I/O”, “it’s just flatmap”, “it’s a burrito”), when all it really is is an abstraction. A very, very general abstraction that still turns out to be really useful, which is why we gave it the cryptic name “monad” because it’s difficult to find a name for it that can be linked to something concrete simply because of how abstract it is. It really is just an interface with 2 key functions: (for a monad M)
- wrap: (x: T) => M[T] // wraps a value - bind: (f: (y: T) => M[U], x: M[T]) => M[U] // unwraps the value in x, potentially doing something with it in the process, passes it to f which should return a wrapped value again somehow, and returns what f returns
Anything that you can possibly find a set of functions for that fits this interface and adheres to the rules described by someone else in this thread is a monad. And it’s useful because, just like any other abstraction, if you identify that this pattern can apply to your type M and you implement the interface, then suddenly a ton of operations that work for any monad will also work for your type. One example is the coroutine transformation (async/await) that is an extremely popular solution to the Node.JS “callback hell” problem that used to exist, and which we call do-notation in Haskell:
// instead of const getPostAuthorName = foo => getPost(foo).then(post => getUser(post.authorId)).then(user => user.username) // you can do this const getPostAuthorName = async foo => { const post = await getPost(foo) const user = await getUser(post.authorId) return user.username }
This is a transformation you can actually do with any monad. In this case
Promise.resolve
is an implementation ofwrap
, andthen
is an implementation ofbind
(more or less, it slightly degenerate due to accepting unwrapped return values from f). Sadly it was not implemented generally in JS and they only implemented the transform specifically for Promises. It’s sad because many people say they hate monads because they’re complex, but then heap praise on Promises and async/await which is just one limited implementation of a monad. You may have noticed that generators withyield
syntax are very similar to async/await. That’s because it’s the exact same transformation for another specific monad, namely generators. List comprehensions are another common implementation where this transform is useful:// instead of const results = [] for (const x of xs) { for (const y of ys) { results.push({ x, y }) } } // you could have const results = do { const x = yield xs const y = yield ys return wrap({ x, y }) }
Another (slightly broken) implementation of monads and the coroutine transform people use without knowing it is “hooks” in the React framework (though they refuse to admit it in order to not confuse beginners).
Fuck… I actually just wanted to write a short reply to the parent comment and devolved into writing a Monad Tutorial…
Thought I’d finish the Monad Tutorial since I stopped midway…
The general notion that the abstraction actually captures is the notion of dependency, the idea that an instance x of your type can be in some common operation dependent on other instances of your type. This common operation is captured in
bind
. For Promises for example, the common operation is “resolving”. In my first post, for thegetPostAuthorName
promise to resolve, you first need to resolvegetPost
, and then you need to resolvegetUser
.It also captures the idea that the set of dependencies of your x is not fixed, but can be dynamically extended based on the result of the operation on previous dependencies, e.g.:
const getPostAuthorName = async foo => { const post = await getPost(foo) if (post === undefined) return undefined const user = await getUser(post.authorId) return user.username }
In this case,
getPostAuthorName
is not dependent ongetUser
ifgetPost
already resolved to undefined. This naturally induces an extra order in your dependents. While some are independent and could theoretically be processed in parallel, the mere existence of others is dependent on each other and they cannot be processed in parallel. Thus the abstraction inherently induces a notion of sequentiality.An even more general sister of Monad, Applicative, does away with this second notion of a dynamic set and requires the set of dependents to be fixed. This loses some programmer flexibility, but gains the ability to process all dependents in parallel.
Isn’t a monad just a monoid in the category of endofunctors?
deleted by creator
Ohhhh, this site is a great find. Exploring all the articles right now. Thanks!
If you use JavaScript, you’ve probably seen a monad, since Promise is a monad. Unit is
Promise.resolve()
, bind isPromise.then()
. As required,Promise.resolve(x).then(y) === y(x)
(unit forms a left identity of bind),y.then(Promise.resolve) === y
(unit forms a right identity of bind), andx.then(y.then(z)) === x.then(y).then(z)
(bind is essentially associative).You even have the equivalent of Haskell’s fancy do-notation (a form of syntactic sugar to save writing unit and bind all over the place) in the form of async/await. It’s just not generalized the way it is in Haskell.
Monads 👁️👄👁️
Honestly, I would advise to not pick a language based on popularity, hate, or whichever of those qualify as internet fame these days.
I would approach the question with what you want to get out of your toy project. Do you want to get something done? Then pick a language that is close to what you are already familiar with. Do you mainly want to learn something? Go with a language with concepts you are unfamiliar with, eg. pick a functional language if you mostly do OOP stuff or pick a low level language when you mostly do high level web stuff.
My advice, generally speaking, is: When you do something in your spare time, don’t spend it on things you already do at work. The way to improve in software development is to see problems from many different angles and to rethink the solutions you already know.
Whenever I tested something that sounds great yet it is slow to get adoption I end learning a reason why it it’s not growing. It’s good to learn what the reason is before you spend a lot of time on it
No amount of reading will replace experience. At some point you will come to the place where you’ll be the one who know why something that sounds good won’t be and why it won’t get adopted, but if you only base your decision on the opinions of others, you’ll never really learn anything.
C# doesn’t have a big spotlight on it like Rust or Python, but it is a popular and very unhated language. It’s a good language that is regularly improving and has phenomenal documentation. Seriously, I’ve not gone to Stack Overflow for anything C# (outside of third-party libraries) for years; Microsoft’s documentation gives me everything I need.
As a Linux user / human, obligatory fuck Microsoft. As a .NET dev, what they’ve done with C# is really great and it’s a very pleasant language and ecosystem to work with.
It is incredible really, I worked with C# for so long, and I tend to be very critical of the stuff I’ve used for a long time. For C#, I am struggling to figure how I would improve it, because all the stuff that suck in C# is usually the lesser of two evils.
Of course if you hate classes, types, managed memory or anything invented in the last 20 years you will hate it, and I’ve met people like this. That is why you gotta keep learning as a dev, you don’t want to be one of those.
The 2 that I struggle with on a daily basis:
-
missing discriminated unions. Third party libraries kind of sort of fill the gap, but it’s a pain point.
-
a flawed async programming model. Namely, there are multiple models (for historical reasons / backwards compatibility), and the more current one (task-based) throws a wrench in your ability to effectively design interfaces, functions, delegates etc. that can be shared between synchronous and asynchronous code. Green threads would have fixed this, at the cost of some other potential issues, but it looks we’re stuck with tasks for now. Also, there is the awkwardness of needing to constantly use .ConfigureAwait(false) after every await, unless you shouldn’t (e.g. in the UI thread), and if you get it wrong you might cause a deadlock in your app but not in a console app… A bit confusing and easy to mess up.
F# will give you discriminated unions and do-notation (it calls it ‘computational expressions’) while retaining full access to the .net ecosystem.
I really like ReactiveX for async programming, though having to go through a library is definitely a pain. It also does not make it less awkward to design your public API unless you’re okay exposing Rx types. Fair points!
-
As humans we (you are human, right?) have a negativity bias. Working projects are better than perfect tech stacks. Seriously. Anything even half way working is infinitely better than anything in your head. Just pick something and go, especially for you projects.
There is a bot posting ai generated stuff on my server, but this is my normal account, to post normal human things
Oh yeah?
- [ ] I am not a robot
Solve that.
I am a fellow organic food ingesting, carbon based human, using my meat based appendices to slowly communicate with other carbon based humans on the public network. While I type this my meat based appendices are getting very tired, because I totally had to use mechanical movements to close electrical circuits in a very inneficient way to send signals to a computer
A lot of the criticisms at specific languages are really directed at people. Especially those that have “{language} brain”. These people are of the opinion that everything looks solvable by said language even if it isn’t the best tool for the job.
If you pick the best tool for the job, no one has standing to rightly criticize you. What’s the right tool? One that you know (or have the ability to learn) and has proven itself in its ability to solve problems you’re seeking to solve.
As a society and as individual computer scientists, none of us actually know what a computer is or how to use them. All programming languages are guesses, mere attempts to encode our natural-language reasoning and philosophy in the purely syntactic and formal fashion required by computers. Don’t let yourself become biased in favor of specific languages; instead, understand that all languages are bad in different ways.
And don’t forget, that much of what people criticize isn’t the language per se, but the community/ecosystem around it.
NPM is objectively bad, but Javascript is by no means coupled to it.
Java projects are often very “verbose”, but that’s a choice by the developer of the libraries and apps, not so much Java itself.
Ecosystems matter, though. In fact, I think they’re the hardest part to learn for most languages.
You can try to get away from NPM, but you’ll always run across instructions on how to do a thing in NPM. Do it any other way, and you’re on your own.
You can try to write Java in a less verbose way, but the standard library will fight you before we even talk about third party libs.
I never argued, that they don’t matter.
There are two types of languages, those that people complain about and those that noone uses. Though rust has been voted the most loved for many years now on the stackoverflow yearly survey, and for good reason IMO.
Qt & C++ because KDE doesn’t allow feedback.
KDE does not develop Qt and is not c++ comitte
Yeah, wasn’t suggesting they were. KDE uses them. Since they’re not willing to take user feedback, thought I’d mention it here.
you got me laughing here
Definitely Verilog
It is not programming language. Good stuff.
deleted by creator
Every languages has their own pitfalls. The answer on picking a language is to pick whatever works for you. There may be even domain-specific languages if you’re interested in a domain, and it can be way more flexible than general-purpose solutions for that domain too.
I use 4 languages.
- C++ for adding features to a program.
- C# for making .dll for an application (
Paint.NET
). Kinda similar purpose to what I do with G’MIC, except so much more limited. - Python for processing strings
- G’MIC for creating/editing raster graphics images (volumetric too)
Now, I wish there was a vector equivalent to G’MIC, but there isn’t.
I haven’t seen any negative criticism on chillicheescript here.
Brainfuck, GLSL
Pick a movie. Any movie. You will always find reviews both praising it and disparaging it.
Programming languages are similar. People will always have their opinions about things. It’s your choice to try them and decide for yourself if you like them.
Just don’t choose PHP ;)
I loved this analogy, it works for old languages as old movies, some characteristics as movie genres and to explain there is not just one and only right language, and that people would have different preferences.