Weird Languages(paulgraham.com)
paulgraham.com
Weird Languages
http://paulgraham.com/weird.html
520 comments
My problem with these arguments from PG is that they require that you pretend (or ignore) all the real world evidence we have about what languages are actually useful to make things with. It’s all fine and well to talk about how great X and Y is, but meanwhile most people are actually making things in Java and Go.
You don't have to use a language to benefit from its existence. Haskell is a weird language that nobody* uses in production, but it's where a lot of functional programming concepts were refined and ultimately made their way into mainstream languages. I use functional programming tools in Java and JS very often and they only exist because many people tried Haskell, saw the potential of this new* paradigm and implemented parts of it into their environments.
Similarly, having been forced to learn Prolog in university, I now have a completely different view of solving problems. And while I'll surely never touch Prolog again, this new perspective allows me to write much better code in some cases, despite working in a completely different language.
Similarly, having been forced to learn Prolog in university, I now have a completely different view of solving problems. And while I'll surely never touch Prolog again, this new perspective allows me to write much better code in some cases, despite working in a completely different language.
I used to argue this. Then I watched multiple engineers under me and next to me ignore this argument in favor of focusing on distributed system design and clear communication. The results have persuaded me that I was wrong, and they were right.
In the end the most effective people around me are capable of designing a system and breaking it down effectively for other engineers to build. Most of them have no idea what things like Monads and Functors are, and they’re no less effective for it.
In the end the most effective people around me are capable of designing a system and breaking it down effectively for other engineers to build. Most of them have no idea what things like Monads and Functors are, and they’re no less effective for it.
I second this. It's always about learning the mindset even if you don't use it for real life. Same for learning mathematics, music, philosophy, etc. It becomes your mental model to apply to other aspects of life.
But what real world evidence do we have? Mostly that languages "most people are actually making things in" are picked by the business on the basis of popularity, which is determined mostly by what people learn in university - which is determined mostly by what is currently most popular on the job market. It's a self-sustaining feedback loop that has little to do with relative utility of languages for real-world problems (at least discounting languages' library ecosystems).
This argument is self refuting. If inferior programming languages are being picked continuously by “the business”, we’d expect that businesses that pick “superior” programming languages to out compete the other businesses. We don’t see this, so one of the following is true:
1) Programming language quality is a non-factor in business success.
2) People like PG are wrong about what makes one language superior to another.
By the by, I have never seen a non-programmer executive demand a “bad” language be used for a startup. What I tend to see is grizzled ex-programmers ignoring the trends and picking the reliable and “boring” choice over the complaints of some IC’s. This is less a “clueless business” issue and more an acknowledgment of an unpopular truth: picking the boring language that lets the business focus on its core domain is better than picking something that excites the most vocal engineers.
1) Programming language quality is a non-factor in business success.
2) People like PG are wrong about what makes one language superior to another.
By the by, I have never seen a non-programmer executive demand a “bad” language be used for a startup. What I tend to see is grizzled ex-programmers ignoring the trends and picking the reliable and “boring” choice over the complaints of some IC’s. This is less a “clueless business” issue and more an acknowledgment of an unpopular truth: picking the boring language that lets the business focus on its core domain is better than picking something that excites the most vocal engineers.
The claim that learning weird languages will help you learn new ways of thinking about problems that may be helpful in other langauges, and the claim that using 'boring' languages is the correct default for building production systems, in no way contradict.
Do what you will with your own time, I’m no longer convinced that learning “weird” languages is an effective way to become a better programmer. From my experience as an IC and as a manager, learning how to write better is probably a better investment for professional growth, second to that would be better distributed system design.
If it pleases you, feel free to learn whatever. It’s why I know Rust and Haskell personally. But as career advice I am much more dubious, even though I once agreed with you.
If it pleases you, feel free to learn whatever. It’s why I know Rust and Haskell personally. But as career advice I am much more dubious, even though I once agreed with you.
I find that for a lot of problems reasoning about the core problem using a mental model akin to lisp makes it easier for me to come to a sufficiently clear understanding to be able to better express the solution in both code and prose.
So while I agree about writing prose, it's also true that learning lisp made me a better documenter.
So while I agree about writing prose, it's also true that learning lisp made me a better documenter.
> If inferior programming languages are being picked continuously by “the business”, we’d expect that businesses that pick “superior” programming languages to out compete the other businesses.
That assumes that the software business is efficient in the market sense, which my experience suggests is very much not true. On the contrary, I've found that success hinges primarily on the ability to find and execute good business deals (which is the work of executive team and/or sales&marketing). Software side has so much slack in it that it can (and often does) do extremely bad job at making the actual thing and still succeed.
> I have never seen a non-programmer executive demand a “bad” language be used for a startup.
I've worked for one many years ago. I was actually promised the free reign over technology stack for a project, until the CEO decided to override me and order me to use a very particular and shitty combination of technologies. He was very up-front with me about his reasoning: he said, "yeah, I could let you write this in something more reasonable, say Ruby or Python, but programmers for those languages are expensive, PHP programmers are much cheaper, and I'm going to be hiring more people to help you".
(I run the project solo for the next year, because he eventually decided not to hire anyone.)
> picking the boring language that lets the business focus on its core domain is better than picking something that excites the most vocal engineers.
Be careful not to mix up topics here. What usually "excites the most vocal engineers" these days is the things they can use to pad their CVs. This usually goes against what the management wants, which is whatever stack they've read about on HBR or whatever one is cheapest to hire people for. Neither of those tend to have anything to do with powerful and advanced tooling.
That assumes that the software business is efficient in the market sense, which my experience suggests is very much not true. On the contrary, I've found that success hinges primarily on the ability to find and execute good business deals (which is the work of executive team and/or sales&marketing). Software side has so much slack in it that it can (and often does) do extremely bad job at making the actual thing and still succeed.
> I have never seen a non-programmer executive demand a “bad” language be used for a startup.
I've worked for one many years ago. I was actually promised the free reign over technology stack for a project, until the CEO decided to override me and order me to use a very particular and shitty combination of technologies. He was very up-front with me about his reasoning: he said, "yeah, I could let you write this in something more reasonable, say Ruby or Python, but programmers for those languages are expensive, PHP programmers are much cheaper, and I'm going to be hiring more people to help you".
(I run the project solo for the next year, because he eventually decided not to hire anyone.)
> picking the boring language that lets the business focus on its core domain is better than picking something that excites the most vocal engineers.
Be careful not to mix up topics here. What usually "excites the most vocal engineers" these days is the things they can use to pad their CVs. This usually goes against what the management wants, which is whatever stack they've read about on HBR or whatever one is cheapest to hire people for. Neither of those tend to have anything to do with powerful and advanced tooling.
> yeah, I could let you write this in something more reasonable, say Ruby or Python, but programmers for those languages are expensive, PHP programmers are much cheaper, and I'm going to be hiring more people to help you
It sounds like the exec made the right choice. PHP is a wildly successful language that powers an obscene portion of the Internet web apps.
That’s not a “bad” language, it’s just an annoying one for engineers to work with. A bad language would be one with so little adoption and such a steep learning curve that hiring new software engineers is a year-long path to expanded productivity.
It sounds like the exec made the right choice. PHP is a wildly successful language that powers an obscene portion of the Internet web apps.
That’s not a “bad” language, it’s just an annoying one for engineers to work with. A bad language would be one with so little adoption and such a steep learning curve that hiring new software engineers is a year-long path to expanded productivity.
The further you dig into the matter, the more you realize that most people’s definitions of “good” and “bad” languages map onto their own personal preferences, not anything concrete about the language or how it’s used.
> That assumes that the software business is efficient in the market sense, which my experience suggests is very much not true. On the contrary, I've found that success hinges primarily on the ability to find and execute good business deals (which is the work of executive team and/or sales&marketing). Software side has so much slack in it that it can (and often does) do extremely bad job at making the actual thing and still succeed.
I actually covered this in literally the next line.
I actually covered this in literally the next line.
ashtonkem: To quote what you wrote two sentences afterwards:
> 1) Programming language quality is a non-factor in business success.
What TeMPOral wrote (below) is is not quite the same in my view. First, they elaborate more. Second, there is a different argument:
> Software side has so much slack in it that it can (and often does) do extremely bad job at making the actual thing and still succeed.
Namely: it is NOT the case that software does not have a business effect. Rather, other aspects of the business have to work extra hard to compensate.
To take a systems point of view: two systems can have the same output over some time period but very different internal efficiencies.
> 1) Programming language quality is a non-factor in business success.
What TeMPOral wrote (below) is is not quite the same in my view. First, they elaborate more. Second, there is a different argument:
> Software side has so much slack in it that it can (and often does) do extremely bad job at making the actual thing and still succeed.
Namely: it is NOT the case that software does not have a business effect. Rather, other aspects of the business have to work extra hard to compensate.
To take a systems point of view: two systems can have the same output over some time period but very different internal efficiencies.
This is bullshit because popular languages have changed and emerged from outside of university (see Go, Python, etc that had no university presence and exploded in popularity in industry).
PG's arguments are not forcing you to pretend (or ignore) anything.
I think it's possible you are falling prey to the either/or fallacy.
I think it's possible you are falling prey to the either/or fallacy.
I honestly haven't seen any evidence of this whole "think things you couldn't previously think" idea. The only interesting thing I've seen people be able to do by switching languages, is significantly improving static analysis, in order to save debugging cycles and improve production reliability. But everything else that is "interesting" is just different ways to generate code in order to reduce lines of code written manually, which is convenient, and is certainly fun for nerds like most of us here, but I really don't see it as this superpower that folks like pg seem to believe it to be.
A better analogy for new materials is new techniques, like machine learning and higher order abstractions over it, or new algorithms. But those are independent of languages.
A better analogy for new materials is new techniques, like machine learning and higher order abstractions over it, or new algorithms. But those are independent of languages.
I think it's really about an interplay of mental models and domains. Hers's my one personal datapoint. I did my undergrad in math and discovered functional programming back then. Got real excited about it, read the Learn You a Haskell book and then sort of nothing happened. But I waited on that "mind expanding" stuff to pay off.
Then I got my first job, where they really only cared that I was good in python. Cranked out a bunch of python services, and got good at cloud stuff along the way. Decided FP and that kind of thing was "school stuff."
A few years later I found myself working at another shop doing backend Go/Kotlin. We were increasingly writing a lot of streaming stuff on Kafka, and could tell we weren't really "doing it right." Just gut feel that something was not as good as it could be. So we brought in a senior eng with a bunch of Kafka experience, who just sort of coincidentally had been working in Scala during that experience. We onboarded him onto Kotlin, but the code pretty quickly picked up a Scala style and flavor.
After about a year I couldn't shake the feeling of how perfectly this kind of functional thinking mapped to stream processing services. Especially when you're working on a framework like KStreams or Flink, being able to describe your transformations with these pure non-nullable functions was just perfect for the domain. When you squint a lot of the Option/Either monad stuff really helps you think about your programs as a linear flow of data, which is exactly what stream processing is.
When you look at a lot of the Java api's in the space of big data, they look functional. AFAIK thats not because a bunch of Java devs decided to use all the cutting edge Java functional features. Its because the stuff people were building in Scala just fit the domain so much better. So the Java ecosystem took those ideas and everyone is for the better.
At no point did I develop a superpower. Now I'm back to writing Python stuff in a new domain, and those insights aren't so valuable day to day. I try to make my code a bit more linear and functional, but can increasingly tell its not the practical choice. But if somebody needed me to write a high throughput reliable stream processing thing, I would immediately jump back to those patterns.
Then I got my first job, where they really only cared that I was good in python. Cranked out a bunch of python services, and got good at cloud stuff along the way. Decided FP and that kind of thing was "school stuff."
A few years later I found myself working at another shop doing backend Go/Kotlin. We were increasingly writing a lot of streaming stuff on Kafka, and could tell we weren't really "doing it right." Just gut feel that something was not as good as it could be. So we brought in a senior eng with a bunch of Kafka experience, who just sort of coincidentally had been working in Scala during that experience. We onboarded him onto Kotlin, but the code pretty quickly picked up a Scala style and flavor.
After about a year I couldn't shake the feeling of how perfectly this kind of functional thinking mapped to stream processing services. Especially when you're working on a framework like KStreams or Flink, being able to describe your transformations with these pure non-nullable functions was just perfect for the domain. When you squint a lot of the Option/Either monad stuff really helps you think about your programs as a linear flow of data, which is exactly what stream processing is.
When you look at a lot of the Java api's in the space of big data, they look functional. AFAIK thats not because a bunch of Java devs decided to use all the cutting edge Java functional features. Its because the stuff people were building in Scala just fit the domain so much better. So the Java ecosystem took those ideas and everyone is for the better.
At no point did I develop a superpower. Now I'm back to writing Python stuff in a new domain, and those insights aren't so valuable day to day. I try to make my code a bit more linear and functional, but can increasingly tell its not the practical choice. But if somebody needed me to write a high throughput reliable stream processing thing, I would immediately jump back to those patterns.
I agree with all of this and have seen many of the same dynamics in my career, but it just doesn't seem like this mystical mind altering eureka thing that a lot of people seem to make it out to be. To me it's more like, oh good, here are some more useful techniques that help get stuff done sometimes.
It's a real thing, but I think (extrapolating from my own experience) it's much more profound and tangible if you're starting from something like C or pre-modern C++ and then moving to something more modern and FP-flavored. Modern popular language are on a much more even playing field versus 20 years ago. Even so, I still had one of these mind blowing "things I couldn't previously think" experiences when I finally ventured into Prolog and logic programming a few years ago. It's such an order of magnitude beyond my day to day C++ and Python nonsense, at least up until the evaluation model blows up exponentially.
I'd still like, as a learning exercise, to build some semi-practical small applications in Prolog, but I feel like I'd need an expert mentor to guide me.
I'd still like, as a learning exercise, to build some semi-practical small applications in Prolog, but I feel like I'd need an expert mentor to guide me.
I agree that there aren't a ton of convincing examples mentioned that aren't relevant to people who already agree w/the value of lisp-style macros -- but if you're interested I used the example of erlang when responding to a comment above: https://news.ycombinator.com/item?id=28343140
FWIW I do actually agree w/pg about macros; I use them day-to-day for more mundane things than his impressive fully-bottom-up approach to programming. But each time I do use them, I feel like "thank heavens I don't have to reach for some weird external codegen tool to do this".
FWIW I do actually agree w/pg about macros; I use them day-to-day for more mundane things than his impressive fully-bottom-up approach to programming. But each time I do use them, I feel like "thank heavens I don't have to reach for some weird external codegen tool to do this".
See I don't really feel that way about macros. To me, codegen is codegen, useful for a bunch of stuff but not really anything special, and whether or not it is homoiconic doesn't seem like the fundamental question to me.
Don't get me wrong, I think homoiconicity and macros are really neat, I can get behind the aesthetic appreciation of different programming languages and syntaxes for doing different things. But people seem to want to convince me that there is some mystical mind expanding power to it, rather than just aesthetic nicety, and that's what I find unconvincing.
Don't get me wrong, I think homoiconicity and macros are really neat, I can get behind the aesthetic appreciation of different programming languages and syntaxes for doing different things. But people seem to want to convince me that there is some mystical mind expanding power to it, rather than just aesthetic nicety, and that's what I find unconvincing.
> Languages are solved, not important; I build systems.
This argument always gets funny when sufficiently complicated systems start themselves looking like languages (and their implementations).
This argument always gets funny when sufficiently complicated systems start themselves looking like languages (and their implementations).
I'm not sure it's getting funny. I find it's getting interesting. If the best mechanisms the developers could find to solve a certain problem could be implemented in a language + compiler, does this mean the project should be implemented in this language is? What does this even mean? Maybe it already is implemented in this language? Or is it not, because of the missing syntactic abstraction?
The thought I have related to this is that languages are much like GUIs in this regard. They enable a certain process using some built-in features, but it's next to impossible to abstract over those feature to optimize further.
And I think that is why I stay with a simple language that gives arrays, structs, and function calls - basically tools to manipulate data / memory, I'm not sure that more features are all that useful to write "well-compressed" programs (but I can imagine that it's often hard to see why certain useful seeming features will be detrimental down the road).
The thought I have related to this is that languages are much like GUIs in this regard. They enable a certain process using some built-in features, but it's next to impossible to abstract over those feature to optimize further.
And I think that is why I stay with a simple language that gives arrays, structs, and function calls - basically tools to manipulate data / memory, I'm not sure that more features are all that useful to write "well-compressed" programs (but I can imagine that it's often hard to see why certain useful seeming features will be detrimental down the road).
I think the feeling a lot of people have – or at least the one I have – is just tiredness of al the churn. This year all tables need to be in wood, but in two years wooden tables are soooo old, what kind of old coot are you for using wooden tables?! Is there something wrong with you?! All Real Programmers™ exclusively use steel tables now!
Two years down the line people start to realize that steel actually isn't perfect either. But wait, now someone made a carbon fibre table and we need to break down all our steel tables and burn the few wooden tables left and rebuild it all in carbon fibre! It's the future, after all!
Of course, eventually people figure out that wooden tables are actually quite good for a fair number of use cases and we've come full circle.
I'm just tired of the churn-and-hype cycle and suspect a lot of people have roughly similar feelings, which is expressed in the "languages are unimportant; I build systems"-sentiment. Less and less of modern software development seems to be about actually building interesting things to solve real problems.
Two years down the line people start to realize that steel actually isn't perfect either. But wait, now someone made a carbon fibre table and we need to break down all our steel tables and burn the few wooden tables left and rebuild it all in carbon fibre! It's the future, after all!
Of course, eventually people figure out that wooden tables are actually quite good for a fair number of use cases and we've come full circle.
I'm just tired of the churn-and-hype cycle and suspect a lot of people have roughly similar feelings, which is expressed in the "languages are unimportant; I build systems"-sentiment. Less and less of modern software development seems to be about actually building interesting things to solve real problems.
I'd agree that it's a totally valid sentiment in our industry. In the specific context of an essay on pg's site though -- look at those graphics! :D This seems to me like a dude who is okay with wooden tables.
In my experience, the churn is on the systems side, not languages side. The churn happens because someone makes a marginal improvement on some API and makes a nicer marketing copy, and boom, the new most popular JavaScript framework/bundler for this year is born.
Programming languages don't churn nearly as fast (and some degree of existing churn can be attributed to the business model of a PL funded by a company - they have every incentive to push it, no matter how little improvements or different concepts the language brings.)
Programming languages don't churn nearly as fast (and some degree of existing churn can be attributed to the business model of a PL funded by a company - they have every incentive to push it, no matter how little improvements or different concepts the language brings.)
I resonate with this. The churn I find most demoralizing is in the library/module/component space.
I’ve been pushing myself to learn elixir these last few months. This is, by the comments of many, more of a niche language. I like the language’s novelty and it has caused me to think in new ways. So Paul is righ in this pint.
But when I want to send an http request, there must be at least 10 choices on hex to choose from. The one that is a hit this year will be passe’ next year. When I watch the traffic in the Phoenix slack channel, the “stack” of libraries combined seems overwhelming. The same goes for people talking about front end apps.
I’ve been pushing myself to learn elixir these last few months. This is, by the comments of many, more of a niche language. I like the language’s novelty and it has caused me to think in new ways. So Paul is righ in this pint.
But when I want to send an http request, there must be at least 10 choices on hex to choose from. The one that is a hit this year will be passe’ next year. When I watch the traffic in the Phoenix slack channel, the “stack” of libraries combined seems overwhelming. The same goes for people talking about front end apps.
You hit a nerve there - our company has gone through 4 "choice" http client libraries in the past 4 years. (We're a JS/TS environment). axios, request, superagent, fetch.
Just curious, why not use OTP's built-in httpc? https://erlang.org/doc/man/httpc.html
Not OP, but httpc isn't secure by default. It works fine if you hold it correctly but I wouldn't recommend it to someone really new to the language.
https://erlef.github.io/security-wg/secure_coding_and_deploy...
https://erlef.github.io/security-wg/secure_coding_and_deploy...
httpc is good for a one off request, but it is not very up-to-date with the latest features of the web. So building application logic on top of it is not ideal.
Churn and choice are what keeps me on the fence with Elixir too. Over the last few years I went from very excited and built a few things with it to "maybe try again later".
It's just not fun to be in a constant state of package fatigue, especially when a lot of semi-popular libraries are maintained by 1 person. If that 1 person leaves that entire bit of functionality becomes a liability to your application because it's unrealistically demanding to be a solo developer or small team and be responsible to maintain a bunch of libraries that become unmaintained but then also build your application.
This is IMO especially true with a language as powerful as Elixir with macros. Picking up and reading someone else's code can either feel natural or be really hard, to the point where looking at it doesn't feel like the language you know. This makes it doubly hard to read 3rd party library code because you're learning the other person's code and have to mentally deconstruct a lot of advanced patterns if they use them. I don't consider myself that good of a programmer but there's a lot of times where in Elixir, phrases like "this is impossible for me to understand" come up when I've written hundreds of thousands of lines of code in Python but never thought this. I sometimes had the "what am I looking at?" feeling with Ruby too btw.
As for library availability, this is a problem that doesn't come up as often with more main stream web frameworks, at least not in the Python and Ruby eco-system. Sure things go in and out of fashion but both languages have frameworks that include more batteries included or the community has gotten so big that there's a bunch of independently developed libraries that most of the community got behind and supports it so well that it becomes a no-brainer to use it.
So that's what keeps me on the fence and I think some of these problems can be solved with time, but time is a scary thing because waiting a few years feels like an eternity and the outcome after waiting a few years might be waiting a few more years. At some point you need to build whatever you're building and run with it without looking back.
But I think this really comes down to personal preference. I used to think I wanted unlimited choice and an endless world of possibilities. I don't. I want to build web applications quickly using the most straight forward code I can think of and get as many batteries as included as possible while leaning on / contributing back to a massive eco-system. I don't want to be on the front lines of building a new eco-system. I still do think in the very long term (5+ years maybe) Elixir could be a good match for me once there's a lot of libraries that have hit critical mass.
There's plenty of people using it successfully now, and I'm happy there are people who like being closer to early adopters and setting up the initial ground work for an eco-system.
It's just not fun to be in a constant state of package fatigue, especially when a lot of semi-popular libraries are maintained by 1 person. If that 1 person leaves that entire bit of functionality becomes a liability to your application because it's unrealistically demanding to be a solo developer or small team and be responsible to maintain a bunch of libraries that become unmaintained but then also build your application.
This is IMO especially true with a language as powerful as Elixir with macros. Picking up and reading someone else's code can either feel natural or be really hard, to the point where looking at it doesn't feel like the language you know. This makes it doubly hard to read 3rd party library code because you're learning the other person's code and have to mentally deconstruct a lot of advanced patterns if they use them. I don't consider myself that good of a programmer but there's a lot of times where in Elixir, phrases like "this is impossible for me to understand" come up when I've written hundreds of thousands of lines of code in Python but never thought this. I sometimes had the "what am I looking at?" feeling with Ruby too btw.
As for library availability, this is a problem that doesn't come up as often with more main stream web frameworks, at least not in the Python and Ruby eco-system. Sure things go in and out of fashion but both languages have frameworks that include more batteries included or the community has gotten so big that there's a bunch of independently developed libraries that most of the community got behind and supports it so well that it becomes a no-brainer to use it.
So that's what keeps me on the fence and I think some of these problems can be solved with time, but time is a scary thing because waiting a few years feels like an eternity and the outcome after waiting a few years might be waiting a few more years. At some point you need to build whatever you're building and run with it without looking back.
But I think this really comes down to personal preference. I used to think I wanted unlimited choice and an endless world of possibilities. I don't. I want to build web applications quickly using the most straight forward code I can think of and get as many batteries as included as possible while leaning on / contributing back to a massive eco-system. I don't want to be on the front lines of building a new eco-system. I still do think in the very long term (5+ years maybe) Elixir could be a good match for me once there's a lot of libraries that have hit critical mass.
There's plenty of people using it successfully now, and I'm happy there are people who like being closer to early adopters and setting up the initial ground work for an eco-system.
As someone who just started learning Elixir, this comment makes me anxious. I don't think I am going to write some exotic web application or some unique functionality, but at the same time I also don't want to be constantly fighting with the limitations of the stack I choose.
Is it a mistake to spend time learning Elixir?
Is it a mistake to spend time learning Elixir?
Elixir is an involving platform and community. Think about the Ruby community from years ago, a lot of things are missing, but there is a lot of potentials as well. From my side, I started to see Elixir seriously 5 years ago when I need to maintain a big SaaS rails codebase, and in order to support the increasing quantity of users, I need to throw more powerful and expensive machines, and it was hurting us at that time, and after some POCs, we perceived that it would be really interesting to rewrite some parts of our application in Elixir with Phoenix. I think that it's an important tool to have at hand, something that you can reach if needed.
I wouldn't say it's limiting in the sense you can't create certain things with it. You just need to be very prepared to maybe make more choices and also write a lot more libraries that you could potentially find in Python or Ruby.
It also depends on the app you're building. For me I was building a very large app (a video course platform with multiple payment gateways). One limitation I came across with Elixir is there's no official SDKs for Stripe, PayPal, Braintree or Paddle but there are SDKs for most other popular languages. So if you plan to interface with a number of APIs, chances are you're not going to find an official client for Elixir unless the company happens to be using Elixir or are happy to support it (such as Mux).
It could be challenging and time consuming to have to write both your app level features and the underlying libraries. If your goal is to get a web app launched quickly to test it out and you already have experience with Python, Ruby, Node or PHP it's kind of a hard sell to use Elixir. It's mainly because other languages have way more community libraries and frameworks available that cover common web feature use cases. Plus there's a lot more community resources around blog posts, videos, books, courses, etc..
There's also an interesting divide right now in Phoenix around using Live View or not and if you go down the LV route there's very few resources beyond the docs, especially now with LV 0.16 coming out which completely changed the templating system and how components work. It still feels like it's in a pre-1.0 (because it is :D) semi-experimental state. As far as I know there's also no really big success stories with LV. I don't know of any big sites who are using it all-in to drive the entire navigation of their site and all routes.
The above continues to fall in line with my overall feeling of having choice fatigue with Elixir.
With that said if you're interested in it, maybe try to put together a proof concept that focuses on the hardest part of your app and if it works, make a judgment call based on your personal experience. It's possible you'll have better luck than I did. Programming language selection is a very personal choice, especially when you get past libraries choices and start writing code. If Elixir clicks enough for you at a fundamental level maybe it'll be a better choice even if it means having to write more libraries.
It also depends on the app you're building. For me I was building a very large app (a video course platform with multiple payment gateways). One limitation I came across with Elixir is there's no official SDKs for Stripe, PayPal, Braintree or Paddle but there are SDKs for most other popular languages. So if you plan to interface with a number of APIs, chances are you're not going to find an official client for Elixir unless the company happens to be using Elixir or are happy to support it (such as Mux).
It could be challenging and time consuming to have to write both your app level features and the underlying libraries. If your goal is to get a web app launched quickly to test it out and you already have experience with Python, Ruby, Node or PHP it's kind of a hard sell to use Elixir. It's mainly because other languages have way more community libraries and frameworks available that cover common web feature use cases. Plus there's a lot more community resources around blog posts, videos, books, courses, etc..
There's also an interesting divide right now in Phoenix around using Live View or not and if you go down the LV route there's very few resources beyond the docs, especially now with LV 0.16 coming out which completely changed the templating system and how components work. It still feels like it's in a pre-1.0 (because it is :D) semi-experimental state. As far as I know there's also no really big success stories with LV. I don't know of any big sites who are using it all-in to drive the entire navigation of their site and all routes.
The above continues to fall in line with my overall feeling of having choice fatigue with Elixir.
With that said if you're interested in it, maybe try to put together a proof concept that focuses on the hardest part of your app and if it works, make a judgment call based on your personal experience. It's possible you'll have better luck than I did. Programming language selection is a very personal choice, especially when you get past libraries choices and start writing code. If Elixir clicks enough for you at a fundamental level maybe it'll be a better choice even if it means having to write more libraries.
No. I'd say even if you don't end up using it in your day to day, learning elixir/Erlang and reading Armstrong's thesis are some of the best things you can do for yourself in terms of "system design/programming enlightenment".
It’s not just how many variations of a given component there are, it’s all the many components I have to become aware of to use, each written by a different author with possibly diffeeent idioms, with varying degrees of interoperability. One has to have an http package, an auth package, a json package, a structure modeling package, the list just goes on and on and on. And so many are often derivative dependencies. It’s not just elixir.
When I look for help in the Kotlin slack, the responses are just a firehouse of “you need Zanzibar, no Algolly, try Firetruck, do Conduct, you might want xWyze…”
When I look for help in the Kotlin slack, the responses are just a firehouse of “you need Zanzibar, no Algolly, try Firetruck, do Conduct, you might want xWyze…”
All the passé options still work fine :)
But yes. It's true http clients have churned quite a bit. Other things are settling better, for instance Ecto, Phoenix, Jason are very popular and stable.
But yes. It's true http clients have churned quite a bit. Other things are settling better, for instance Ecto, Phoenix, Jason are very popular and stable.
I think this is also why a lot of older programmers (or even older workers in general) get mistakenly labelled as "resistant to change". It's not that we're unwilling to learn new things, quite the contrary. It's that we've been to enough rodeos to see that many "new" solutions are either pure hype or repackaged versions of stuff that was already tried and found lacking.
I believe this label is less likely to apply to an older programmer if instead of grumbling they were willing or able to clearly communicate problems and consequences of “new” solutions. They would be labeled “old wizards” instead :)
There's some truth to that, but I don't think better communication would really change anything, beyond a few minor victories here and there.
So much of the fetishization of everything "new" comes from a combination of wishful thinking and mental laziness. Especially in larger organizations where decisions are made far from where the work is actually done, there is a tendency to think we can solve problems simply by embracing the newest management fad, enterprise software, etc. It's kind of like the way people think they can get organized "if only they had the right trendy organizer or todo app".
I get the impulse, we desperately want to believe that our hard problems can easily be solved by just changing one thing or buying something. This is the crux of most modern marketing, in fact. Unhappy happy with something hard, just by product or service X.
Older workers tend to know better than others that hard things are hard and that layering some shiny new tool or framework on top of crappy process or a broken business model will not change anything. But saying that out loud, even tactfully, is a very inconvenient truth that will make most managers resent you, and probably label you "resistant to change".
So much of the fetishization of everything "new" comes from a combination of wishful thinking and mental laziness. Especially in larger organizations where decisions are made far from where the work is actually done, there is a tendency to think we can solve problems simply by embracing the newest management fad, enterprise software, etc. It's kind of like the way people think they can get organized "if only they had the right trendy organizer or todo app".
I get the impulse, we desperately want to believe that our hard problems can easily be solved by just changing one thing or buying something. This is the crux of most modern marketing, in fact. Unhappy happy with something hard, just by product or service X.
Older workers tend to know better than others that hard things are hard and that layering some shiny new tool or framework on top of crappy process or a broken business model will not change anything. But saying that out loud, even tactfully, is a very inconvenient truth that will make most managers resent you, and probably label you "resistant to change".
They do. It's the nature of new programmers to be prone to hype and marketing and not understand those "clearly communicated problems and consequences" as anything but grumbling.
In my experience more often than not, the people the people that accuse others of unclear communication are making an effort into not understanding the message.
But then, I'm not known for fighting against new solutions either, so that experience is probably in a disjoint population. Anyway, I imagine you say that from the position of an "old wizard", but that position is as dependent on a receptive audience as it is on a communicative "wizard".
But then, I'm not known for fighting against new solutions either, so that experience is probably in a disjoint population. Anyway, I imagine you say that from the position of an "old wizard", but that position is as dependent on a receptive audience as it is on a communicative "wizard".
They’re grumbling because they’ve been there done that, too — tried to communicate the ills of frivolous changes — and nobody was interested in paying attention.
I think we are on the same page that communications are a two-way street. There must be mutual desire to listen carefully and to speak clearly.
My comment above focuses on what the stoics advised to focus on - the things one is in control of changing. In our case, old wizards could control their attitude.
My comment above focuses on what the stoics advised to focus on - the things one is in control of changing. In our case, old wizards could control their attitude.
IF there is a lot of churn you will need to do a lot of communicating, but obviously some times the new will succeed, as time goes by with all the churn and all the poor decisions you would get glum at the prospect at communicating yet again why you think a new solution is not preferable.
I don't actually care though, just I can see this possibility.
I don't actually care though, just I can see this possibility.
It is a fashion industry, and so it follows that when everyone has wooden tables you need to sell them a reason to stay in business, repairing wooden tables isn't enough.
Yup. The ugly truth is that there are too many programmers writing too much code. It's like the idea of too many lawyers (possibly true?) but way worse. Because, of course, we can produce infinite wood and steel and carbon fibre tables at will at the press of a button.
Re: 2nd sentence : How do you come to this conclusion?
Oh, I am a lawyer. I was more recognizing the cliche here, and maybe that was sort of flip. I would say it's probably more like, "a lot of good lawyer brains are wasted on generally pointless this-big-ass-company v. that-big-ass-company disputes."
> What can you say in this language that would be impossibly inconvenient to say in others?
Maybe it's just me and my possibly-unreasonable infatuation with the Sapir-Whorf hypothesis (SWH) but I've come to think it also applies to many things in life, PLs especially so. "Weird languages" aren't valuable because you can deploy it in production, rather because it will help you recontextualize a problem (in SWH-parlance, it helps you see the world differently).
You can also say, SWH is an academic formulation of the beloved programmer motto "When all you have is a hammer, everything looks like a nail". If all you know is an imperative syntax, all problems look solvable by breaking them down into a series of steps/procedures.
In my almost ten years in the industry, there's exactly one time I was able to apply an "unusual" paradigm to solve a problem. GvR might curse me because I sort of made a Lisp-like DSL in Python but I stand by my design decision. The end-result was a small (~200LoC linted with black) DSL parser with some DB access and a lot of rules which actually tried to solve the problem. When I found something wrong I just had to reformulate a rule, not actually wrangle with loops, conditionals, and control flow in order to rewrite logic.
Honest negatives: I had to turn over the project to someone whose background is in EEE, not CS, and I had to explain Higher-Order Functions to them. Not ideal! Actually, in fairness, I bet most in that team would have a hard time figuring it out because, hey, I made a Lisp in Python! But I still stand by my decision; it was the best for the problem given the resources and time I had.
Maybe it's just me and my possibly-unreasonable infatuation with the Sapir-Whorf hypothesis (SWH) but I've come to think it also applies to many things in life, PLs especially so. "Weird languages" aren't valuable because you can deploy it in production, rather because it will help you recontextualize a problem (in SWH-parlance, it helps you see the world differently).
You can also say, SWH is an academic formulation of the beloved programmer motto "When all you have is a hammer, everything looks like a nail". If all you know is an imperative syntax, all problems look solvable by breaking them down into a series of steps/procedures.
In my almost ten years in the industry, there's exactly one time I was able to apply an "unusual" paradigm to solve a problem. GvR might curse me because I sort of made a Lisp-like DSL in Python but I stand by my design decision. The end-result was a small (~200LoC linted with black) DSL parser with some DB access and a lot of rules which actually tried to solve the problem. When I found something wrong I just had to reformulate a rule, not actually wrangle with loops, conditionals, and control flow in order to rewrite logic.
Honest negatives: I had to turn over the project to someone whose background is in EEE, not CS, and I had to explain Higher-Order Functions to them. Not ideal! Actually, in fairness, I bet most in that team would have a hard time figuring it out because, hey, I made a Lisp in Python! But I still stand by my decision; it was the best for the problem given the resources and time I had.
On the other side of the ledger, the Sapir-Whorf hypothesis is widely considered discredited by linguists.
Has it? I'm genuinely curious to know. "Widely considered discredited" sounds like it's met the same fate as ether or alchemy.
I commented on SWH a few months ago in HN too when another user, claiming background in linguistics, replied that it factors in your world view but not as huge a factor as other cultural considerations. That sounded reasonable.
So as of the last time I looked up SWH (a few months ago), my knowledge of its consensus is that:
- the weak form ("relativism") is true to a certain extent, and definitely not to the extent Whorf originally proposed.
- the strong form ("determinism") is largely debated and, personally, I think it's indefensible as a thesis.
I commented on SWH a few months ago in HN too when another user, claiming background in linguistics, replied that it factors in your world view but not as huge a factor as other cultural considerations. That sounded reasonable.
So as of the last time I looked up SWH (a few months ago), my knowledge of its consensus is that:
- the weak form ("relativism") is true to a certain extent, and definitely not to the extent Whorf originally proposed.
- the strong form ("determinism") is largely debated and, personally, I think it's indefensible as a thesis.
When I took linguistics classes in school it was summarily brushed off, but here's how Wikipedia summarizes:
> The strong version, or linguistic determinism, says that language determines thought and that linguistic categories limit and determine cognitive categories. This version is generally agreed to be false by modern linguists.
> The weak version says that linguistic categories and usage only influence thought and decisions. Research on weaker forms has produced positive empirical evidence for a relationship.
> The strong version, or linguistic determinism, says that language determines thought and that linguistic categories limit and determine cognitive categories. This version is generally agreed to be false by modern linguists.
> The weak version says that linguistic categories and usage only influence thought and decisions. Research on weaker forms has produced positive empirical evidence for a relationship.
Well, DUH! Did anybody put forward the first version which sounds like a strawman?
"language determines thought and that linguistic categories limit and determine cognitive categories. This version is generally agreed to be false by modern linguists"
The use of words like "determine" appears to make it look bogus. Whereas "influences" basically means the same thing (in practical terms, strongly influences is just as good as determines).
"language determines thought and that linguistic categories limit and determine cognitive categories. This version is generally agreed to be false by modern linguists"
The use of words like "determine" appears to make it look bogus. Whereas "influences" basically means the same thing (in practical terms, strongly influences is just as good as determines).
Well, based on my own introspection, the strong version looks obviously true to me - so I'm glad someone took time to disprove it.
When I read the description, I understand "determines" as in, your thoughts internally work in terms of language processing, so their complexity is limited to the complexity of the language(s) you know. It sounds plausible, but also testable by checking if humans who never learned a language with complex grammar are capable of processing complex concepts.
When I read the description, I understand "determines" as in, your thoughts internally work in terms of language processing, so their complexity is limited to the complexity of the language(s) you know. It sounds plausible, but also testable by checking if humans who never learned a language with complex grammar are capable of processing complex concepts.
For a long time in human history people did not accept the existence of negative numbers; a Greek mathematician couldn't solve x+1=0 for example (this one also has "zero" in it, which also did not exist for some mathematicians). This seems like a decent example for linguistic categories limiting the thinkable categories. Other Greek examples: Zeno's paradoxes, irrational numbers, ...
Seems like a bad one. New concepts are given new names, or borrowed names, when they’re introduced. The first guy to come up with zero didn’t speak a language with a word for zero at the time.
>This seems like a decent example for linguistic categories limiting the thinkable categories.
As in absolutely limiting them, though? Like the Ancient Greeks, those who invented zero, didn't have it previously in their language, and couldn't do zero-based equations before either.
As in absolutely limiting them, though? Like the Ancient Greeks, those who invented zero, didn't have it previously in their language, and couldn't do zero-based equations before either.
>I'm glad someone took time to disprove it
What do you think "disprove" means in this context though?
E.g. do you think they really settled anything, the way we can prove a math theorem or verify some physical theory to hold (as a predictive model) to the nth degree of precision?
>When I read the description, I understand "determines" as in, your thoughts internally work in terms of language processing, so their complexity is limited to the complexity of the language(s) you know.
That would mean that developing further language is impossible or even that developing the first languages would be impossible - as those nearly language-less peoples have no means to develop those more complex later concepts.
It's not like e.g. Europeans (let's take them as a model of "advanced" language) emerged in nature in fully formed ancient Greek, Latin, English, French, etc.
They started with the same or even more "constrained" languages (verbally and conceptually) as any primitive people, and - going back to our forefathers - even language-less.
What do you think "disprove" means in this context though?
E.g. do you think they really settled anything, the way we can prove a math theorem or verify some physical theory to hold (as a predictive model) to the nth degree of precision?
>When I read the description, I understand "determines" as in, your thoughts internally work in terms of language processing, so their complexity is limited to the complexity of the language(s) you know.
That would mean that developing further language is impossible or even that developing the first languages would be impossible - as those nearly language-less peoples have no means to develop those more complex later concepts.
It's not like e.g. Europeans (let's take them as a model of "advanced" language) emerged in nature in fully formed ancient Greek, Latin, English, French, etc.
They started with the same or even more "constrained" languages (verbally and conceptually) as any primitive people, and - going back to our forefathers - even language-less.
> What do you think "disprove" means in this context though?
What it means for every scientific hypothesis: it takes infinite amount of evidence to positively prove it, but it takes one counterexample to kill it. +/- the usual uncertainty caveats.
> That would mean that developing further language is impossible or even that developing the first languages would be impossible
Not necessarily. It would mean that you can't think about some concepts without first extending the language to support them. Languages still could be extended piece by piece.
What it means for every scientific hypothesis: it takes infinite amount of evidence to positively prove it, but it takes one counterexample to kill it. +/- the usual uncertainty caveats.
> That would mean that developing further language is impossible or even that developing the first languages would be impossible
Not necessarily. It would mean that you can't think about some concepts without first extending the language to support them. Languages still could be extended piece by piece.
>What it means for every scientific hypothesis: it takes infinite amount of evidence to positively prove it, but it takes one counterexample to kill it. +/- the usual uncertainty caveats.
Only in such soft sciences you can "prove" any number of competing hypothesis, and have fractions arguing about them for decades or centuries. And whether a "counter example" is valid and "kills" a theory, will be a matter of interpretation and endlessly debated as well.
>It would mean that you can't think about some concepts without first extending the language to support them. Languages still could be extended piece by piece.
If you can always extend a language to new concepts, the language is not limiting in the strong SWH sense. If it was it would be impossible to reach those concepts from a reduced set of concepts.
Only in such soft sciences you can "prove" any number of competing hypothesis, and have fractions arguing about them for decades or centuries. And whether a "counter example" is valid and "kills" a theory, will be a matter of interpretation and endlessly debated as well.
>It would mean that you can't think about some concepts without first extending the language to support them. Languages still could be extended piece by piece.
If you can always extend a language to new concepts, the language is not limiting in the strong SWH sense. If it was it would be impossible to reach those concepts from a reduced set of concepts.
> Only in such soft sciences you can "prove" any number of competing hypothesis, and have fractions arguing about them for decades or centuries.
It took millennia for spontaneous generation to be definitively disproven.
It took millennia for spontaneous generation to be definitively disproven.
That's exactly my point, as that was before we settled on the scientific method.
So this might have been relatedto biology (or in other domains physics, chemistry, and so on), but the matter was debated in the soft sciences way, not in the way we do biology in the 20th century.
So this might have been relatedto biology (or in other domains physics, chemistry, and so on), but the matter was debated in the soft sciences way, not in the way we do biology in the 20th century.
> Well, DUH! Did anybody put forward the first version which sounds like a strawman?
A lot of proto-linguistic (I say proto because linguistics want a real discipline yet) thought in the '50s-'60s did actually believe this. It was the informal basis for teaching lots of colonized peoples Western languages. It was the basis for the book 1984's Newspeak. It was also the hypothesis that motivated the creation of the Loglan (predecessor to the more well known, but still obscure, language Lojban) language. That you find this to be a strawman argument is a good testament to how widespread the knowledge of its disproval has become.
N.B. I also think in the pop programming language world (e.g. Twitter rants) that a lot of folks genuinely believe something similar to Strong Sapir-Whorf, at least as applied to programming languages.
A lot of proto-linguistic (I say proto because linguistics want a real discipline yet) thought in the '50s-'60s did actually believe this. It was the informal basis for teaching lots of colonized peoples Western languages. It was the basis for the book 1984's Newspeak. It was also the hypothesis that motivated the creation of the Loglan (predecessor to the more well known, but still obscure, language Lojban) language. That you find this to be a strawman argument is a good testament to how widespread the knowledge of its disproval has become.
N.B. I also think in the pop programming language world (e.g. Twitter rants) that a lot of folks genuinely believe something similar to Strong Sapir-Whorf, at least as applied to programming languages.
Having actually worked with James Cooke Brown on Loglan (I wrote the first Yacc grammar for it), I have to say my recollection is that Jim's view was more tentative and nuanced than you've made it sound. While we certainly enjoyed finding things that seemed easier to say in Loglan than English, I don't recall him ever suggesting that there might be a thought that a non-Loglan speaker couldn't think.
I think it would be fairer to say that he was convinced that Whorfian effects were strong enough that there would be value in engineering a language to take advantage of them. But while value is somewhat in the eye of the beholder, I would say this hypothesis has not held up well either.
I think it would be fairer to say that he was convinced that Whorfian effects were strong enough that there would be value in engineering a language to take advantage of them. But while value is somewhat in the eye of the beholder, I would say this hypothesis has not held up well either.
Thanks. My understanding was that Loglan was simply a mechanism to play around with the Sapir-Whorf theory among humans, but thanks for the additional context/correction.
Alchemy is a bit more reasonable.
Even the weak version falls apart under scrutiny. Here's a nice example of this: https://cpb-us-w2.wpmucdn.com/web.sas.upenn.edu/dist/4/81/fi...
This is a good example of a case where there was a phenomenon (a language prominently using non-speaker-oriented direction terms, and correlations with real-world behaviour of speakers of that language) which seemed to support a weak version of SW, but it turns that seemingly supporting evidence was really just a by-product of the testing environment.
Even the weak version falls apart under scrutiny. Here's a nice example of this: https://cpb-us-w2.wpmucdn.com/web.sas.upenn.edu/dist/4/81/fi...
This is a good example of a case where there was a phenomenon (a language prominently using non-speaker-oriented direction terms, and correlations with real-world behaviour of speakers of that language) which seemed to support a weak version of SW, but it turns that seemingly supporting evidence was really just a by-product of the testing environment.
I'm not sure how the study you linked is an indictment of the weak version. It seems to fall well under my understanding of the consensus that the weak version is only true to a certain extent and definitely not to the extent Sapir and Whorf originally claimed.
So this does present an interesting result, and one that (AFAICT---I am not a linguist by training) does run counter to the claims of SWH but, more importantly, the study is limited only to spatial reasoning. Surely there are more areas of thought than that?
So this does present an interesting result, and one that (AFAICT---I am not a linguist by training) does run counter to the claims of SWH but, more importantly, the study is limited only to spatial reasoning. Surely there are more areas of thought than that?
The study shows that differences in systems of direction words doesn't really affect spatial reasoning.
Yes, this one study doesn't disprove every aspect of SWH, but it's a good example of how SWH claims, even in the weaker versions, tend to fare when subject to more rigorous investigation & analysis.
What area of thought do you think provides good evidence for (some version of) the SWH?
Yes, this one study doesn't disprove every aspect of SWH, but it's a good example of how SWH claims, even in the weaker versions, tend to fare when subject to more rigorous investigation & analysis.
What area of thought do you think provides good evidence for (some version of) the SWH?
Given that language is also created or modified by people in order to get their ideas across, wouldn’t it make sense if one can have thoughts arise that don’t fit into language but then they cannot be shared without the creation of appropriate language. I often have the experience of having ideas that I have in a sort of mathematical reasoning space (this here makes that there impossible) that I have to translate into English. (Eg If the the call is routed at the IP layer then they can’t reach this no matter what DNS they have access to)
People do, of course, create new vocabulary, but that's not modifying language on a deep level. And, in part that's a convenience: even when you don't have a "word" for something, you can generally describe it. But if it's something you're going to refer to frequently having a nice lexical entry for it is more convenient. We have memory limitations, so sometimes having convenient handles can free up resources.
And your example, I think, also speaks to the point: you're able to reason in mathematical ways; being a speaker of English doesn't block this, even though English perhaps doesn't offer convenient vocabulary for this in all cases.
And your example, I think, also speaks to the point: you're able to reason in mathematical ways; being a speaker of English doesn't block this, even though English perhaps doesn't offer convenient vocabulary for this in all cases.
On the other hand, it's not like linguists are doing exactly a hard science, and their discrediting something means much, especially when it touches totally unrelated domains like psychology and neuroscience.
Sometimes, when it's a field well outside of your area of expertise, not making pronouncements can save embarrassment later on.
My sentiments exactly (only on the other side).
You seem to respect everything labeled academic, but not all "areas of expertise" and not all "fields" are equally valid -- and surely not just because they are taught in universities, written about in "peer reviewed" journals, and so on.
Linguistics is closer to soft sciences than the opposite.
You seem to respect everything labeled academic, but not all "areas of expertise" and not all "fields" are equally valid -- and surely not just because they are taught in universities, written about in "peer reviewed" journals, and so on.
Linguistics is closer to soft sciences than the opposite.
> You seem to respect everything labeled academic,
I assure you, I really don't.
> but not all "areas of expertise" and not all "fields" are equally valid -- and surely not just because they are taught in universities, written about in "peer reviewed" journals, and so on.
Fully agreed.
> Linguistics is closer to soft sciences than the opposite.
"Linguistics" spans a range of things from the humanities to the 'soft' sciences (in the sense that psychology and cognitive studies 'soft' sciences) to logic/maths.
I assure you, I really don't.
> but not all "areas of expertise" and not all "fields" are equally valid -- and surely not just because they are taught in universities, written about in "peer reviewed" journals, and so on.
Fully agreed.
> Linguistics is closer to soft sciences than the opposite.
"Linguistics" spans a range of things from the humanities to the 'soft' sciences (in the sense that psychology and cognitive studies 'soft' sciences) to logic/maths.
If we want to take this into a more concrete and measurable realm, every programming language is going to get converted into the same machine code before it is run, so it is quite untrue that there is any idea that "cannot be expressed" in one programming language but can be expressed in another. It may be more or less convenient to do but nothing like the strong Sapir-Whorf hypothesis for human languages.
Well, in programming yes.
Though even in programming, there are e.g. non turing complete languages (e.g. simple regex languages), languages without certain high level facilities (making it much harder to organize your code in terms of certain concepts - analogous to organizing your thinking of the world around certain concepts -, which is a SWH-like effect), languages that can't express e.g. infinite loops and are certain to terminate (used e.g. for business logic, templating, etc), and so on.
Even if it all goes down to assembly, a language like Cobol might it much harder to write e.g. a 3D game. And that can be enough for games not be written in that language - it doesn't have to be impossible, just hard, which is enough to discourage most, aside from a few weirdos writing games in Cobol and compilers in bash.
Though even in programming, there are e.g. non turing complete languages (e.g. simple regex languages), languages without certain high level facilities (making it much harder to organize your code in terms of certain concepts - analogous to organizing your thinking of the world around certain concepts -, which is a SWH-like effect), languages that can't express e.g. infinite loops and are certain to terminate (used e.g. for business logic, templating, etc), and so on.
Even if it all goes down to assembly, a language like Cobol might it much harder to write e.g. a 3D game. And that can be enough for games not be written in that language - it doesn't have to be impossible, just hard, which is enough to discourage most, aside from a few weirdos writing games in Cobol and compilers in bash.
Declarativeness targeting a specific problem is definitely good, but it is implementable in any language.
You have touched on what is both the best and the worst thing about programming languages in 2021.
On the one hand, most modern languages are powerful enough that you can build whatever you want on them. DSLs, constraint solving, pure FP, CPS, logic programming, whatever you like.
On the other hand, languages are subject to network effects. If you build an FP system on top of Python and I build one on top of Ruby, the resulting “FP frameworks” will be almost entirely incompatible. That makes it hard for people coming to either of our projects to “pick it up."
It’s great fun to implement your own library or framework that in turn implements something interesting, but everyone doing that leads to applications that are built on top of in-house home-grown greenspunned code bases.
In most production situations, it’s better to find the language and framework that already cater to the idiom you like, and come with a community of like-minded programmers who are familiar with how things work.
Network effects matter at scale, even if they’re irrelevant for a passion project.
The notion that any language can be coerced into supporting any programming idiom is true in theory, “But the difference between theory and practice is narrower in theory, than it is in practice.”
So I suggest there is still a lot of value in selecting the language/framework/library that was built to do the thing we want, right off the bat, and comes trailing a community and ecosystem around it.
On the one hand, most modern languages are powerful enough that you can build whatever you want on them. DSLs, constraint solving, pure FP, CPS, logic programming, whatever you like.
On the other hand, languages are subject to network effects. If you build an FP system on top of Python and I build one on top of Ruby, the resulting “FP frameworks” will be almost entirely incompatible. That makes it hard for people coming to either of our projects to “pick it up."
It’s great fun to implement your own library or framework that in turn implements something interesting, but everyone doing that leads to applications that are built on top of in-house home-grown greenspunned code bases.
In most production situations, it’s better to find the language and framework that already cater to the idiom you like, and come with a community of like-minded programmers who are familiar with how things work.
Network effects matter at scale, even if they’re irrelevant for a passion project.
The notion that any language can be coerced into supporting any programming idiom is true in theory, “But the difference between theory and practice is narrower in theory, than it is in practice.”
So I suggest there is still a lot of value in selecting the language/framework/library that was built to do the thing we want, right off the bat, and comes trailing a community and ecosystem around it.
Lisp Macros making DSLs have similar issues, your DSL doesn't work with the other guy's DSL trying to solve a similar issue.
When we use a system built around programming model X to implement programming model Y, and then write our program Z using model Y on top of model X, we are deliberately implementing the “Inner Platform Effect.”
https://en.wikipedia.org/wiki/Inner-platform_effect
https://en.wikipedia.org/wiki/Inner-platform_effect
Sure, you can always implement a Lisp compiler in Java.
Please tel us more - a DSL in python is ... fun ... and having a real world use is cherry on top
Flattered by your interest but now I'm afraid the words "DSL" and "Lisp-like" might've given the impression of far more complexity than the project actually was. Keep in mind the core engine is ~200LoC. Maybe twice that at most. But really, there were far more rules than engine logic in the end.
The project was started for legal compliance so I don't want to go into specifics in case I make a slip one way or another. It did not run in the production cluster per se but was important nonetheless. (Actually, gods forbid it run in production!)
Very vaguely, it simplified structured data. A rule is recursively defined, base cases being simple rules that just returned primitive data. The original data could be an object with deep properties but most rules just simplified it to one with less fields.
I call it "Lisp-like" because after writing a handful of recursive rules, I had flashbacks of when I studied (actually) Scheme in uni. The tree-structure and meta-rules certainly gave that impression. I did not parse parens though, rather the rule syntax is JSON dictionaries. I hope this aided in readability---it should be self-explanatory what each rule did---and so my team did not find it too esoteric.
I don't remember the exact volume of data we processed but it was in the tens of GB, if not low hundreds. We parallelized it and had maybe 20 runners working concurrently. You can claim mapreduce (ha!) at this approach but honestly I think we could've parallelized it as easily if I did not go with this DSL-approach. :)
The project was started for legal compliance so I don't want to go into specifics in case I make a slip one way or another. It did not run in the production cluster per se but was important nonetheless. (Actually, gods forbid it run in production!)
Very vaguely, it simplified structured data. A rule is recursively defined, base cases being simple rules that just returned primitive data. The original data could be an object with deep properties but most rules just simplified it to one with less fields.
I call it "Lisp-like" because after writing a handful of recursive rules, I had flashbacks of when I studied (actually) Scheme in uni. The tree-structure and meta-rules certainly gave that impression. I did not parse parens though, rather the rule syntax is JSON dictionaries. I hope this aided in readability---it should be self-explanatory what each rule did---and so my team did not find it too esoteric.
I don't remember the exact volume of data we processed but it was in the tens of GB, if not low hundreds. We parallelized it and had maybe 20 runners working concurrently. You can claim mapreduce (ha!) at this approach but honestly I think we could've parallelized it as easily if I did not go with this DSL-approach. :)
Immutable record types as the default, most-used way of modeling data is a great idea that some languages cater to and other languages force you to do in weird, hacky ways.
Countless systems have been designed around mutable data simply because they were written in languages where mutable data was the default. I personally worked on several Java systems where mutability was used but was trivial to refactor out, because every place an instance was modified, it was simple to construct a new instance instead. On a couple of them I had ownership of the codebase and was able to complete this refactoring with a reasonable amount of effort.
I also created a small codebase in Java with an immutable data model, only to pass it off to someone who immediately added setters for every field because they were "missing." And then of course he started to find uses for them.
I don't have a desire to work in Java again, but I think Java recognizing immutable record classes as a concept worthwhile of first class language support is a significant step forward for the industry.
Countless systems have been designed around mutable data simply because they were written in languages where mutable data was the default. I personally worked on several Java systems where mutability was used but was trivial to refactor out, because every place an instance was modified, it was simple to construct a new instance instead. On a couple of them I had ownership of the codebase and was able to complete this refactoring with a reasonable amount of effort.
I also created a small codebase in Java with an immutable data model, only to pass it off to someone who immediately added setters for every field because they were "missing." And then of course he started to find uses for them.
I don't have a desire to work in Java again, but I think Java recognizing immutable record classes as a concept worthwhile of first class language support is a significant step forward for the industry.
> Actually, in fairness, I bet most in that team would have a hard time figuring it out because, hey, I made a Lisp in Python! But I still stand by my decision; it was the best for the problem given the resources and time I had.
Are you completely sure you didn’t just create a massive headache for the team that followed you? Now they have to understand something that looks like magic, or pay more money to hire a wizard.
I’ve seen a lot of “clever and elegant” solutions that become instant legacy when the original genius leaves, and a lot of “boring and repetitive” solutions that stand the rest of time.
Are you completely sure you didn’t just create a massive headache for the team that followed you? Now they have to understand something that looks like magic, or pay more money to hire a wizard.
I’ve seen a lot of “clever and elegant” solutions that become instant legacy when the original genius leaves, and a lot of “boring and repetitive” solutions that stand the rest of time.
I feel like the bit you quoted already captures what I think came of it after I turned it over. It is even from a paragraph labeled "Honest negatives".
Complete certainty of how it turned out is a bit too much to ask. For every story like mine, there's an equivalent story of a legacy system in boring Java/C that no one wants to touch, works like magic, etc.
FWIW, I wrote a pretty extensive documentation of the project before I left, including recommendations for improvement[1]. Again, it's foolish to claim complete certainty but the nature of the project was such that they are unlikely to need to rewrite anything on top of the engine. Any modifications and additions moving forward would be in the declared rules, not in any of the logic. And for that, they have hundreds of examples from me to copy from.
And if they do need to touch the "parser", at ~200LoC the complexity is certainly far below, say, a Spring J2EE code base. It's all in one file too, that shouldn't be too bad.
[1] If I may use HN as a small soapbox, actually, months later, I figured out a further small addition to that project that would've made working with it far easier. If any of my previous team recognizes this and this project is still in use, feel free to reach out to me for one last brilliant idea. :)
Complete certainty of how it turned out is a bit too much to ask. For every story like mine, there's an equivalent story of a legacy system in boring Java/C that no one wants to touch, works like magic, etc.
FWIW, I wrote a pretty extensive documentation of the project before I left, including recommendations for improvement[1]. Again, it's foolish to claim complete certainty but the nature of the project was such that they are unlikely to need to rewrite anything on top of the engine. Any modifications and additions moving forward would be in the declared rules, not in any of the logic. And for that, they have hundreds of examples from me to copy from.
And if they do need to touch the "parser", at ~200LoC the complexity is certainly far below, say, a Spring J2EE code base. It's all in one file too, that shouldn't be too bad.
[1] If I may use HN as a small soapbox, actually, months later, I figured out a further small addition to that project that would've made working with it far easier. If any of my previous team recognizes this and this project is still in use, feel free to reach out to me for one last brilliant idea. :)
Sounds like a useful project.
> It's all in one file too, that shouldn't be too bad.
Fewer files is not necessarily better.
The guiding principle in my mind is reduction of entropy. If splitting one file into multiple files makes sense in the brains of the beholders it is a good thing.
> It's all in one file too, that shouldn't be too bad.
Fewer files is not necessarily better.
The guiding principle in my mind is reduction of entropy. If splitting one file into multiple files makes sense in the brains of the beholders it is a good thing.
200 lines in one file sounds fine on the face of it. I like it when I don't have to trace through to other files to see what's going on.
I haven't yet seen a DSL that wasn't a big improvement over compiling the DSL to a bunch of boilerplate in my head and making everyone try to reread the boilerplate forever.
Rocket materials don't ultimately compile down to the same material though. This makes the analogy somewhat flawed. Also, if a novel language feature is useful enough, it's often stolen by the competition.
From the article,
> [Lisp macros] by their nature would be hard to implement properly in a language without turning it into a dialect of Lisp
Other candidates that come to mind (because I recently learned about them) are effect systems, like in Koka.
> [Lisp macros] by their nature would be hard to implement properly in a language without turning it into a dialect of Lisp
Other candidates that come to mind (because I recently learned about them) are effect systems, like in Koka.
Yes, I read that, but I don't know Lisp well enough to evaluate the claim.
I'd highly recommend learning lisp and writing some higher-order functions with macros. You start with an instance of a lower-order function, insert a few backticks and commas where appropriate, wrap that in a defmacro, and boom, you're a metaprogrammer. You can certainly do similar stuff in other languages, but it's almost always a cludge.
The rest of lisp is pretty easy if you've done any sort of functional programming, and view the code through a lens that translates (foo ...) to foo(...)
The rest of lisp is pretty easy if you've done any sort of functional programming, and view the code through a lens that translates (foo ...) to foo(...)
Mixin macros in D are just about as powerful, and D is not a dialect of lisp.
The main difference is: mixins are compile-time only, you can't add them to a running system like in Lisp.
In practice, it is a much smaller difference than it looks like.
The main difference is: mixins are compile-time only, you can't add them to a running system like in Lisp.
In practice, it is a much smaller difference than it looks like.
The other problem is the "productive-only" trap. You begin to hate art, essays and everything related with free time because you are not doing anything productive doing those.
This can expand to your tastes or everyday life by not wanting to learn X "just for the fun".
This can expand to your tastes or everyday life by not wanting to learn X "just for the fun".
The amount of intellectual curiosity on a site called Hacker News always feels lower than it should be.
I'd say that (2) isn't a side point...
> 99.5% of programming consists of gluing together calls to library functions. All popular languages are equally good at this.
In my experience, there are tons of programmers who balk at anything more complicated than a for loop, to the point where they won't even read the surrounding documentation of a short block of code to try and understand what it does. That's the 99.5% of programming that pg is talking about. I'd guess that some 80% of programmers spend their entire lives in this regime. When algorithm/language researchers talk to software engineers about what programming is, sparks fly. Like the parable of the blind people examining an elephant, we're talking about the same thing, but our experiences with it are too different to reconcile.
> 99.5% of programming consists of gluing together calls to library functions. All popular languages are equally good at this.
In my experience, there are tons of programmers who balk at anything more complicated than a for loop, to the point where they won't even read the surrounding documentation of a short block of code to try and understand what it does. That's the 99.5% of programming that pg is talking about. I'd guess that some 80% of programmers spend their entire lives in this regime. When algorithm/language researchers talk to software engineers about what programming is, sparks fly. Like the parable of the blind people examining an elephant, we're talking about the same thing, but our experiences with it are too different to reconcile.
If someone used Lisp, Elm, Rust, Elixir, Go, or even just JavaScript, they should know that these are SO vastly different in their mental models that "languages are solved" doesn't strike me as a reasonable argument at all.
This is still a pretty narrow group. Throw in APL, Prolog and Z3.
I just started playing with Dyalog APL after listening to the Array Cast. It’s mind bending stuff even after being familiar with Numpy and R. Makes most languages look clunky and cluttered for array manipulation.
And the idea that a language can be designed around one data structure is elegant. Of course you get that in Lisp and Smalltalk as well. But having all those primitives that work over array structures is incredibly expressive.
I believe the array podcasters when they claim array languages can be several times more productive than other languages, at least for domains that fit well with arrays.
And the idea that a language can be designed around one data structure is elegant. Of course you get that in Lisp and Smalltalk as well. But having all those primitives that work over array structures is incredibly expressive.
I believe the array podcasters when they claim array languages can be several times more productive than other languages, at least for domains that fit well with arrays.
Are they so vastly different? Other than perhaps Lisp and Elm, they are largely equivalent, with different levels of immutability on top of a largely imperative core.
At least mention prolog, forth, SQL or the like that are truly different.
At least mention prolog, forth, SQL or the like that are truly different.
Rust’s ownership model (which is more than just the borrow checker, it’s the whole concept of one location actually owning data, and aliasing XOR mutability, and the pervading effects of this design on the language and its libraries) is a really big deal, even if it doesn’t look like it would be at a casual glance. It changes how you approach programming and reason about systems, and truly is (or should be used as) a fundamentally different approach to data flow and what’s possible, a smidgeon like Prolog in that way of being different, though not as much. I miss it very frequently when working in other languages (which is mostly JavaScript these days), because there are plenty of things that just become impossible to express reliably without it. Working in another language you can adopt conventions of writing in this style, but you can’t verify it without representing it in the type system, so the result will be riddled with holes in other languages.
(It is, however, difficult to disentangle some features that Rust’s ownership model requires but which aren’t necessarily a part of that ownership model: for example, algebraic data types are essential and expression orientation extremely desirable, but there are other languages which have those features without the rest of the ownership model.)
People often think memory safety without garbage collection is Rust’s shtick, but it’s actually the ownership model that’s Rust’s defining feature, underpinning everything and making that possible.
(It is, however, difficult to disentangle some features that Rust’s ownership model requires but which aren’t necessarily a part of that ownership model: for example, algebraic data types are essential and expression orientation extremely desirable, but there are other languages which have those features without the rest of the ownership model.)
People often think memory safety without garbage collection is Rust’s shtick, but it’s actually the ownership model that’s Rust’s defining feature, underpinning everything and making that possible.
Correct me if I’m wrong, but Pony lang brings Rust’s ownership model to the max - so as a niche language, do check it out!
They all have distiguishing features that can be emulated in other languages (to a degree) but will throw off even senior developers.
Lisp has its macros.
Elm has its type system.
Go, Elixir, and JS have rather idiosyncratic concurrency models.
Rust has its borrow checker.
Perl seems to be SO special that even proficient Perl devs aren't able to write performant code in it. /s
Sure, Prolog and SQL are much more different than the rest. But I didn't want to strawman here.
Lisp has its macros.
Elm has its type system.
Go, Elixir, and JS have rather idiosyncratic concurrency models.
Rust has its borrow checker.
Perl seems to be SO special that even proficient Perl devs aren't able to write performant code in it. /s
Sure, Prolog and SQL are much more different than the rest. But I didn't want to strawman here.
[deleted]
Not to mention that languages are not just a tool for communicating meaning: it's also a tool for communicating emotions and mannerism as well.
> but saying that languages don't matter, for us, would be like rocket engineers saying that materials don't matter.
This is a bad analogy. Programming languages all get compiled to the same machine codes. The human-readable version of that code doesn't actually matter very much, if at all, after compilation. Programming languages are tools for humans: they're either expressive enough or they're not.
A better analogy would be rocket engineers saying the CAD tool you choose to design your rocket in doesn't matter—and that has some merit.
This is a bad analogy. Programming languages all get compiled to the same machine codes. The human-readable version of that code doesn't actually matter very much, if at all, after compilation. Programming languages are tools for humans: they're either expressive enough or they're not.
A better analogy would be rocket engineers saying the CAD tool you choose to design your rocket in doesn't matter—and that has some merit.
> What can you say in this language that would be impossibly inconvenient to say in others?
This ideology is why I believe so strongly in the power of SQL (and similarly-expressive functional/DSLs). They are effectively limitless in their ability to describe problem spaces. In SQL, joining 30 different dimensions of data is a matter of the same # of lines of SQL. Doing such a thing in any imperative language would be a medium nightmare at best. Even with LINQ at your disposal, this is not fun.
I actually did not realize it was possible to construct a useful piece of business software that exclusively uses SQL for its domain logic until ~18 months ago. Turns out the trick is to go all-in and just make sure 100% of the relevant domain state is represented in the schema. You also have to understand why database normalization is important if you go down this road. The only reason you would fail to model something properly is lack of imagination, experience and/or discipline. These tools are limitless.
There is also the benefit to the business. You can print off all of the tables as excel spreadsheets and review them with non-technical stakeholders. I find this much preferable to explaining how procedural code works to non-wizards.
So, I would say - Weird languages - Absolutely yes.
But, also go check out some of these new tricks you can teach to old mainstream things. If you want to play around with these ideas, getting SQL into your application is absolutely trivial with SQLite these days. We are using it in production for this purpose right now. My project managers are more familiar with the product's schema than I am at this point, because they are authoring BL in SQL today. This is where you really want to be, IMO.
This ideology is why I believe so strongly in the power of SQL (and similarly-expressive functional/DSLs). They are effectively limitless in their ability to describe problem spaces. In SQL, joining 30 different dimensions of data is a matter of the same # of lines of SQL. Doing such a thing in any imperative language would be a medium nightmare at best. Even with LINQ at your disposal, this is not fun.
I actually did not realize it was possible to construct a useful piece of business software that exclusively uses SQL for its domain logic until ~18 months ago. Turns out the trick is to go all-in and just make sure 100% of the relevant domain state is represented in the schema. You also have to understand why database normalization is important if you go down this road. The only reason you would fail to model something properly is lack of imagination, experience and/or discipline. These tools are limitless.
There is also the benefit to the business. You can print off all of the tables as excel spreadsheets and review them with non-technical stakeholders. I find this much preferable to explaining how procedural code works to non-wizards.
So, I would say - Weird languages - Absolutely yes.
But, also go check out some of these new tricks you can teach to old mainstream things. If you want to play around with these ideas, getting SQL into your application is absolutely trivial with SQLite these days. We are using it in production for this purpose right now. My project managers are more familiar with the product's schema than I am at this point, because they are authoring BL in SQL today. This is where you really want to be, IMO.
“You can print off all of the tables as excel spreadsheets and review them with non-technical stakeholders.”
Try something like Metabase. Just place the SQL in there and you get a URL that gives you dynamically updated “Excel”.
I like this way of business development: Prototype some SQL, place it in Metabase, get feedback, update the SQL, when they are happy, make it to an Update that solve their need automatically.
And it gets way more powerful when you learn Macros in PL/SQL or PostgreSQL so that you can dynamically change the SQL based on results. One example is to build the Metabase functionality into the business application do that you can easily add/change SQL, and the resulting values automatically is clickable if the data comes from the right tables/views.
I like this way of business development: Prototype some SQL, place it in Metabase, get feedback, update the SQL, when they are happy, make it to an Update that solve their need automatically.
And it gets way more powerful when you learn Macros in PL/SQL or PostgreSQL so that you can dynamically change the SQL based on results. One example is to build the Metabase functionality into the business application do that you can easily add/change SQL, and the resulting values automatically is clickable if the data comes from the right tables/views.
The thing I've always had trouble with from there is extending and versioning domain logic, both for new features as well as for rollback. What's worked for you here?
I use a lot of views for abstraction and backward compatibility.
Rollback is always difficult on live systems, especially when the data propagate to integrations. I try to always have 'first created' and 'last changed' time stamp, and first created and last changed user. If the job is automatic the “user” should be traceable back to the individual job, not some generic system user.
Rollback is always difficult on live systems, especially when the data propagate to integrations. I try to always have 'first created' and 'last changed' time stamp, and first created and last changed user. If the job is automatic the “user” should be traceable back to the individual job, not some generic system user.
I had great success maintaining views (and tests on top of them) for the business people by using dbt. Everything is in git and gets deployed along side our fivetran sync.
Funny you should bring up SQL. The "learning how to think things you couldn't previously think" resonated with me also, specifically when I realized that SQL would be so much better if joins were values instead of language constructs. I can't imagine I would have come up with this thought if I hadn't been working in Racket with the substitution model (as taught by SICP) fresh in mind.
Sections 5.1.1 and 5.1.2 in my side project demonstrate what I mean by "joins are values": https://docs.racket-lang.org/plisqin/Refactoring_Recipes.htm...
Sections 5.1.1 and 5.1.2 in my side project demonstrate what I mean by "joins are values": https://docs.racket-lang.org/plisqin/Refactoring_Recipes.htm...
I feel like LINQ is pretty close to the equivalent SQL if you're already using DataTables or some other easily composeable type. But I agree SQL is great.
I feel like with SQL although, you could reproduce the vast majority of usage of it with about 5 very large functions / objects, which is what it essentially is in most usage.
There was this analogy about programming language proponents.
Language A has features 1, 2, and 3. Language B has features 1, 2, and 4.
Language A user thinks they're superior because they have feature 3, which B lacks. B's feature 4 they don't understand, but they've never needed it so it's useless.
Language B user thinks the opposite, of course.
(this was much better explained in an article that graced HN a while back, and I can't find anymore)
Language A has features 1, 2, and 3. Language B has features 1, 2, and 4.
Language A user thinks they're superior because they have feature 3, which B lacks. B's feature 4 they don't understand, but they've never needed it so it's useless.
Language B user thinks the opposite, of course.
(this was much better explained in an article that graced HN a while back, and I can't find anymore)
>Languages are solved, not important; I build systems.
The language of the System - Rich Hickey https://www.youtube.com/watch?v=ROor6_NGIWU
The language of the System - Rich Hickey https://www.youtube.com/watch?v=ROor6_NGIWU
Looking at functional languages helped me understand the point of all a little better, to the point where I write completely different imperative code now. I'm much better at reducing state, leveraging static calls / libs etc..
But I'll probably never use a functional language in production.
The Rust borrowchecker is an awesome idea, I don't quite like Rust and don't want to use it, but I'm excited for the concept to be introduced into established or newer languages - and it helped me reason about my own programs a little bit.
Even beyond personal curiosity, that was time well spent.
But I'll probably never use a functional language in production.
The Rust borrowchecker is an awesome idea, I don't quite like Rust and don't want to use it, but I'm excited for the concept to be introduced into established or newer languages - and it helped me reason about my own programs a little bit.
Even beyond personal curiosity, that was time well spent.
> saying that languages don't matter, for us, would be like rocket engineers saying that materials don't matter.
It also seems plainly mistaken. We still see a steady stream of security vulnerabilities relating to imperfect use of unsafe languages. Safer languages make those sorts of errors categorically impossible. Even if your position is sure but these languages aren't always practical, that's still a concession that further work is needed on safe languages.
It also seems plainly mistaken. We still see a steady stream of security vulnerabilities relating to imperfect use of unsafe languages. Safer languages make those sorts of errors categorically impossible. Even if your position is sure but these languages aren't always practical, that's still a concession that further work is needed on safe languages.
In my experience, as you learn more about lambda calculus and type theory (LC, STLC, System-F, System-Fw, CiC) the peculiarities of language designs start to fade. This is because when you see a weird-looking language feature, instead of internalizing it as a unique design with its own unique character, you tend to see it as "syntactic sugar" on elemental theories.
That said, some languages are more ergonomic than others, especially when you compare them against particular domains. But IMO that's a problem that transcends language design. All tools, not just a language, should be fit to the domain. And in general you can build APIs and libraries that can reasonably fit any language to a domain.
Edit: slight simplification.
That said, some languages are more ergonomic than others, especially when you compare them against particular domains. But IMO that's a problem that transcends language design. All tools, not just a language, should be fit to the domain. And in general you can build APIs and libraries that can reasonably fit any language to a domain.
Edit: slight simplification.
I'd definitely agree with the specific point of both paragraphs, especially because you said 'language designs' in the first. But I think the essay uses 'language' to mean what you do in your second paragraph, 'features'/stdlib/ecosystem -- the whole experience of working with that material in practice.
And in that sense, I think the value of 'weird' languages is that they can package so many different mutually-reenforcing design decisions together that they literally can have the 'think different' effect described in the essay.
Taking one example that's kinda-weird, kinda-mainstream -- a 'language' like Erlang includes way more than a Prolog-inspired syntax for a simple functional language, and when you look closely at it, it's not simple to just recreate by pulling in features ad-hoc; the language, its stdlib, and its VM complement each other and have informed each others' design.
Probably the feature that most comes to mind when we think of Erlang is that it 'goes all-in' on message passing in a functional language. 'All in' meaning that they've made decisions like: being willing to copy a lot if needed, little details like keeping a count of reductions, big things like pulling in concerns that are often left to the OS when working in other languages like process scheduling, preemption, and supervision, and providing a toolkit out of the box that supports building full systems via Nodes with Applications with trees of Supervisors of Processes (all of which are effectively language concepts now), etc. Well, every one of those decisions is eyebrow-raising to somebody or a lot of somebodies. But if you do go all-in on that combo of capabilities, what's it like?
A good engineering team with a lot of money can fit another language and another VM to the same kinds of domains that Erlang is a fit for. (Not that you can get people to agree what those domains are, even within Ericcson apparently). But their solution will necessarily look very different, and the difference between what's easy/hard in their approach vs. an erlang-ish approach is what the weird language can teach us.
And in that sense, I think the value of 'weird' languages is that they can package so many different mutually-reenforcing design decisions together that they literally can have the 'think different' effect described in the essay.
Taking one example that's kinda-weird, kinda-mainstream -- a 'language' like Erlang includes way more than a Prolog-inspired syntax for a simple functional language, and when you look closely at it, it's not simple to just recreate by pulling in features ad-hoc; the language, its stdlib, and its VM complement each other and have informed each others' design.
Probably the feature that most comes to mind when we think of Erlang is that it 'goes all-in' on message passing in a functional language. 'All in' meaning that they've made decisions like: being willing to copy a lot if needed, little details like keeping a count of reductions, big things like pulling in concerns that are often left to the OS when working in other languages like process scheduling, preemption, and supervision, and providing a toolkit out of the box that supports building full systems via Nodes with Applications with trees of Supervisors of Processes (all of which are effectively language concepts now), etc. Well, every one of those decisions is eyebrow-raising to somebody or a lot of somebodies. But if you do go all-in on that combo of capabilities, what's it like?
A good engineering team with a lot of money can fit another language and another VM to the same kinds of domains that Erlang is a fit for. (Not that you can get people to agree what those domains are, even within Ericcson apparently). But their solution will necessarily look very different, and the difference between what's easy/hard in their approach vs. an erlang-ish approach is what the weird language can teach us.
The whole explanation of your point is just filled with analogies. IMO if you have to use analogies to explain your point then you really don't understand your own point.
When programming, I am thinking in terms of data, what processing the data needs, how will you structure the data in memory/disk, what IO/integration is required etc. This thinking has nothing to do with what the programming language allows/makes you to think. If your programming language is supposed to dominate your thinking about programs then you are just constraining yourself to a specific way of solving the problem.
When programming, I am thinking in terms of data, what processing the data needs, how will you structure the data in memory/disk, what IO/integration is required etc. This thinking has nothing to do with what the programming language allows/makes you to think. If your programming language is supposed to dominate your thinking about programs then you are just constraining yourself to a specific way of solving the problem.
This rocket analogy falls flat because the languages that have been used to build the most scalable and/or complex systems of today are usually the boring ones (c/c++/Java/python/ruby/JavaScript).
Linux, llvm, Android, iOS, git, cPython, numpy, etc, etc. From operating systems, to compilers, to scientific computing, to literal rocket control systems, it’s mostly boring C/C++/obj-C/Java.
Linux, llvm, Android, iOS, git, cPython, numpy, etc, etc. From operating systems, to compilers, to scientific computing, to literal rocket control systems, it’s mostly boring C/C++/obj-C/Java.
Is that true? WhatsApp, Discord, and Facebook Messenger are Erlang. Some pretty extreme scale systems, I'd say.
Some of these companies are so insanely huge that they have dozens of technology stacks, so I would not attribute elixir specifically, to the latter two at least (wasn’t discord rewritten in rust not too long ago?)
And facebook itself is historically PHP (where they had to fork the runtime even), but they use plenty of other boring tech (eg. Java), as well as some exotic ones, notably haskell for some query pre-optimization (afaik)
And facebook itself is historically PHP (where they had to fork the runtime even), but they use plenty of other boring tech (eg. Java), as well as some exotic ones, notably haskell for some query pre-optimization (afaik)
They rewrote some services from Go to Rust, but have always been a huge elixir shop. They wrote some NIFs in Rust too.
> Pick a language that most programmers consider weird but whose median user is smart
I think this heuristic fails, with my poster-child counter-example being Nock and Hoon, the languages used to implement Urbit. Those languages are unquestionably weird, and I think their median user is pretty smart -- you have to be pretty smart to use those languages because they are intentionally designed to be difficult to use. But I don't see any merit whatsoever in Nock and Hoon, at least not with respect to giving you any leverage in programming. C++ is another example. It's not considered weird, but I think it would be if it were not so widely used. Again, to use C++ you have to be smart because you have to know the locations of a zillion and one hidden land mines. But the appeal of these languages is not the leverage they give you, it's the barrier to entry. Once you invest the time to learn them you become a member of an exclusive club. In the case of C++ at least, being a member of the club gives you leverage and opens up employment opportunities. But that doesn't make C++ a good language.
I think this heuristic fails, with my poster-child counter-example being Nock and Hoon, the languages used to implement Urbit. Those languages are unquestionably weird, and I think their median user is pretty smart -- you have to be pretty smart to use those languages because they are intentionally designed to be difficult to use. But I don't see any merit whatsoever in Nock and Hoon, at least not with respect to giving you any leverage in programming. C++ is another example. It's not considered weird, but I think it would be if it were not so widely used. Again, to use C++ you have to be smart because you have to know the locations of a zillion and one hidden land mines. But the appeal of these languages is not the leverage they give you, it's the barrier to entry. Once you invest the time to learn them you become a member of an exclusive club. In the case of C++ at least, being a member of the club gives you leverage and opens up employment opportunities. But that doesn't make C++ a good language.
Being smart is not equivalent to "know the locations of a zillion and one hidden land mines".
C and C++ were weird at the beginning and their median user was smart. They just become so mainstream that, for many, programming is programming in C-like languages. The majority of developers nowadays won't find new concepts, new ways of thinking by picking up C or C++, they're likely to have met those concepts already.
If the majority of developers picked up Lisp or Haskell, they would likely discover new ways of thinking.
This is changing, because popular features, abstractions and ways of thinking are trickling down from Lisp and Haskell to more mainstream languages.
C and C++ were weird at the beginning and their median user was smart. They just become so mainstream that, for many, programming is programming in C-like languages. The majority of developers nowadays won't find new concepts, new ways of thinking by picking up C or C++, they're likely to have met those concepts already.
If the majority of developers picked up Lisp or Haskell, they would likely discover new ways of thinking.
This is changing, because popular features, abstractions and ways of thinking are trickling down from Lisp and Haskell to more mainstream languages.
C and C++ were never weird. In fact, C was criticized when it was new for being a "baby" version of better languages. Their median user was intentionally not smart; it aimed for an entirely different demographic of user, the common person.
Wasn't C designed to be used in Unix as a successor to B?
> Being smart is not equivalent to "know the locations of a zillion and one hidden land mines".
That's right, and I never said they were equivalent. But I think being smart is a prerequisite to navigating C++.
> If the majority of developers picked up Lisp or Haskell, they would likely discover new ways of thinking.
Yes, I agree. But the problem is that the weird-language-with-smart-users heuristic is as likely to lead one to Nock and Hoon as it is to Lisp and Haskell, and I don't believe that you will discover new ways of thinking in the former. What you will discover (though it may take you a lifetime to realize this) is complex obfuscations of simple ideas that were discovered long ago.
That's right, and I never said they were equivalent. But I think being smart is a prerequisite to navigating C++.
> If the majority of developers picked up Lisp or Haskell, they would likely discover new ways of thinking.
Yes, I agree. But the problem is that the weird-language-with-smart-users heuristic is as likely to lead one to Nock and Hoon as it is to Lisp and Haskell, and I don't believe that you will discover new ways of thinking in the former. What you will discover (though it may take you a lifetime to realize this) is complex obfuscations of simple ideas that were discovered long ago.
By the time you finish navigating C++, you have no smarts left over :D.
Now, when I first modified Nix I saw some surprisingly readable C++, but this was all performance non-critical code where C++ wasn't needed. In situations where the use of C++ is actually justified, the weirdest is much more pronounced, and the cognative burden much worse.
Definitely agree Urbit is a trap, though.
Now, when I first modified Nix I saw some surprisingly readable C++, but this was all performance non-critical code where C++ wasn't needed. In situations where the use of C++ is actually justified, the weirdest is much more pronounced, and the cognative burden much worse.
Definitely agree Urbit is a trap, though.
> The majority of developers nowadays won't find new concepts, new ways of thinking by picking up C or C++
Maybe, but at a minimum pointer arithmetic would appear to be an exception.
Maybe, but at a minimum pointer arithmetic would appear to be an exception.
[deleted]
> But that doesn't make C++ a good language.
TFA is about weird languages, not good (or bad) languages. It's about aspects of a programming language that are not part of the intersection of "95% of all programming languages".
TFA is about weird languages, not good (or bad) languages. It's about aspects of a programming language that are not part of the intersection of "95% of all programming languages".
The thesis is:
> if you want to expand your concept of what programming can be, one way to do it is by learning weird languages.
Implicit in this advice is that programming is actually a useful endeavor and not just a puzzle like sudoku that you engage in mainly to pass the time. And I'm saying that the weird-language heuristic is as likely to lead you to something sudoku-like, where you face a lot of interesting intellectual challenges, but at the end of the day you don't actually get any leverage towards doing anything that is actually useful, as it is to lead you to something with actual utility.
> if you want to expand your concept of what programming can be, one way to do it is by learning weird languages.
Implicit in this advice is that programming is actually a useful endeavor and not just a puzzle like sudoku that you engage in mainly to pass the time. And I'm saying that the weird-language heuristic is as likely to lead you to something sudoku-like, where you face a lot of interesting intellectual challenges, but at the end of the day you don't actually get any leverage towards doing anything that is actually useful, as it is to lead you to something with actual utility.
Absolutely. However, I don't see a path from that to "XX is a (bad|not good) language".
There is no such thing as a good language or a bad language an an absolute sense. There are only languages that provide you with more leverage towards a certain goal and languages that provide you with less. Is brainfuck a good language or a bad one? If your goal is to write a high performance back-end for a web site, it's probably bad. If your goal is to pass some time trying to solve an intellectually challenging puzzle, it's probably good.
But in general programming is viewed as something one does in order to achieve some practical purpose, not just to while away the hours. And with respect to that goal, "seek out weird languages" seems like a poor heuristic to me.
But in general programming is viewed as something one does in order to achieve some practical purpose, not just to while away the hours. And with respect to that goal, "seek out weird languages" seems like a poor heuristic to me.
I was quoting you saying "But that doesn't make C++ a good language."
Putting aside the other controversial things that Graham says in this post, I think we could find common ground and have some fun technical discussion by focusing on this angle:
> What can you say in this language that would be impossibly inconvenient to say in others?
The first experience that comes to mind for me was XSLT. Early on in my technical writing career, I needed to convert the Doxygen output of a C library to a more barebones HTML output (so that the reference docs would have the same branding as the rest of our site). I used XSLT to extract only the bits of HTML that I needed and I transformed them into nice, straightforward, semantic HTML. It took me a while to wrap my head around XSLT's flow but I was amazed to find that a task that would have taken probably 50-100 lines of looping and condition checking could be accomplished in literally 1-3 lines of XSLT.
Would love to hear other's experiences along these lines (i.e. concrete examples).
> What can you say in this language that would be impossibly inconvenient to say in others?
The first experience that comes to mind for me was XSLT. Early on in my technical writing career, I needed to convert the Doxygen output of a C library to a more barebones HTML output (so that the reference docs would have the same branding as the rest of our site). I used XSLT to extract only the bits of HTML that I needed and I transformed them into nice, straightforward, semantic HTML. It took me a while to wrap my head around XSLT's flow but I was amazed to find that a task that would have taken probably 50-100 lines of looping and condition checking could be accomplished in literally 1-3 lines of XSLT.
Would love to hear other's experiences along these lines (i.e. concrete examples).
The whole tidyverse set of packages for R. Its a DSL for data analysis that makes heavy use of R macros. The vocabulary and mental model that it has about data transformation is superior to any other analysis package I've used.
Pandas/Numpy is close but R's macro/custom operators make everything much more seamless.
Pandas/Numpy is close but R's macro/custom operators make everything much more seamless.
In particular I'd shoutout ggplot as an amazing DSL for graphics. It truly is a language of itself for describing visualizations as mappings from data to graphical layers. And yet being a library it seamlessly interacts with the rest of R just as you expect
Is it really better than python? I'm not too much in the data analysis space, but it seems like with python's dominance in machine learning that R's days are numbered.
I've done data analysis for a decade in the healthcare space, ML is not at all common. Basic statistics and data munging is 99% of what you need, you're mostly doing SQL to gather the data, then a lot of older folks still use SAS, my god. R looks way more "shiny" than SAS, nevermind python. Python is trendier in all other fields it seems, it really hasn't penetrated healthcare in my experience. R on the other hand, so many healthcare researchers come from academics and statistics courses where R is way way more popular than python.
Unless you think machine learning by is going to put statisticians out of work, R will stick around. It also has a lot of libraries useful to scientists.
Strictly speaking about data analysis, tidyverse is way better. Even in adjacent spaces such as plotting and interactive data, tools like Shiny [0] are ahead of the Python ecosystem.
R is definitely weird language, not as useful for general purpose computing, and has far less marketshare. But that's kinda the point of pg's essay.
[0] https://shiny.rstudio.com/
R is definitely weird language, not as useful for general purpose computing, and has far less marketshare. But that's kinda the point of pg's essay.
[0] https://shiny.rstudio.com/
Once implimented a mulitlingual cms using xml schema, doctypes and xslt. The lifting was done by a server i called saw. Servlet action wrappers. Maps for namespaces led to varying transforms. XSLTs produced html, applet editors, flash, etc. Was fun. 29 markets. Bonus, was running in blackdown jvm on netbsd. Had to use oracle for db. But there were idls for as400s in the mix to.
My experience with XSLT is it only works until you hit an edge case, and then it's impossibly hard and you need a full programming language. I usually hit those edge cases quickly so I'd prefer XSLT didn't exist and that I just had a well designed XML library in something like python
Reflection combined with runtime code generation is very powerful in C#. Here's moderately complicated example https://github.com/Const-me/ComLightInterop/tree/master/ComL...
Wow! Would you be able to share the xlst code? Would love to learn more
Interesting because this is the first time I’ve heard this kind of love for XSLT.
Got about 600 of my mother's playlists after she died, all in Windows PlayList format (.wpl, an XML-ish variant). Could not find anything better than XSLT to generate portable .m3u files from them. Worked like a charm.
It's a very badly designed language (that's true for anything that came from the XML way of thinking). But it's amazingly powerful and capable.
XSLT is basically SQL for structured text.
XSLT is basically SQL for structured text.
> XSLT is basically SQL for structured text.
That is what XQuery is for.
That is what XQuery is for.
To be fair, I only used it that one time and I was new to programming. Nonetheless it was very much a "wow, this is a different way to do things" experience. And at the time it seemed to magically solve much more accurately and with much less work than an imperative approach.
XSLT is great when you try to do simple things.
Then you try to e.g. format a date or something.
As long as you stick to what it is good at and relegate everything else to another layer, it's fine (it could certainly be a lot better, though)
Then you try to e.g. format a date or something.
As long as you stick to what it is good at and relegate everything else to another layer, it's fine (it could certainly be a lot better, though)
Most people who encountered it never really understood its programming model. In short, they tried to use it as an imperative language, but XSLT doesn't want to be an imperative language. The basic paradigm is pattern matching. You're supposed to create templates that say what to do when a node meeting certain characteristics is encountered (including how/whether to continue descending into the node's children/siblings/etc). Instead, what you see in most real-life XSLT programs is a whole bunch of xsl:if statements that attempt to conditionally (and, worse, procedurally) handle multiple node types within a single template. That's a dead giveaway that the program's author didn't really understand what they were trying to do or how to accomplish it in the language.
XSLT doesn't do itself many favors, either, because the model depends on the execution of a few "hidden" default templates that drive the tree processing. If you don't know those are there or what they're doing -- or worse, if you don't know they're there and you accidentally override them -- then it's really hard to understand what the heck is going on. It just looks like poorly-defined magic.
Plus, you need to understand XPath to write effective templates and most people don't understand it as well as they think they do. It's deceptively powerful.
Finally, add on the fact that XSLT programs are themselves valid XML -- who the heck wants to write code in XML! -- and it really never had a chance to be understood, much less liked.
But many of its ideas were good!
XSLT doesn't do itself many favors, either, because the model depends on the execution of a few "hidden" default templates that drive the tree processing. If you don't know those are there or what they're doing -- or worse, if you don't know they're there and you accidentally override them -- then it's really hard to understand what the heck is going on. It just looks like poorly-defined magic.
Plus, you need to understand XPath to write effective templates and most people don't understand it as well as they think they do. It's deceptively powerful.
Finally, add on the fact that XSLT programs are themselves valid XML -- who the heck wants to write code in XML! -- and it really never had a chance to be understood, much less liked.
But many of its ideas were good!
This describes my one serious attempt to use XSLT pretty well. It seemed like a powerful idea. But after some weeks of struggling with it, I decided the syntax was too painful to deal with. But I know I never learned it properly, as you say.
Shameless plug: The xmlstarlet utility allows creating implicit XSLT from command line args, so it would also be one line of shell. This way the XSLT verbosity is also gone: xsl:value-of becomes -v for example.
Yes lots of programming consists of gluing together libraries, but in my experience languages vary dramatically at how well they do even this.
For example, consider logging libraries. It's useful to have statements like log.debug(someSlowFunction()) in your code. In LISPs it's really easy to create a (debug) macro that generates empty code when you don't want debug logging turned on. In other languages, you have to wrap the arguments in a function to avoid extra runtime costs, and even then you can't avoid the "if debug" conditional at runtime. All those anonymous function wraps add clutter, and that clutter accumulates. There are many other cases where having advanced language features greatly helps gluing together libraries.
Another aspect is the tooling. When I am considering a new library, I like to try it out in the REPL. In Clojure I can quickly start calling library functions, and use the (time) macro to get a sense of how long they take to evaluate. Not all popular languages are amenable to this kind of REPL-driven experimentation with libraries.
Not only does the language impact how you use libraries, but it also impacts what libraries may exist. Some libraries are simply not possible to write in less powerful programming languages. In LISP this would include any library that uses a macro. For example, Clojure was able to introduce core.async as a library, providing an async facility similar to what golang offers. But in most languages you wouldn't be able to implement that as a library.
Another major example is reagent vs. react. The concise hiccup representation supported by Reagent is only possible because of design decisions that went into Clojure. JavaScript users are stuck with JSX, which is less concise, and in my opinion far less good.
Another issue that arises when using libraries is whether or not the language has a static type system. Without getting into the age-old flamewar about static vs dynamic typing, I'll just note that popular languages differ in this dimension, and this has a big impact on what it's like to glue together libraries.
So overall, I think this essay undersells the benefits of LISP. Even if you spend all day gluing together libraries, LISP makes that much better by improving how you can call libraries, how you can quickly experiment with them, and even what kinds of libraries can exist.
For example, consider logging libraries. It's useful to have statements like log.debug(someSlowFunction()) in your code. In LISPs it's really easy to create a (debug) macro that generates empty code when you don't want debug logging turned on. In other languages, you have to wrap the arguments in a function to avoid extra runtime costs, and even then you can't avoid the "if debug" conditional at runtime. All those anonymous function wraps add clutter, and that clutter accumulates. There are many other cases where having advanced language features greatly helps gluing together libraries.
Another aspect is the tooling. When I am considering a new library, I like to try it out in the REPL. In Clojure I can quickly start calling library functions, and use the (time) macro to get a sense of how long they take to evaluate. Not all popular languages are amenable to this kind of REPL-driven experimentation with libraries.
Not only does the language impact how you use libraries, but it also impacts what libraries may exist. Some libraries are simply not possible to write in less powerful programming languages. In LISP this would include any library that uses a macro. For example, Clojure was able to introduce core.async as a library, providing an async facility similar to what golang offers. But in most languages you wouldn't be able to implement that as a library.
Another major example is reagent vs. react. The concise hiccup representation supported by Reagent is only possible because of design decisions that went into Clojure. JavaScript users are stuck with JSX, which is less concise, and in my opinion far less good.
Another issue that arises when using libraries is whether or not the language has a static type system. Without getting into the age-old flamewar about static vs dynamic typing, I'll just note that popular languages differ in this dimension, and this has a big impact on what it's like to glue together libraries.
So overall, I think this essay undersells the benefits of LISP. Even if you spend all day gluing together libraries, LISP makes that much better by improving how you can call libraries, how you can quickly experiment with them, and even what kinds of libraries can exist.
> All those anonymous function wraps add clutter, and that clutter accumulates.
Another great example of this is feature flags -- adding/removing an entire chunk of code in most languages tends to be limited to (for example) the inside of a function.
> JavaScript users are stuck with JSX, which is less concise, and in my opinion far less good.
And a key aspect to it as well is that JSX is a fully-custom extension, not something that can be implemented in JS as a library -- whereas Hiccup is 'just another library' allowing for fast iteration and experimentation by the community.
Another great example of this is feature flags -- adding/removing an entire chunk of code in most languages tends to be limited to (for example) the inside of a function.
(when-feature :something
(def some-constant ...)
(defn some-function [...]))
... is not possible in most languages, where you end up intermingling conditionals into the body of definitions and functions all over the place, creating dead code and issues besides.> JavaScript users are stuck with JSX, which is less concise, and in my opinion far less good.
And a key aspect to it as well is that JSX is a fully-custom extension, not something that can be implemented in JS as a library -- whereas Hiccup is 'just another library' allowing for fast iteration and experimentation by the community.
If the code in the parens that does what I think it does, Ruby has the same capability. Ruby allows you to redefine and even undefine... just about everything. Case in point: `binding.local_variable_set`. https://www.rubydoc.info/stdlib/core/Binding I think the only thing you can't do is undefine a local variable.
I've used environmental variables to determine which modules extend a class. This allowed me to test the same code against two different apis while we were migrating vendors. While this is done at "compile time", it could have easily been done during run time.
One nightmare of a system I worked on had the initializer of a class conditionally load modules to completely redefine the class. I called it reverse inheritance because it did the same thing as inheritance, without any of the readability or simplicity. Just because you can do a thing doesn't mean you should do a thing. XD
But I think Ruby is the exception that proves the rule. It allows absolutely crazy things and probably deserves the label of being a weird language. It's just wrapped in the trappings of a non-weird language.
I've used environmental variables to determine which modules extend a class. This allowed me to test the same code against two different apis while we were migrating vendors. While this is done at "compile time", it could have easily been done during run time.
One nightmare of a system I worked on had the initializer of a class conditionally load modules to completely redefine the class. I called it reverse inheritance because it did the same thing as inheritance, without any of the readability or simplicity. Just because you can do a thing doesn't mean you should do a thing. XD
But I think Ruby is the exception that proves the rule. It allows absolutely crazy things and probably deserves the label of being a weird language. It's just wrapped in the trappings of a non-weird language.
I am going to argue for a most normal language with your points.
> For example, consider logging libraries. It's useful to have statements like log.debug(someSlowFunction()) in your code.
Java/C# have good debuggers and thus you can set breakpoints.
You often want to have a debug printing in final release build anyway, activated through a --verbose option for example.
Thus I think this is less useful than it seems.
> Another aspect is the tooling. When I am considering a new library, I like to try it out in the REPL. In Clojure I can quickly start calling library functions, and use the (time) macro to get a sense of how long they take to evaluate. Not all popular languages are amenable to this kind of REPL-driven experimentation with libraries.
In python REPL you can do a reasonable level of experimentation with libraries. You can't do weird stuff like runtime monkey patching but that's not always considered a good thing.
In java also, there's jshell. (importing maven libs is little roundabout, but there are packages for that, and in return you get a solid ecosystem with static typing and great compilers / runtime.
> Another major example is reagent vs. react. The concise hiccup representation supported by Reagent is only possible because of design decisions that went into Clojure. JavaScript users are stuck with JSX, which is less concise, and in my opinion far less good.
It's a matter of opinion. In my opinion, jetpack compose or flutter (admittedly, fringe language but can be learnt by anyone with java or c# experience), are better way of doing UI than jsx / fxml etc..
> Even if you spend all day gluing together libraries, LISP makes that much better by improving how you can call libraries, how you can quickly experiment with them, and even what kinds of libraries can exist.
I think benefits of macros is way overblown, and higher order functions with ocassionally well documented APIs that use compile-time or run-time reflection are good enough. Macros are not worth the readability and compile time sacrifices.
Overall, my point is, blub paradox isn't one dimensional. I place more importance to tooling and libraries than language itself, as long as language isn't horrible.
> For example, consider logging libraries. It's useful to have statements like log.debug(someSlowFunction()) in your code.
Java/C# have good debuggers and thus you can set breakpoints.
You often want to have a debug printing in final release build anyway, activated through a --verbose option for example.
Thus I think this is less useful than it seems.
> Another aspect is the tooling. When I am considering a new library, I like to try it out in the REPL. In Clojure I can quickly start calling library functions, and use the (time) macro to get a sense of how long they take to evaluate. Not all popular languages are amenable to this kind of REPL-driven experimentation with libraries.
In python REPL you can do a reasonable level of experimentation with libraries. You can't do weird stuff like runtime monkey patching but that's not always considered a good thing.
In java also, there's jshell. (importing maven libs is little roundabout, but there are packages for that, and in return you get a solid ecosystem with static typing and great compilers / runtime.
> Another major example is reagent vs. react. The concise hiccup representation supported by Reagent is only possible because of design decisions that went into Clojure. JavaScript users are stuck with JSX, which is less concise, and in my opinion far less good.
It's a matter of opinion. In my opinion, jetpack compose or flutter (admittedly, fringe language but can be learnt by anyone with java or c# experience), are better way of doing UI than jsx / fxml etc..
> Even if you spend all day gluing together libraries, LISP makes that much better by improving how you can call libraries, how you can quickly experiment with them, and even what kinds of libraries can exist.
I think benefits of macros is way overblown, and higher order functions with ocassionally well documented APIs that use compile-time or run-time reflection are good enough. Macros are not worth the readability and compile time sacrifices.
Overall, my point is, blub paradox isn't one dimensional. I place more importance to tooling and libraries than language itself, as long as language isn't horrible.
I agree with your main points but to be nit-picky, every C/C++ project I've ever worked on was/is able to 100% compile out logging code with a compile time flag. No "if debug" is left in the compiled code, it just doesn't exist.
Just a note:
A constant false value used in an if statement will trivially be optimized away in case of any non-toy JIT compiler.
A constant false value used in an if statement will trivially be optimized away in case of any non-toy JIT compiler.
In the case of non-toy runtimes in general to be honest.
It's one of the simplest and most commonly implemented peephole optimisations - perl has handled it for as long as I can remember, I'm pretty sure cpython does, etc. etc.
It's one of the simplest and most commonly implemented peephole optimisations - perl has handled it for as long as I can remember, I'm pretty sure cpython does, etc. etc.
That's a good point. Even though this would weaken my argument (slightly), I now wonder if modern JITs can completely optimize debug.log(someExpensiveFunction()) into a NOOP if they realize that the argument won't end up being used inside the log function.
The javadoc for slf4j's Logger.debug implies that the JIT cannot be relied on for this:
http://slf4j.org/apidocs/org/slf4j/Logger.html#debug(java.la......)
"This form avoids superfluous string concatenation when the logger is disabled for the DEBUG level"
I think that means if you call Logger.debug("a"+"b"), the string concatenation happens even if DEBUG logging is disabled. But maybe JITs have improved since that javadoc was written, or the author was not aware of how smart JITs are.
I would be curious to know if there is a JIT expert who could weigh in on this question.
The javadoc for slf4j's Logger.debug implies that the JIT cannot be relied on for this:
http://slf4j.org/apidocs/org/slf4j/Logger.html#debug(java.la......)
"This form avoids superfluous string concatenation when the logger is disabled for the DEBUG level"
I think that means if you call Logger.debug("a"+"b"), the string concatenation happens even if DEBUG logging is disabled. But maybe JITs have improved since that javadoc was written, or the author was not aware of how smart JITs are.
I would be curious to know if there is a JIT expert who could weigh in on this question.
> 99.5% of programming consists of gluing together calls to library functions.
A common complaint at Google was "all I do is copy one protobuf to another". And I think that sums up programming -- that really is all we think we do. For example, a triple-A game just reads a stream of keyboard events, mouse events, and network packets, and emits streams of video frames, sound samples, and network packets. The rest is just details!
That is obviously not true, of course. We find the interfacing the most tedious, annoying, and painful part and overestimate how much time we spend doing it. Interfacing with anything is painful -- I had the idea for this comment in an instant, but I'm spending 5 minutes thinking of words and sentences, figuring out what order they should be in, and commanding my fingers to press keys on my keyboard to get it to you. But it would be incorrect to say that "99.5% of human cognition is convincing your fingers to press keys", even if that's a strict blocker to disseminating your idea on the Internet.
What that means is that tools can help us eliminate the tedious parts. The fact that tedious parts haven't gone away just means that there is more work to do. When the tools start doing what we need, you'll stop seeing the complaint that all programming is is moving data from one library to another. You'll start seeing the complaint "all I do is stare at the screen figuring out what to build."
A common complaint at Google was "all I do is copy one protobuf to another". And I think that sums up programming -- that really is all we think we do. For example, a triple-A game just reads a stream of keyboard events, mouse events, and network packets, and emits streams of video frames, sound samples, and network packets. The rest is just details!
That is obviously not true, of course. We find the interfacing the most tedious, annoying, and painful part and overestimate how much time we spend doing it. Interfacing with anything is painful -- I had the idea for this comment in an instant, but I'm spending 5 minutes thinking of words and sentences, figuring out what order they should be in, and commanding my fingers to press keys on my keyboard to get it to you. But it would be incorrect to say that "99.5% of human cognition is convincing your fingers to press keys", even if that's a strict blocker to disseminating your idea on the Internet.
What that means is that tools can help us eliminate the tedious parts. The fact that tedious parts haven't gone away just means that there is more work to do. When the tools start doing what we need, you'll stop seeing the complaint that all programming is is moving data from one library to another. You'll start seeing the complaint "all I do is stare at the screen figuring out what to build."
True and Shakespeare spent his life only gluing words together!! The only valuable thing he did was coining a few new words when he dared chasing weirdness!
Shakespeare invented how we think in post-Shakespeare English by transforming language, not to mention what is important to focus on in life (and sometimes the importance of focusing on important things).
99.9% of programming is a lot more of just plugging together library and API calls. We plug them together to user interfaces which is the apex of the age we live in: technology, empowering people to change the world in exciting new ways (as hackneyed as that sounds). It's just true. Our age involves a lot of globalization (in the Peter Thiel sense), but it's still very squarely part of a technology revolution.
Viaweb might've been a way to just make money for the most part. But that's not what impactful SaaS or other software is about. What the APIs / library calls are being connected to is of utmost importance.
And similarly, the ideas that Shakespeare came up with - the hundreds of ideas, that help us focus on what's most important to live a meaningful life, those are also helpful. And yes the language plays a role.
That said there is a grain of truth to this parent comment and PG's post. But there's also a lot missing. Both words and C++/Java-esque languages are super basic. But with enough of a fixed idea in mind, over time, they're good enough for getting at some really important things. And that is what matters.
99.9% of programming is a lot more of just plugging together library and API calls. We plug them together to user interfaces which is the apex of the age we live in: technology, empowering people to change the world in exciting new ways (as hackneyed as that sounds). It's just true. Our age involves a lot of globalization (in the Peter Thiel sense), but it's still very squarely part of a technology revolution.
Viaweb might've been a way to just make money for the most part. But that's not what impactful SaaS or other software is about. What the APIs / library calls are being connected to is of utmost importance.
And similarly, the ideas that Shakespeare came up with - the hundreds of ideas, that help us focus on what's most important to live a meaningful life, those are also helpful. And yes the language plays a role.
That said there is a grain of truth to this parent comment and PG's post. But there's also a lot missing. Both words and C++/Java-esque languages are super basic. But with enough of a fixed idea in mind, over time, they're good enough for getting at some really important things. And that is what matters.
> 99.5% of programming consists of gluing together calls to library functions.
First, my own career was not as pathologically skewed as this. I did mostly glued together calls to library functions, but I have done a fair share of algorithmic work, such as parsing and image processing. (And cryptography, though that was mostly done on my free time so I’m not sure that counts). Maybe web dev is like that, but I didn’t do web dev.
Second, this is a huge problem. This means that very few of us actually know how to program. And the problem feeds on itself: if one doesn’t know how to program, it will be easier, more tempting, to take on some significant dependency instead of just implementing the part you need, while tailoring it to your use case. Eventually knowledge is lost.
First, my own career was not as pathologically skewed as this. I did mostly glued together calls to library functions, but I have done a fair share of algorithmic work, such as parsing and image processing. (And cryptography, though that was mostly done on my free time so I’m not sure that counts). Maybe web dev is like that, but I didn’t do web dev.
Second, this is a huge problem. This means that very few of us actually know how to program. And the problem feeds on itself: if one doesn’t know how to program, it will be easier, more tempting, to take on some significant dependency instead of just implementing the part you need, while tailoring it to your use case. Eventually knowledge is lost.
Why would it be better for tens of tthousands of people to rewrite the same bit of code over and over again,
? This amount of code reuse sounds excellent to me.
Because then they would learn to write that code. Because it’s not the same exact bit of code, but just a part, or a different version depending on the exact context. Because taking on a dependency is just as costly as rewriting the thing, if not more…
Code reuse is good, but we should not forget that its costs are not nil.
Code reuse is good, but we should not forget that its costs are not nil.
> Eventually knowledge is lost
There're thousands teams all over the world working on various projects which require people to program. At the very least, someone needs to write and maintain these libraries. Also there're interesting domains like game development, CAD/CAM/CAE, HPC, embedded. Knowledge is transferred within such teams.
There're thousands teams all over the world working on various projects which require people to program. At the very least, someone needs to write and maintain these libraries. Also there're interesting domains like game development, CAD/CAM/CAE, HPC, embedded. Knowledge is transferred within such teams.
But a meta-smart engineer that wants to maximise real world impact through a software project would realise that not all ‘smart’ people agree about what smart ‘IS’.
So for engineering efforts that require large amounts of people to contribute, a more restrictive, less flexible language can yield better overall productivity by expanding the pool of potential contributors and reducing friction arising from pointless differences and ‘smart’ programming (like macros).
In other words, removing ‘smart’ programming features like macros probably turns out to be (weirdly) smart in the real world.
So for engineering efforts that require large amounts of people to contribute, a more restrictive, less flexible language can yield better overall productivity by expanding the pool of potential contributors and reducing friction arising from pointless differences and ‘smart’ programming (like macros).
In other words, removing ‘smart’ programming features like macros probably turns out to be (weirdly) smart in the real world.
Go is one of my favorite languages exactly for the reason you describe - it focuses on getting things done and it scales to collaborating with many people.
At the same time I enjoy tinkering with different new languages every once in a while and I think that's what the article talks about. There's a place for experimenting and trying out new things, that doesn't mean that you need to rewrite everything in Haskell.
At the same time I enjoy tinkering with different new languages every once in a while and I think that's what the article talks about. There's a place for experimenting and trying out new things, that doesn't mean that you need to rewrite everything in Haskell.
But not having enough abstraction is also problematic and Go does cross that line for me at least.
Eg. on my current CRUD app, we use Spring’s aspects to implement some permission checking before specific HTTP requests. The alternative - copying a function call to each place - would be much more bug prone, a change in one will not be propagated, etc.
While it may not be the best example, there are many similar cases where I feel that less abstraction would just make it unmaintainable.
Eg. on my current CRUD app, we use Spring’s aspects to implement some permission checking before specific HTTP requests. The alternative - copying a function call to each place - would be much more bug prone, a change in one will not be propagated, etc.
While it may not be the best example, there are many similar cases where I feel that less abstraction would just make it unmaintainable.
No need to embed function calls everywhere. The integration of authorization middleware should only be as complicated as your routing:
mux.Handle("/", middlewareOne(middlewareTwo(finalHandler)))
https://www.alexedwards.net/blog/making-and-using-middleware
mux.Handle("/", middlewareOne(middlewareTwo(finalHandler)))
https://www.alexedwards.net/blog/making-and-using-middleware
Smart here is used as an indicator of a language with unique powers. So it's more about what the engineer can do to expand his own mind, to get new perspectives.
But in one sense, there are no languages with unique powers. Ultimately all languages are instructions for a CPU. The language can make you ‘feel’ smart as an individual or ‘be’ smart by allowing a large group of people to accomplish something that couldn’t be achieved by a single person.
My hypothesis is that languages that are good at making the individual feel smart have proven to be less effective at allowing a large group of programmers to collaborate.
My hypothesis is that languages that are good at making the individual feel smart have proven to be less effective at allowing a large group of programmers to collaborate.
This was certainly my experience with Smalltalk in the 1990s. The "good" programmers oustripped the departmental guys so quickly we ended up with two factions in the one company and libraries of code only the gurus understood. It killed the code re-use stats and resulted in a lot of duplicated work.
I think that scenario speaks to the importance of training, regular knowledge sharing sessions, pair programming, and the like. I've found myself in the opposite situation, where the team refuses to use a language feature that will make life significantly easier out of consideration for some hypothetical clueless graduate.
Addressing a skill gap technically seems a bit short sighted compared to addressing it culturally. Especially because most weird language features don't actually require you to be smart to understand them; they're just unfamiliar.
Addressing a skill gap technically seems a bit short sighted compared to addressing it culturally. Especially because most weird language features don't actually require you to be smart to understand them; they're just unfamiliar.
I've been thinking about this a bit, and something like Smalltalk is just completely alien if you came from a C or a Cobol background. The Cobol guys were used to using a rich, transaction based environment and the C guys were used to rolling their own everything. When they hit Smalltalk and the "if" statement looks like...wtf the boolean does the work? Or even better, one of the gurus decided that the best way to solve the "how do I get my database connection information" was to give the users a class that deliberately threw an exception they were meant to catch at the top of the chain of execution. In this case, the guru wrote a class that threw a "#doesNotUnderstand" which can be caught, re-injected with the appropriate object, and the program can continue.
It quite simply was too much for some guys to get their heads around. It probably wasn't the best way to use an exception either, but occasionally when I'm working with .NET I really wish I could catch some of those, re-inject the expected bit of data and have my program continue it's merry way.
One of the modes of working in Smalltalk is to deliberately write something half finished, so when the #doesNotUnderstand gets thrown, you can edit the code during while debugging, accept it, and continue the program. If it takes a long time to reproduce a bug in a C# program, you're stuck with going through all the motions to get back to where the bug exists, but in Smalltalk you could simply fill in the bit of broken code, continue and it would work from then on.
Again - hard to change the habits of a lifetime and I'm not sure that as a long term development environment it's very healthy (you might fix an instance of the bug, but did you fix all the possible combinations of it?)
Still, when you're in a Smalltalk groove it feels like walking a high wire and performing magic.
It quite simply was too much for some guys to get their heads around. It probably wasn't the best way to use an exception either, but occasionally when I'm working with .NET I really wish I could catch some of those, re-inject the expected bit of data and have my program continue it's merry way.
One of the modes of working in Smalltalk is to deliberately write something half finished, so when the #doesNotUnderstand gets thrown, you can edit the code during while debugging, accept it, and continue the program. If it takes a long time to reproduce a bug in a C# program, you're stuck with going through all the motions to get back to where the bug exists, but in Smalltalk you could simply fill in the bit of broken code, continue and it would work from then on.
Again - hard to change the habits of a lifetime and I'm not sure that as a long term development environment it's very healthy (you might fix an instance of the bug, but did you fix all the possible combinations of it?)
Still, when you're in a Smalltalk groove it feels like walking a high wire and performing magic.
Being clever alone or in a group can be different things and valuable in different situations.
Sure, but the article is rather disparaging to the engineer spending their life in the so called ‘mainstream’ 99.5% of languages, implying their work is in someway less ‘smart’ than those exploring the 0.5%.
I am offering a counterpoint that instead, some ‘smart’ engineers have concluded that boring programming languages are the way to get big things done.
I am offering a counterpoint that instead, some ‘smart’ engineers have concluded that boring programming languages are the way to get big things done.
There are different types of problems to be solved.
There are "business as usual" problems, so gluing libraries, CRUD's. Where having junior level code is by far most efficient because you probably have to face multiple issues. Ones like employee rotation, lots of business requests where it is by far better to have code duplication and some tweaks in copy pasted code so it stays simple and don't introduce wrong abstractions. Even generic types as in C# I would consider mostly bad idea to use for those.
Other type would be libraries or frameworks where you definitely cannot afford "copy/paste/change". I would hope that people working on libraries or frameworks stick to what they write for at least 5 years and hope they could be life long supporters. For those people and types of projects you want some smart features like generic types so that they can simply do their job. I cannot think of a framework that would not use quite complex ideas to achieve what it should be.
Of course there are many more like hardware programming, operating systems and the ones that PG pointed as 0.5% of developers work like really hard/weird problems one cannot solve by simply making CRUD.
I have pointed only at things that are in my line of work. Unfortunately there is a lot of people who should be delivering things as in CRUD/glue/junior so the first category. Where what THEY think they should be doing is some kind of framework/libraries work. Because they think that it will make business "future proof" and "that is what professional developers should do", while wasting resources.
Of course doing CRUD/glue in an easy way that can be understood by juniors and fast is important and highly valuable in itself. But I think a lot of people don't understand value of it.
There are "business as usual" problems, so gluing libraries, CRUD's. Where having junior level code is by far most efficient because you probably have to face multiple issues. Ones like employee rotation, lots of business requests where it is by far better to have code duplication and some tweaks in copy pasted code so it stays simple and don't introduce wrong abstractions. Even generic types as in C# I would consider mostly bad idea to use for those.
Other type would be libraries or frameworks where you definitely cannot afford "copy/paste/change". I would hope that people working on libraries or frameworks stick to what they write for at least 5 years and hope they could be life long supporters. For those people and types of projects you want some smart features like generic types so that they can simply do their job. I cannot think of a framework that would not use quite complex ideas to achieve what it should be.
Of course there are many more like hardware programming, operating systems and the ones that PG pointed as 0.5% of developers work like really hard/weird problems one cannot solve by simply making CRUD.
I have pointed only at things that are in my line of work. Unfortunately there is a lot of people who should be delivering things as in CRUD/glue/junior so the first category. Where what THEY think they should be doing is some kind of framework/libraries work. Because they think that it will make business "future proof" and "that is what professional developers should do", while wasting resources.
Of course doing CRUD/glue in an easy way that can be understood by juniors and fast is important and highly valuable in itself. But I think a lot of people don't understand value of it.
IMO the greatest achievement of collaborative programming so far is Linux. Not a CRUD application written by Junior developers.
And it is written in C, which I assume is not one of PG’s blessed ‘weird’ languages that supposedly superior programmers are using.
And it is written in C, which I assume is not one of PG’s blessed ‘weird’ languages that supposedly superior programmers are using.
Here's what I could write in C that I couldn't in (most) other languages:
Sure, you can crash your program if there isn't the hardware you expect at 0xFFFF1014. Sure, you can use this exact approach to trash memory anywhere in your program image. But it lets you easily do things that are not easily done in most other languages.
unsigned short *reg = (unsigned short*)0xFFFF1014;
*reg = 0x1027;
If you have memory-mapped I/O (like the 68000-style architectures did), this lets you take a hardware register at a known address, and write any bit pattern you wanted to it. For embedded hardware, this meant that the hardware was right there, ready to work with.Sure, you can crash your program if there isn't the hardware you expect at 0xFFFF1014. Sure, you can use this exact approach to trash memory anywhere in your program image. But it lets you easily do things that are not easily done in most other languages.
Very interesting and you’re right that this is almost uniquely and most easily expressible in C, but if that makes C ‘weird’ I don’t understand what the point of the article is anymore.
By that definition all languages are ‘weird’ including Java and have uniquely expressible koans within them.
Maybe it boils down to ‘use the right tool for the job’, ie, the tool that lends itself best to the job at hand.
By that definition all languages are ‘weird’ including Java and have uniquely expressible koans within them.
Maybe it boils down to ‘use the right tool for the job’, ie, the tool that lends itself best to the job at hand.
Yes, weird depends. PG's point is, again, about finding new pockets of programming, not necessarily finding the best tool -- meta or not -- for a task at hand. Fine, everything is binary code in the end; it doesn't mean there aren't different abstractions that can be made on top of it, obviously. You are probably right that PG is biased towards "hacking" rather than team software engineering by him implying that the 99.5% of "glue programming" is boring. There is potential for a lot of mastery on the glue front, but this point about weirdness is about the remaining 0.5% and how to access it via the language route. Personally I'd be interested to hear what PG says about the weirdness of OOP...
I would have to ask you to explain a bit more why is it that - you took from my comment?
I am not writing about one or the other being better, so I would like to see more context from your point of view.
I enumerated problems as I understand those and tried to match proper tools - while thinking that as a lot of businesses pay for CRUD work, they think it is valuable as in monetary value not in some absolute terms of what we can achieve with software development. I don't think solving hard problems that are "0.5%" of development work done in some esoteric language is greatest achievement or best in absolute terms.
I am not writing about one or the other being better, so I would like to see more context from your point of view.
I enumerated problems as I understand those and tried to match proper tools - while thinking that as a lot of businesses pay for CRUD work, they think it is valuable as in monetary value not in some absolute terms of what we can achieve with software development. I don't think solving hard problems that are "0.5%" of development work done in some esoteric language is greatest achievement or best in absolute terms.
I don't have a background on theory of programming languages or history of CS (I'm EE), correct me if I'm wrong but:
1- I have never seen a language that made me wow. Like, to me, this whole concept of making a digital logic architecture do a task should be "solved" in a systematic/mathematical sense. Yet, whenever I read on criticisms of languages, people always talk about stuff like "Go doesn't have generators", "Rust macro is a mistake", "I don't like python's async story", "C's way of things is outdated" etc...
As an analogy, this whole discussion of PLs in CS circles is like complaining about whether we should use `dot` notation or `d/d(t)` notation or whether we should use `t` or `x` in solving a differential equation. Like, we are not solving the actual DE, but complaining about issues irrelevant to the big picture.
2- I have a feeling that https://www.red-lang.org/ is something completely new and innovative.
3- I think concepts like formal-proofs and RTOSes are under-rated.
1- I have never seen a language that made me wow. Like, to me, this whole concept of making a digital logic architecture do a task should be "solved" in a systematic/mathematical sense. Yet, whenever I read on criticisms of languages, people always talk about stuff like "Go doesn't have generators", "Rust macro is a mistake", "I don't like python's async story", "C's way of things is outdated" etc...
As an analogy, this whole discussion of PLs in CS circles is like complaining about whether we should use `dot` notation or `d/d(t)` notation or whether we should use `t` or `x` in solving a differential equation. Like, we are not solving the actual DE, but complaining about issues irrelevant to the big picture.
2- I have a feeling that https://www.red-lang.org/ is something completely new and innovative.
3- I think concepts like formal-proofs and RTOSes are under-rated.
About (1)
The first Prolog program I ran just blew my mind - sort of "But how did it do that!?" I understood what I wrote down, and how that explained the problem, but a mental model if how that was used by the runtime to solve the problem needed a while to develop.
Similarly Smalltalk was like: "Everything is an object?". I mean the language doesn't have an "if" statement! You send a code block as a message to a boolean value with an "ifTrue" method.
Not that I know these languages to any significant depth, just dabbling.
To me there are a few oddball languages that are simple, have one abstraction of abstraction and are quite weird, but have a stack record of "heroic deeds" by their practitioners.
I mean C#, Java, C, C++, Go are quite similar if you squint.
But Prolog, Forth, Smalltalk, J, Lisp, etc. are definitely something else that stretches your mind a bit in different directions.
And I think that this is a valid point.
It's worth spending a bit of time reading about and playing with these languages. Not because they are useful (although they might well be), but because they will give you a few different ways of thinking about problems that will extend your mental reach.
The first Prolog program I ran just blew my mind - sort of "But how did it do that!?" I understood what I wrote down, and how that explained the problem, but a mental model if how that was used by the runtime to solve the problem needed a while to develop.
Similarly Smalltalk was like: "Everything is an object?". I mean the language doesn't have an "if" statement! You send a code block as a message to a boolean value with an "ifTrue" method.
Not that I know these languages to any significant depth, just dabbling.
To me there are a few oddball languages that are simple, have one abstraction of abstraction and are quite weird, but have a stack record of "heroic deeds" by their practitioners.
I mean C#, Java, C, C++, Go are quite similar if you squint.
But Prolog, Forth, Smalltalk, J, Lisp, etc. are definitely something else that stretches your mind a bit in different directions.
And I think that this is a valid point.
It's worth spending a bit of time reading about and playing with these languages. Not because they are useful (although they might well be), but because they will give you a few different ways of thinking about problems that will extend your mental reach.
I feel the same way about Snobol4. It gave me the same wow factor that Prolog did.
I came to this thread to write about prolog too. it wasn't the first program I wrote, but after a good introduction, then I started thinking the way prolog makes you think, I was blown away. I loved it and I hope I get to use it again!
> Similarly Smalltalk was like: "Everything is an object?". I mean the language doesn't have an "if" statement! You send a code block as a message to a boolean value with an "ifTrue" method.
Incidentally, I don't think that this is how they got there, but this could have come from taking the lambda calculus extremely seriously: in the classical encoding, `true = fst` and `false = snd` (i.e., `true x y = x` and `false x y = y`; or, pointlessly, `true = const` and `false = true id`), so that `if` is just `id`, in the sense that `if true = true` (meaning `if true x y = true x y = x`) and `if false = false` (meaning `if false x y = false x y = y`).
https://en.wikipedia.org/wiki/Lambda_calculus#Logic_and_pred...
Incidentally, I don't think that this is how they got there, but this could have come from taking the lambda calculus extremely seriously: in the classical encoding, `true = fst` and `false = snd` (i.e., `true x y = x` and `false x y = y`; or, pointlessly, `true = const` and `false = true id`), so that `if` is just `id`, in the sense that `if true = true` (meaning `if true x y = true x y = x`) and `if false = false` (meaning `if false x y = false x y = y`).
https://en.wikipedia.org/wiki/Lambda_calculus#Logic_and_pred...
> 1- I have never seen a language that made me wow. Like, to me, this whole concept of making a digital logic architecture do a task should be "solved" in a systematic/mathematical sense. Yet, whenever I read on criticisms of languages, people always talk about stuff like "Go doesn't have generators", "Rust macro is a mistake", "I don't like python's async story", "C's way of things is outdated" etc...
Math does have a lot of notations that express the same, but are used for different purpose, where some of those are better suited for solving some task than others. One of the simpler examples is polar vs cartesian coordinates. Where polar coordinates is expressed by angels and distance from a zero point. While cartesian we use the distance on axis from the zero point. Both can express all the same points, but some problems are easier to solve in one of those and some are easier to solve in the other. Coordinate system is definitely not the only place where you have this in math, and it is probably one of the simplest examples.
So math, and all it's different ways of being expressed is more of an example why we need different languages, and that programming languages matter. Than a counterexample of why languages shouldn't matter, and that we are fine with any one language.
Math does have a lot of notations that express the same, but are used for different purpose, where some of those are better suited for solving some task than others. One of the simpler examples is polar vs cartesian coordinates. Where polar coordinates is expressed by angels and distance from a zero point. While cartesian we use the distance on axis from the zero point. Both can express all the same points, but some problems are easier to solve in one of those and some are easier to solve in the other. Coordinate system is definitely not the only place where you have this in math, and it is probably one of the simplest examples.
So math, and all it's different ways of being expressed is more of an example why we need different languages, and that programming languages matter. Than a counterexample of why languages shouldn't matter, and that we are fine with any one language.
I agree with your statement that concepts like formal-proofs is underrated. Fortunately, one of the general trend that I'm seeing going forward is the birth of programming languages with more and more sophisticated type systems. In these languages type systems do not only capture object types (eg., int, string) but also various other aspects.
For example functional languages and their monadic construct supports capturing various interesting aspects. This allows for really useful feature such as capturing concurrency behaviour (Future/Promise) and possibility of returning errors (Try), at compile time.
Then there's Rust where memory ownership can be reasoned about at compile time.
Languages such as Idris allows to declare a type that is dependent on the value (eg., declare that this function "x() can only return odd numbers?)
I also happen to work in a company where we try to bring type-safety to the databse world with our product TypeDB.
I think this trend is very good to see - stronger type-system = safer code. In a way the stronger type system a programming language has, the more it can validate at compile time. And therefore, we can say that such language somewhat provides what formal proof / formal verification systems ought to provide, but in a practical setting.
For example functional languages and their monadic construct supports capturing various interesting aspects. This allows for really useful feature such as capturing concurrency behaviour (Future/Promise) and possibility of returning errors (Try), at compile time.
Then there's Rust where memory ownership can be reasoned about at compile time.
Languages such as Idris allows to declare a type that is dependent on the value (eg., declare that this function "x() can only return odd numbers?)
I also happen to work in a company where we try to bring type-safety to the databse world with our product TypeDB.
I think this trend is very good to see - stronger type-system = safer code. In a way the stronger type system a programming language has, the more it can validate at compile time. And therefore, we can say that such language somewhat provides what formal proof / formal verification systems ought to provide, but in a practical setting.
Are you familiar with prolog ? For me it was kind of "wow" as it's very different from all other programming languages. I don't use it but it was very interesting to learn it.
The OP doesn't really touch on this aspect, but I think one of the most important traits of a PL is what it doesn't let you say (there's almost nothing that Lisp doesn't let you say, which is a double-edged sword)
A majority of Haskell's innovations have been in the space of placing interesting new kinds of constraints on code
Rust's big innovation is not allowing you to make memory errors (in designated sections of your code)
Go's headlining feature is not allowing people to write code that's extremely abstracted, which helps readability
And this isn't just for avoiding mistakes: code that's very regular can be more easily processed by a machine to make it more efficient
So looking at it through the lens of syntax is missing a lot of the picture. You're right that syntax is rarely important. At the end of the day the differences between code and notation are: 1) code often grows to enormous sizes where managing it becomes a challenge, and 2) code is processed by a machine
A majority of Haskell's innovations have been in the space of placing interesting new kinds of constraints on code
Rust's big innovation is not allowing you to make memory errors (in designated sections of your code)
Go's headlining feature is not allowing people to write code that's extremely abstracted, which helps readability
And this isn't just for avoiding mistakes: code that's very regular can be more easily processed by a machine to make it more efficient
So looking at it through the lens of syntax is missing a lot of the picture. You're right that syntax is rarely important. At the end of the day the differences between code and notation are: 1) code often grows to enormous sizes where managing it becomes a challenge, and 2) code is processed by a machine
> Rust's big innovation is not allowing you to make memory errors (in designated sections of your code)
I’d actually say Rust’s ownership model is its defining feature and big innovation; memory safety without garbage collection was the original goal of the project, but that has arguably actually ended up being more of a side-effect of the ownership model than the actual artefact, from the innovations perspective. Several other languages have been adopting significant ideas from Rust’s ownership model without actually needing it for memory safety.
(Also, some factual clarifications on the wording you used: Rust doesn’t allow you to make memory errors except in areas marked with the “unsafe” keyword—you’re marking small dangerous zones, rather than marking safe zones. But scripting languages are normally memory-safe too, it’s the absence of any garbage collector that makes Rust special there.)
I’d actually say Rust’s ownership model is its defining feature and big innovation; memory safety without garbage collection was the original goal of the project, but that has arguably actually ended up being more of a side-effect of the ownership model than the actual artefact, from the innovations perspective. Several other languages have been adopting significant ideas from Rust’s ownership model without actually needing it for memory safety.
(Also, some factual clarifications on the wording you used: Rust doesn’t allow you to make memory errors except in areas marked with the “unsafe” keyword—you’re marking small dangerous zones, rather than marking safe zones. But scripting languages are normally memory-safe too, it’s the absence of any garbage collector that makes Rust special there.)
Either way the point stands: Rust’s biggest features are about what you can’t do, not what you can do
Absolutely.
I took a class simply named "Programming Languages" as part of my degree, and we focused on one different language each week for the entire semester.
The only two to make me go "wow" were Lisp and Haskell. They really are that strange and different.
(Well, technically the assembly language we used also made me go "wow," in the sense that I had sympathy for the suffering of programmers in the olden days, but as an EE you may have a different takeaway.)
The only two to make me go "wow" were Lisp and Haskell. They really are that strange and different.
(Well, technically the assembly language we used also made me go "wow," in the sense that I had sympathy for the suffering of programmers in the olden days, but as an EE you may have a different takeaway.)
> As an analogy, this whole discussion of PLs in CS circles is like complaining about whether we should use `dot` notation or `d/d(t)` notation or whether we should use `t` or `x` in solving a differential equation
Until you start manipulating the 'dt's on their own which wouldn't occur to you if you were using the dot notation.
(And then some people tell you that it's illegal, or maybe okay but only if you've taken real analysis... it gets confusing)
Until you start manipulating the 'dt's on their own which wouldn't occur to you if you were using the dot notation.
(And then some people tell you that it's illegal, or maybe okay but only if you've taken real analysis... it gets confusing)
1. Read this: https://physicsworld.com/a/how-feynman-diagrams-transformed-...
Main point:
> Theory, Kaiser suggests, is ultimately less important to theorists than the tools that mediate their calculations.
To me, programming languages are almost like Feynman diagrams or chemical notation in that they define how we think or what we think is 'real' in programming. In that sense, we should absolutely care about the fine-grained characteristics of the tools. After all, doesn't a chef prefer a sharp knife to a blunt one?
Main point:
> Theory, Kaiser suggests, is ultimately less important to theorists than the tools that mediate their calculations.
To me, programming languages are almost like Feynman diagrams or chemical notation in that they define how we think or what we think is 'real' in programming. In that sense, we should absolutely care about the fine-grained characteristics of the tools. After all, doesn't a chef prefer a sharp knife to a blunt one?
(1) F# Type Providers still blow my mind.
Strongly typed SQL/XML/CSV/JSON without boilerplate is a massive leap forward, and it's a shame that it hasn't caught on.
https://fsprojects.github.io/SQLProvider/#Example
Strongly typed SQL/XML/CSV/JSON without boilerplate is a massive leap forward, and it's a shame that it hasn't caught on.
https://fsprojects.github.io/SQLProvider/#Example
Scala experimented with type providers, but it looks abandoned: https://docs.scala-lang.org/overviews/macros/typeproviders.h...
Idris has them (but it's Idris) https://docs.idris-lang.org/en/latest/guides/type-providers-...
This SO answer states that Java has something similar called "Type Manifold" https://stackoverflow.com/a/53037742
I only have F# experience so I can't comment about the ergonomics of the above. I love, love, love the JSON/Regex type providers. I'm trying to move away from SQL (to event sourcing) so haven't used that type provider yet.
Idris has them (but it's Idris) https://docs.idris-lang.org/en/latest/guides/type-providers-...
This SO answer states that Java has something similar called "Type Manifold" https://stackoverflow.com/a/53037742
I only have F# experience so I can't comment about the ergonomics of the above. I love, love, love the JSON/Regex type providers. I'm trying to move away from SQL (to event sourcing) so haven't used that type provider yet.
> As an analogy, this whole discussion of PLs in CS circles is like complaining about whether we should use `dot` notation or `d/d(t)`
The fact that makes all the difference is that informal notations in math, science, linguistics and other fields are interpreted by human brains, human brains are flexible at filling the gaps and deriving most reasonable consequences from their incomplete descriptions. Symbolic notations outside of formal logic and programming are mostly an annotation DSL to augment humans communicating with each other.
In contrast, a programming language imposes itself upon you in a way that those notations don't. You have to describe a lot of things in it. Underspecification leaves too much to the machine, overspecification tortures the poor brains reading after you. The optimal boundary differs depending on the thing being described, might not always exist and sometimes not always that satisfactory (still pisses off the humans or the machines in some parts or another of the program).
Making different programs in different languages and making them somehow all cooperate to describe the same problem opens a whole new can of worms that's just as hard to solve as the original problem. It's nowhere near as hard to mix-and-match mathematical notations (e.g. Lagrangian formulation of classical mechanics where Newtonian dot notation is used to denote time derivatives and Leibnizian fraction notation is used to denote coordinate derivatives). If you're stuck, you can always invent a new notation or whip up a diagram, describe how they work on-the-fly in some shared meta-language, then use it right away anywhere and everywhere you want, including in conjunction with old notations.
So it basically boils down to the capabilities of the underlying machine. The human brain is one hell of a machine, you have a lot of leeway. But programming languages are primarily ways to communicate with a very different type of machine, and as if that wasn't enough they _also_ still have to support wet brains, and as if that wasn't enough they are extremely rigid and heavyweight compared to human notations, i.e. much more difficult and time-consuming to design and implement and spread (when they are new) and de-spread (when they are obsolete and there are better alternatives).
The fact that makes all the difference is that informal notations in math, science, linguistics and other fields are interpreted by human brains, human brains are flexible at filling the gaps and deriving most reasonable consequences from their incomplete descriptions. Symbolic notations outside of formal logic and programming are mostly an annotation DSL to augment humans communicating with each other.
In contrast, a programming language imposes itself upon you in a way that those notations don't. You have to describe a lot of things in it. Underspecification leaves too much to the machine, overspecification tortures the poor brains reading after you. The optimal boundary differs depending on the thing being described, might not always exist and sometimes not always that satisfactory (still pisses off the humans or the machines in some parts or another of the program).
Making different programs in different languages and making them somehow all cooperate to describe the same problem opens a whole new can of worms that's just as hard to solve as the original problem. It's nowhere near as hard to mix-and-match mathematical notations (e.g. Lagrangian formulation of classical mechanics where Newtonian dot notation is used to denote time derivatives and Leibnizian fraction notation is used to denote coordinate derivatives). If you're stuck, you can always invent a new notation or whip up a diagram, describe how they work on-the-fly in some shared meta-language, then use it right away anywhere and everywhere you want, including in conjunction with old notations.
So it basically boils down to the capabilities of the underlying machine. The human brain is one hell of a machine, you have a lot of leeway. But programming languages are primarily ways to communicate with a very different type of machine, and as if that wasn't enough they _also_ still have to support wet brains, and as if that wasn't enough they are extremely rigid and heavyweight compared to human notations, i.e. much more difficult and time-consuming to design and implement and spread (when they are new) and de-spread (when they are obsolete and there are better alternatives).
There are real differences between languages[0], but they tend to be less apparent than the syntactical fluff -- you have to get past the syntax to appreciate the emergent behavior of the language when you are solving a non-trivial problem in it. Also, what set of language features people want is often shaped by historical accident of what they're accustomed to, but also by the problem domain is. It's doubtful that there could be an "ultimate language" that's right for everyone and everything. One of Julia's creators quipped that designing a language isn't just a technical problem, it's also an exercise in applied psychology.
Thanks for point to Red, I'll have to check it out.
Yeah, I agree that it's about time we had more formal methods in software. OTOH, messing around with Dafny has been fun (well, I enjoyed abstract algebra in undergrad), but it takes forever to write anything useful.
[0]https://homepage.cs.uiowa.edu/~jgmorrs/eecs762f19/papers/fel...
Thanks for point to Red, I'll have to check it out.
Yeah, I agree that it's about time we had more formal methods in software. OTOH, messing around with Dafny has been fun (well, I enjoyed abstract algebra in undergrad), but it takes forever to write anything useful.
[0]https://homepage.cs.uiowa.edu/~jgmorrs/eecs762f19/papers/fel...
It's easier to argue about programming languages than it is to argue about things that actually matter[0]. You start to realize that programming languages matter very little the more experience you get programming. Some languages are better suited for one task over another, but there is no objective "best" language.
This isn't to say that the choice of language doesn't matter -- it does. If your team knows C then you probably shouldn't try to start a new project in Java without some ramp-up/learning time. If you're working in JavaScript then you better set aside a lot of time before writing production code in Haskell. These are issues that are more related to people than they are to programming.
The best language is the one that you/your team knows. The second best is the one that suits the task.
[0] https://en.wikipedia.org/wiki/Law_of_triviality
This isn't to say that the choice of language doesn't matter -- it does. If your team knows C then you probably shouldn't try to start a new project in Java without some ramp-up/learning time. If you're working in JavaScript then you better set aside a lot of time before writing production code in Haskell. These are issues that are more related to people than they are to programming.
The best language is the one that you/your team knows. The second best is the one that suits the task.
[0] https://en.wikipedia.org/wiki/Law_of_triviality
(2) Red is just a (worse) REBOL variant, actually.
I think its more correct to call Red (currently) an incomplete Rebol variant but with loftier ambitions due to its Red/System & toolchain.
Can you elaborate on this please? (About it being worse)
This is one that blew my mind back in the day, compare these two quicksort implementations:
https://rosettacode.org/wiki/Sorting_algorithms/Quicksort#C
https://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Ha...
The C code implement quicksort, the Haskell code does not. It has different (worse) space characteristics. Proper quicksort in Haskell is not a two-liner.
Is it a parlour trick in lisp or erlang?
It's a parlor trick, but a cool one is my point.
But you can make that parlor trick work ok in C too if you even the playing field by implementing a partition() helper separately.
The Haskell version reveals more of a deficiency in the C standard library than the language.
The Haskell version reveals more of a deficiency in the C standard library than the language.
A sort is a sort or it isn't a sort? Don't get it. Is the claim that the first quick sort impl. in haskell on rosetta is NOT a quick sort?
Quicksort is a specific algorithm involving two array pointers and swapping values. The haskell implementation in question is not it. It’s not a “claim”, it is what it is.
A parlor trick that doesn't implement what it claims to, even if cool, doesn't make a point very well...
1) Try an array language like J or APL. Or some other paradigm outside the mainstream.
> A concrete example: Lisp macros.
Who didn't see this coming?
For someone who's constantly extolling the importance of other languages and flexible thinking, Paul doesn't seem to ever be able to get his mind out of Lisp.
> [Lisp macros] by their nature would be hard to implement properly in a language without turning it into a dialect of Lisp.
There are numerous counter examples to this claim, the most obvious one being Rust.
How do you call someone who only knows one language and refuses to learn new ones? Oh right, a blub programmer.
Who didn't see this coming?
For someone who's constantly extolling the importance of other languages and flexible thinking, Paul doesn't seem to ever be able to get his mind out of Lisp.
> [Lisp macros] by their nature would be hard to implement properly in a language without turning it into a dialect of Lisp.
There are numerous counter examples to this claim, the most obvious one being Rust.
How do you call someone who only knows one language and refuses to learn new ones? Oh right, a blub programmer.
Indeed. The author's appreciation of Lisp is well known. If he really is convinced by this abstract argument, it would have been nice to know what other weird languages besides Lisp it has inspired him to learn. APL, Prolog, Smalltalk, R, Haskell - perhaps?
I don't mean to be too dismissive. I think this short piece was thought-provoking enough to be worth reading, and it was not a bad argument in favor of Lisp. Maybe I really should learn Lisp. But if the heuristic was generalized from just one example, it might overfit to just one particular kind of weirdness.
I don't mean to be too dismissive. I think this short piece was thought-provoking enough to be worth reading, and it was not a bad argument in favor of Lisp. Maybe I really should learn Lisp. But if the heuristic was generalized from just one example, it might overfit to just one particular kind of weirdness.
It's pretty disappointed that there's an article called Weird Languages and all we get is Lisp again.
I also think it's a bit arrogant to imply that if you don't like Lisp than you're just not smart. I'm sure many of us have been exposed to Lisp and still prefer to programming language that less powerful but more humane.
I also think it's a bit arrogant to imply that if you don't like Lisp than you're just not smart. I'm sure many of us have been exposed to Lisp and still prefer to programming language that less powerful but more humane.
[deleted]
I wouldn’t care to claim that Rust has Lisp macros.
Lisp macros you define just like any Lisp function, and allow you to create new syntax constructs indistinguishable from any built-in constructs, which can execute whatever code they like as part of the process.
In Lisp, macros are evaluated at run-time and can do anything, including access program state (if you play your cards right). They consume something that’s very roughly an AST, and emit something that’s very roughly an AST, and the language makes doing that quite easy, largely because it’s all structural in nature.
In Rust, you’ve got macro_rules! which provides convenient syntax for simple structural macros, and then after that you have procedural macros which have the full power, but have to be written in a completely different place and get evaluated at compile-time only (so no dynamic macros), in a completely different context to the code that calls them (so no program state). They’re a lot harder to work with, consuming a stream of token trees (e.g. `if`, `3`, `.`, `{ … }`, `(…)`) and emitting a stream of token trees, a representation that’s clumsy and prone to error (especially since it’s not structural) though this can be mitigated a lot with crates like syn and quote which can make the process at least somewhat more structural, but it’s still way more clumsy than Lisp, where you can’t really distinguish between structural and procedural because they’re basically the same thing. Also Rust macros look different from built-in language constructs, all being like `foo!(…)`, `foo![…]` or `foo! { … }`.
I can’t comment about any other languages; they may have things much closer to Lisp macros.
(I write this as a Rust expert who writes structural macros regularly but procedural macros only once every year or two at least partly because of how painful they are to write, and a Lisp outsider who’s familiar with all the concepts and written a little here and there over the years but never anything serious.)
Lisp macros you define just like any Lisp function, and allow you to create new syntax constructs indistinguishable from any built-in constructs, which can execute whatever code they like as part of the process.
In Lisp, macros are evaluated at run-time and can do anything, including access program state (if you play your cards right). They consume something that’s very roughly an AST, and emit something that’s very roughly an AST, and the language makes doing that quite easy, largely because it’s all structural in nature.
In Rust, you’ve got macro_rules! which provides convenient syntax for simple structural macros, and then after that you have procedural macros which have the full power, but have to be written in a completely different place and get evaluated at compile-time only (so no dynamic macros), in a completely different context to the code that calls them (so no program state). They’re a lot harder to work with, consuming a stream of token trees (e.g. `if`, `3`, `.`, `{ … }`, `(…)`) and emitting a stream of token trees, a representation that’s clumsy and prone to error (especially since it’s not structural) though this can be mitigated a lot with crates like syn and quote which can make the process at least somewhat more structural, but it’s still way more clumsy than Lisp, where you can’t really distinguish between structural and procedural because they’re basically the same thing. Also Rust macros look different from built-in language constructs, all being like `foo!(…)`, `foo![…]` or `foo! { … }`.
I can’t comment about any other languages; they may have things much closer to Lisp macros.
(I write this as a Rust expert who writes structural macros regularly but procedural macros only once every year or two at least partly because of how painful they are to write, and a Lisp outsider who’s familiar with all the concepts and written a little here and there over the years but never anything serious.)
I think there is similarity. Lisp can take its own AST, and modify it with its own fully-capable code. In this sense Rust's proc-macros can too. The difference is that Lisp has bare-bones syntax, so the AST manipulation doesn't get tedious. But Rust's proc macros using the quote crate look kinda Lisp-y.
And just like LOOP in Common Lisp, you can totally make Rust macros that are a new language inside a language, and are too clever for their own good ;)
And just like LOOP in Common Lisp, you can totally make Rust macros that are a new language inside a language, and are too clever for their own good ;)
The problem I had is I learned a bit of LISP - just the basics and then thought “hey this is super powerful -
I bet it can elegantly solve some great problems” but then I was stuck! I had no idea what sorts of problems or how to go about it. I guess I’d need to see some motivating examples. The tutorial had a very cool test framework in like 5 or 6 lines of macros so I got a feel for the power but I’d need to see more.
My fear with lisp is that if you use macros it can become obscure what is really going on. Even in C# when I’ve seen metaprogramming done it can kill the discoverability of an app, meaning you have to talk to people who have talked to the person who left the company who knows the mental model. Searching code for keywords no longer helps, or you read the entire codebase to figure out how it works. It was a relief to get off that and work with more familiar CRUD like code. If someone writes a macro, they should write a manual!
My fear with lisp is that if you use macros it can become obscure what is really going on. Even in C# when I’ve seen metaprogramming done it can kill the discoverability of an app, meaning you have to talk to people who have talked to the person who left the company who knows the mental model. Searching code for keywords no longer helps, or you read the entire codebase to figure out how it works. It was a relief to get off that and work with more familiar CRUD like code. If someone writes a macro, they should write a manual!
I think this is a very valid viewpoint. Typically its better not to learn / use macros until one is sufficiently advanced, functions will do for 99.5% of the circumstances, to call a famous author ;-)
You should try it out. The book Common Lisp Recipes by Edi Weitz is really good and practical - you can get web servers up and running in minutes, and has many other practical uses (I have to check the contents again, but its about 750 pages long and covers stuff like interfacing with C and Java), highly recommended if you want to get productive in Lisp!
You should try it out. The book Common Lisp Recipes by Edi Weitz is really good and practical - you can get web servers up and running in minutes, and has many other practical uses (I have to check the contents again, but its about 750 pages long and covers stuff like interfacing with C and Java), highly recommended if you want to get productive in Lisp!
i had the following thought the other day, interesting if it has any validity:
The availability of programmers who are proficient in a programming language is the single most important factor in programming language adoption. I think the continued popularity of C++ and Java has much to do with the fact; an enterprise wants to treat programmers as interchangeable screws, and a less widespread programming language would make this practice much more difficult. C++ was designed to be easier to learn by means of backward compatibility with C; This decision was good for programming language adoption; it was a good trade off, even at the expense of being a source of many issues with the language.
Interesting implication: I think that an enterprise with a less common programming language (like Scala or Rust), would have to treat its programmers much better than a competing shop that is using a commonly used platform like Java or C++; they have a greater investment in their workforce, due to the language/platform issue, are probably more likely to raise salaries every now and then and would be less likely to 'hire and fire'...
So adopting a less common programming language might have some non trivial implications on the culture and governance of an enterprise.
On the other hand there would be a lot of pressure to switch back to a more common programming language, in the event that the shop needs to grow significantly, these shops would then be inclined to port their systems back to a more common language...
The availability of programmers who are proficient in a programming language is the single most important factor in programming language adoption. I think the continued popularity of C++ and Java has much to do with the fact; an enterprise wants to treat programmers as interchangeable screws, and a less widespread programming language would make this practice much more difficult. C++ was designed to be easier to learn by means of backward compatibility with C; This decision was good for programming language adoption; it was a good trade off, even at the expense of being a source of many issues with the language.
Interesting implication: I think that an enterprise with a less common programming language (like Scala or Rust), would have to treat its programmers much better than a competing shop that is using a commonly used platform like Java or C++; they have a greater investment in their workforce, due to the language/platform issue, are probably more likely to raise salaries every now and then and would be less likely to 'hire and fire'...
So adopting a less common programming language might have some non trivial implications on the culture and governance of an enterprise.
On the other hand there would be a lot of pressure to switch back to a more common programming language, in the event that the shop needs to grow significantly, these shops would then be inclined to port their systems back to a more common language...
Fairly closely related: http://www.paulgraham.com/pypar.html
related, though observed from different perspectives. But yes, they adopt 'weird languages' for hope of 'hiring the best', but that does that mean? The best according to what measure? I mean few people are 'the best' according to each criteria, there are so many of these criteria.
It's fascinating how my (our?) opinion on Google has changed since 2004.
Ah, this reminds me of the days I spent writing RPL programs for solving electric circuits on my trusty old HP48 calculator. (It is said but nowhere officially confirmed that RPL stands for "reverse-polish lisp".) It was quite enjoyable _then_ and for _that_ purpose (programs designed to run in a specific UI environment) but today I wouldn't even consider starting a "serious" project in a postfix language. EDIT: https://factorcode.org/ is a modern postfix language.
Using weird languages DOES have one merit though: it opens your horizons. It teaches you to see a "conventional" programming language as a collection of mechanisms at your disposal instead of something "intended to be used to do X".
More to the point, I think that there are two types of languages: 1) those that encourage top-down design (that's how I learned programming with Pascal) and 2) those that encourage bottom-up design (such as RPL, these have often an interactive REPL.)
So actively using something like RPL or ML or Scheme (yeah, I've read ca 2/3 rds of SICP) allows you to turn C# "inside out", to apply bottom-up programming techniques. You don't create a class because "some OO principles tell you to do so" or because it came as godsend from some "architect", but because you understand workings of classes and a class is the right tool for the task at hand.
Also, there's no programming in the large without some mechanisms to control accessibility.
Using weird languages DOES have one merit though: it opens your horizons. It teaches you to see a "conventional" programming language as a collection of mechanisms at your disposal instead of something "intended to be used to do X".
More to the point, I think that there are two types of languages: 1) those that encourage top-down design (that's how I learned programming with Pascal) and 2) those that encourage bottom-up design (such as RPL, these have often an interactive REPL.)
So actively using something like RPL or ML or Scheme (yeah, I've read ca 2/3 rds of SICP) allows you to turn C# "inside out", to apply bottom-up programming techniques. You don't create a class because "some OO principles tell you to do so" or because it came as godsend from some "architect", but because you understand workings of classes and a class is the right tool for the task at hand.
Also, there's no programming in the large without some mechanisms to control accessibility.
> Nor is this all you can do with macros; it's just one region in a space of program-manipulating techniques that even now is far from fully explored.
I like macros. I find myself, not infrequently, thinking about where they would be convenient despite using a language without them.
Nevertheless none of the languages that include them (that I’m aware of) seem very appealing.
Part of this is “program-manipulating techniques”. Less powerful languages are easier for programs to reason statically about, and so usually have great editor refactoring / navigation / static analysis already available. This makes the 99.5% of programming that is mundane more pleasant, and it’s hard to imagine special programs that don’t involve at least a good chunk of this.
The alternative to macros is not never doing metaprogramming, you can do code generation, parse and process the AST, or have program behavior be data-directed at runtime up to including an embedded interpreter. These things are surely less convenient than macros, but it’s a trade off against making all the other parts of the program less convenient to write.
Another issue is most languages with macros are Lisp/Scheme types, and having linked-lists-of-boxed-objects be the default representation for everything often isn’t great for domains that are performance-sensitive (this probably wouldn’t apply to some languages like Nim).
Of course there are the other downsides of using uncommon languages, like often less mature runtimes / library ecosystems.
It seems technically feasible for a language with macros to address all these issues (and maybe Rust does if you’re willing to give up GC). If I was writing a new language I would probably start by compiling to either the JVM/.NET/Go to get a runtime and libraries, and focus on the problem of incremental language extension while maintaining good editor and static analysis support (I think there are some promising approaches for that but this comment is already pretty long).
I like macros. I find myself, not infrequently, thinking about where they would be convenient despite using a language without them.
Nevertheless none of the languages that include them (that I’m aware of) seem very appealing.
Part of this is “program-manipulating techniques”. Less powerful languages are easier for programs to reason statically about, and so usually have great editor refactoring / navigation / static analysis already available. This makes the 99.5% of programming that is mundane more pleasant, and it’s hard to imagine special programs that don’t involve at least a good chunk of this.
The alternative to macros is not never doing metaprogramming, you can do code generation, parse and process the AST, or have program behavior be data-directed at runtime up to including an embedded interpreter. These things are surely less convenient than macros, but it’s a trade off against making all the other parts of the program less convenient to write.
Another issue is most languages with macros are Lisp/Scheme types, and having linked-lists-of-boxed-objects be the default representation for everything often isn’t great for domains that are performance-sensitive (this probably wouldn’t apply to some languages like Nim).
Of course there are the other downsides of using uncommon languages, like often less mature runtimes / library ecosystems.
It seems technically feasible for a language with macros to address all these issues (and maybe Rust does if you’re willing to give up GC). If I was writing a new language I would probably start by compiling to either the JVM/.NET/Go to get a runtime and libraries, and focus on the problem of incremental language extension while maintaining good editor and static analysis support (I think there are some promising approaches for that but this comment is already pretty long).
> Another issue is most languages with macros are Lisp/Scheme types,
Rust, Julia and Zig (if you consider comptime to be a specific type of macros) don't look Lispy to me but all have macros. In Rust I would consider them essential to the language (don't know the others well enough to say), without them Rust would be terribly verbose.
> having linked-lists-of-boxed-objects be the default representation for everything often isn’t great for domains that are performance-sensitive
Disagree, there are extremely performant Lisps out there, including Common Lisp and Chez Scheme. They run as fast as, or faster than, any language that's not a systems-language (C, C++, Rust, Zig).
Rust, Julia and Zig (if you consider comptime to be a specific type of macros) don't look Lispy to me but all have macros. In Rust I would consider them essential to the language (don't know the others well enough to say), without them Rust would be terribly verbose.
> having linked-lists-of-boxed-objects be the default representation for everything often isn’t great for domains that are performance-sensitive
Disagree, there are extremely performant Lisps out there, including Common Lisp and Chez Scheme. They run as fast as, or faster than, any language that's not a systems-language (C, C++, Rust, Zig).
Julia is a Dylan is a Lisp.
> there are extremely performant Lisps out there
Yes, that’s because CommonLisp also provides native high performance data structures like vectors, arrays and hash tables that complement basic linked lists. Furthermore, most Lisp compilers are pretty mature and create well-optimized x86 code. You can annotate your code with type hints to help and guide the compiler in hot spots of your program.
Yes, that’s because CommonLisp also provides native high performance data structures like vectors, arrays and hash tables that complement basic linked lists. Furthermore, most Lisp compilers are pretty mature and create well-optimized x86 code. You can annotate your code with type hints to help and guide the compiler in hot spots of your program.
> Rust, Julia and Zig […] don’t look Lispy to me
Sure, I even mentioned both Nim and Rust (Zig’s comptime is interesting but I wouldn’t put it on the same level). It just seems like most language implementations with macros are Lisp variants (although which ones count as different languages is somewhat fuzzy).
> there are extremely performant Lisps out there, including Common Lisp and Chez Scheme
If you look at for example the benchmarks game [1], Lisp puts in an extremely impressive showing relative to Python/Ruby but often lags slightly Java/C#/Go. But more importantly, the Lisp code is often very non-idiomatic [2], with lots of special annotations and even turning safety features off. Maybe it’s acceptable for optimizing very narrow hot spots, but I wouldn’t want to write a lot of code in this style and wouldn’t expect most third party libraries to be written that way.
I don’t think any of this is the fault of Lisp implementers, but more that the basically default (although not only) data type provides the semantics of dynamically typed linked lists, which are inherently (relatively) slow and tricky to optimize. And even if very clever optimizations exist, relying on them to get adequate performance is less than ideal, since it’s often not obvious where you fall off the fast path. Of course many applications aren’t performance sensitive enough for these sorts of things to matter much, I’m thinking about 3D games etc here where you usually want control of memory layout.
[1] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
[2] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
Sure, I even mentioned both Nim and Rust (Zig’s comptime is interesting but I wouldn’t put it on the same level). It just seems like most language implementations with macros are Lisp variants (although which ones count as different languages is somewhat fuzzy).
> there are extremely performant Lisps out there, including Common Lisp and Chez Scheme
If you look at for example the benchmarks game [1], Lisp puts in an extremely impressive showing relative to Python/Ruby but often lags slightly Java/C#/Go. But more importantly, the Lisp code is often very non-idiomatic [2], with lots of special annotations and even turning safety features off. Maybe it’s acceptable for optimizing very narrow hot spots, but I wouldn’t want to write a lot of code in this style and wouldn’t expect most third party libraries to be written that way.
I don’t think any of this is the fault of Lisp implementers, but more that the basically default (although not only) data type provides the semantics of dynamically typed linked lists, which are inherently (relatively) slow and tricky to optimize. And even if very clever optimizations exist, relying on them to get adequate performance is less than ideal, since it’s often not obvious where you fall off the fast path. Of course many applications aren’t performance sensitive enough for these sorts of things to matter much, I’m thinking about 3D games etc here where you usually want control of memory layout.
[1] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
[2] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
Maybe you'd be interested in looking at the way Jonathan Blow implemented macros in his programming language.
The video is quite long (and has a Q&A accompanying followup), but I think just the example of creating custom iterators with macros is really interesting.
https://www.youtube.com/watch?v=QX46eLqq1ps
The video is quite long (and has a Q&A accompanying followup), but I think just the example of creating custom iterators with macros is really interesting.
https://www.youtube.com/watch?v=QX46eLqq1ps
Jai seems pretty interesting, I’m looking forward to trying it out once a public beta is available! Not the least because there’ll hopefully be a fair amount of batteries already included for 3D graphics / math stuff.
In general I really like the approach of designing a language in conjunction with implementing a large project (other than the language itself).
In general I really like the approach of designing a language in conjunction with implementing a large project (other than the language itself).
Sort of like how the Hy language (hylang) compiles a Lisp dialect into a Python AST?
Yes, like that! Or like Clojure. If I was targeting the JVM or CLR I’d probably use bytecode, or for Go I’d just generate ordinary source code to feed into the compiler.
It sounds a little ungainly but parsing shouldn’t be a big percent of compile times, so the overhead shouldn’t be that big. And it addresses two of the biggest issues, libraries and (current and future) platform support, things that new language adopters should legitimately be concerned about.
A lot of the most popular mobile games actually now use a similar technology. The game engine Unity converts the bytecode for game C# scripts to C++ which it can feed into the system toolchain. Even as a billion dollar company they decided it was more practical to piggyback on another language for platform support (in their case game consoles, which come with their own C++ compiler but may not be supported out of the box by other language toolchains).
It sounds a little ungainly but parsing shouldn’t be a big percent of compile times, so the overhead shouldn’t be that big. And it addresses two of the biggest issues, libraries and (current and future) platform support, things that new language adopters should legitimately be concerned about.
A lot of the most popular mobile games actually now use a similar technology. The game engine Unity converts the bytecode for game C# scripts to C++ which it can feed into the system toolchain. Even as a billion dollar company they decided it was more practical to piggyback on another language for platform support (in their case game consoles, which come with their own C++ compiler but may not be supported out of the box by other language toolchains).
> 99.5% of programming consists of gluing together calls to library functions. All popular languages are equally good at this.
This seems to be true in the same way that "99.5% of cooking consists of making food hot. All popular kitchen appliances are equally good at this." is "true".
Technically you can fry bacon in a pressure cooker, but you shouldn't because we have frying pans.
This seems to be true in the same way that "99.5% of cooking consists of making food hot. All popular kitchen appliances are equally good at this." is "true".
Technically you can fry bacon in a pressure cooker, but you shouldn't because we have frying pans.
> 99.5% of programming consists of gluing together calls to library functions. All popular languages are equally good at this.
I'm not sure this is so true. I've glued stuff together in a bunch of languages, and some are easier than others. Particularly in how the package manager works. I'd say c++ throws the weirdest integration issues out of the ones I've used. Rust seems pleasant, nothing too odd thus far for me. Python, super easy so long as you got Anaconda for all the math stuff. JS/npm maybe too easy. Swift/Cocoapods smooth sailing.
But also the languages themselves can make it easier or harder to glue stuff together. If you need to play with pointers and allocators, there's more work to do.
> Weird languages aren't weird by accident. Not the good ones, at least.
No true Scotsman? I'm sure once a language gets more than the initial attention, it can end up a strange mess, just like anything that has a bunch of people tugging at it.
> So if you want to expand your concept of what programming can be, one way to do it is by learning weird languages. Pick a language that most programmers consider weird but whose median user is smart, and then focus on the differences between this language and the intersection of popular languages.
I think this is selection at work. Yes, I do consider some coders better than others. But often it's because the kind of person who is good at coding is often the kind who gets to the bottom of things, and part of that is cave diving in weird languages. Probably I rate people higher as coders just from telling me they know Haskell or Lisp, which I perhaps shouldn't (?). But it does appear to me like some of the sharper coders I've met have for some reason been down the Haskell cave, perhaps investigating something to do with the type system.
I'm not sure this is so true. I've glued stuff together in a bunch of languages, and some are easier than others. Particularly in how the package manager works. I'd say c++ throws the weirdest integration issues out of the ones I've used. Rust seems pleasant, nothing too odd thus far for me. Python, super easy so long as you got Anaconda for all the math stuff. JS/npm maybe too easy. Swift/Cocoapods smooth sailing.
But also the languages themselves can make it easier or harder to glue stuff together. If you need to play with pointers and allocators, there's more work to do.
> Weird languages aren't weird by accident. Not the good ones, at least.
No true Scotsman? I'm sure once a language gets more than the initial attention, it can end up a strange mess, just like anything that has a bunch of people tugging at it.
> So if you want to expand your concept of what programming can be, one way to do it is by learning weird languages. Pick a language that most programmers consider weird but whose median user is smart, and then focus on the differences between this language and the intersection of popular languages.
I think this is selection at work. Yes, I do consider some coders better than others. But often it's because the kind of person who is good at coding is often the kind who gets to the bottom of things, and part of that is cave diving in weird languages. Probably I rate people higher as coders just from telling me they know Haskell or Lisp, which I perhaps shouldn't (?). But it does appear to me like some of the sharper coders I've met have for some reason been down the Haskell cave, perhaps investigating something to do with the type system.
“Pick a language that most programmers consider weird but whose median user is smart, and then focus on the differences between this language and the intersection of popular languages.”
Any suggestions on which languages could fit this criteria?
Any suggestions on which languages could fit this criteria?
Zig is one that’s been on my list for Paul's stated reason.
Is Zig weird though? I find it eminently pragmatic and a lot of the interest in it comes from people migrating from popular languages like C and C++ (not that C++ isn't itself pretty weird).
From what I’ve seen, Zig has no built-in polymorphism features (no vtables/interfaces/traits), which is _pretty_ weird for a modern language in a good way.
That is just because it is new. If it survives it will end up with everything.
“Adding everything” is definitely not a part of Zig’s philosophy.
https://github.com/ziglang/zig/issues/130#issuecomment-70601...
> However, at this point the plan is to not add an additional dynamic dispatch language feature.
https://github.com/ziglang/zig/issues/130#issuecomment-70601...
> However, at this point the plan is to not add an additional dynamic dispatch language feature.
Key phrase: "at this point".
Isn't that forecasting a trend with too few data points? The field is still young and changing.
> too few data points?
There have been rather a lot of languages. The field is approaching 70 years old, and still changing, but clear evolutionary processes are seen repeated in hundreds of languages living and dead. The ones that don't grow are the most reliably dead.
There have been rather a lot of languages. The field is approaching 70 years old, and still changing, but clear evolutionary processes are seen repeated in hundreds of languages living and dead. The ones that don't grow are the most reliably dead.
Oh, I don’t think it is a trend. I rather see it as a curious phenomenon that makes one reflect on the trade offs we usually make when using polymorphism, and whether it’s worth all the time, not only in terms of performance, but also in terms of program architecture.
Interesting. What are the program architecture tradeoffs you are suggesting?
To be honest, I have zero experience programming with Zig. But I imagine programming with Zig would lead to more literal style and fewer, simpler abstractions (no IoC, no frameworks). That might be beneficial for certain kinds of focused-scope projects.
I see. They say you can solve every problem with an other indirection, and ad hoc polymorphism is an instance of that. But there are other ways to enable composition that are seldom reached for when your language makes that easy
Every problem, except those caused by too many indirections.
Each solution uses only a few language features. Different problems call for different subsets. Not using a feature on your favorite sort of problem says nothing about its value. "Ways to enable composition" poorly supported are reached for less. Poorly supporting one of them that has proven frequently useful does not improve a language.
Each solution uses only a few language features. Different problems call for different subsets. Not using a feature on your favorite sort of problem says nothing about its value. "Ways to enable composition" poorly supported are reached for less. Poorly supporting one of them that has proven frequently useful does not improve a language.
It has compile time programming designed to subsume those features. So eg a generic struct becomes instead a compile time function that takes a type and returns a struct
That is a wholly other set of language features, for a different purpose, and is thus no substitute.
Practical languages accumulate features to better address a multitude of common real-world problems. Toy languages don't. Sometimes a toy language is adopted and grown to practicality. People always complain about that.
Practical languages accumulate features to better address a multitude of common real-world problems. Toy languages don't. Sometimes a toy language is adopted and grown to practicality. People always complain about that.
Zig uses explicit allocations everywhere (if you want to allocate something you need a reference to an allocator) which is pretty unique even for low-level languages (e.g. C, Rust)
Zig is certainly not weird in the way that something like prolog or scheme are.
[deleted]
Besides Lisp, languages like Haskell and F# would probably fit. As would Forth and modern stack languages like Factor.
The APL/J/BQN family of array languages, or Prolog & other Horn clause languages. Both will change your idea of what’s expressible in a programming language.
I'm not a programmer/developer by trade but I do like writing scripts to make my job easier.
I'm looking into APL and Lisp type languages basically to expand my mind as up to now I've really only being using "traditional" type languages.
It's like starting from scratch again.
I'm looking into APL and Lisp type languages basically to expand my mind as up to now I've really only being using "traditional" type languages.
It's like starting from scratch again.
That's true for everybody, I think.
I find "thinking in lisp, then writing the program out in X" where X is whatever 'mundane' language seems most suitable to the task is often a very effective technique.
Array languages I've tried to learn repeatedly over the years and always ended up bouncing off, so have no opinion there except "personal aha moment not yet reached".
I find "thinking in lisp, then writing the program out in X" where X is whatever 'mundane' language seems most suitable to the task is often a very effective technique.
Array languages I've tried to learn repeatedly over the years and always ended up bouncing off, so have no opinion there except "personal aha moment not yet reached".
Ruby, Io, Prolog, Scala, Erlang, Clojure, Haskell which are covered in "Seven Languages in Seven Weeks" are quite nice for start.
Can also recommend the followup "Seven More Languages in Seven Weeks" [1] which covers: Lua, Factor, Elixir, Elm, Julia, MiniKanren, and Idris
[1] https://pragprog.com/titles/7lang/seven-more-languages-in-se...
[1] https://pragprog.com/titles/7lang/seven-more-languages-in-se...
> "Ruby, Io, Prolog, Scala, Erlang, Clojure, Haskell"
Do they offer any meaningful differences to an otherwise "mainstream" language - anything beyond syntax, tooling ecosystem and the usual functional vs. procedural vs. OOP paradigms?
Anything I can't just whip up in modern C#, C++, Java or Python if I wanted to constrain myself to a specific subset of features or a specific paradigm?
I get the "it's fun to try something new every once in a while" part but people tend to forget that the distinctions between programming languages have blurred significantly over the last 10+ years.
Do they offer any meaningful differences to an otherwise "mainstream" language - anything beyond syntax, tooling ecosystem and the usual functional vs. procedural vs. OOP paradigms?
Anything I can't just whip up in modern C#, C++, Java or Python if I wanted to constrain myself to a specific subset of features or a specific paradigm?
I get the "it's fun to try something new every once in a while" part but people tend to forget that the distinctions between programming languages have blurred significantly over the last 10+ years.
Haskell's laziness gets you all sorts of control flow that is awkward in or missing from most languages. So I think it's worth checking out.
Well, Prolog for one seems very different. In functional/procedural/OOP you have to write a program describing every step of the way. In Prolog you just have to describe the destination.
Yes, there are plenty of meaningful differences. It's true most mainstream languages in industry are essentially syntax swaps of each other, but Prolog and Haskell are not that at all.
In the case of Erlang the answer to your question about meaningful differences is: oh yes! I could list more, but there are two:
- support for concurrency. After tasting it you never will want to go back to techniques normally used in the languages you listed
- data immutability, which makes reading code so much easier.
- support for concurrency. After tasting it you never will want to go back to techniques normally used in the languages you listed
- data immutability, which makes reading code so much easier.
Imagine if you could run a Python function backwards and feed something into the return value and have Python tell you the parameters to match. That's the uncomon, twisty difference of Prolog relations. In Python a test whether this combination of length and area makes a valid square:
It isn't /only/ a built in brute-force search, or a "do everything with recursion" computer science lesson timewaster.
[1] https://www.youtube.com/watch?v=5KUdEZTu06o
def test_square(side_length, area):
return (side_length ** 2) == area
which says imperatively "square the side length and compare it to the area, return the result" becomes a Prolog relation: :-use_module(library(clpfd)).
square_side_area(X, A) :-
X #> 0,
X*X #= A.
which says declaratively "square_side_area holds for X and A if X is positive and X squared equals A". This can be used in the same way as the Python code to ask "does length 5 and area 25 make a valid square, yes/no?" but it can also be queried to find: "given length X 5, can this relation hold?" and it answers yes, if A=25. Or "given area 25, can this hold?" and it answers "yes, when X is 5". Or "are there any solutions?": ?- square_side_area(5,25).
true.
?- square_side_area(5,AREA).
AREA = 25.
?- square_side_area(SIDE,25).
SIDE = 5.
?- square_side_area(SIDE, AREA).
SIDE in 1..sup,
SIDE^2#=AREA,
AREA in 1..sup.
Then, unlike the Python, you can combine this with extra conditions outside e.g. "(that), and AREA is between 1 and 25" and have it show all the possible answers in that range: ?- square_side_area(SIDE, AREA), AREA in 1..25, label([SIDE,AREA]).
SIDE = AREA, AREA = 1 ;
SIDE = 2,
AREA = 4 ;
SIDE = 3,
AREA = 9 ;
SIDE = 4,
AREA = 16 ;
SIDE = 5,
AREA = 25.
If you can spare 30 minutes for a video, this Sudoku Solver in Prolog[1] shows quite well this style of thinking and its consequences. As you watch it, wonder what you might write in C# to solve sudoku (and how much code), and notice here what there is in the way of variables, loops, recursion, indexing, control flow, etc. This kind of thing "I give the constraints to a combinatorial problem, through constraint propagation find some valid solutions" is one of Prolog's strengths.It isn't /only/ a built in brute-force search, or a "do everything with recursion" computer science lesson timewaster.
[1] https://www.youtube.com/watch?v=5KUdEZTu06o
TLA+, AWK, jq are also interesting choices.
For 'pg it's just an excuse to talk about Lisp.
The max I’ve seen in both categories is Brainfuck: https://en.wikipedia.org/wiki/Brainfuck
Check ACPUL 1.0 pure programming language for mobiles. ACPUL have 99.5% common features.
No keywords, only 2 statements (if/while), no strings in code but bulitin i18n. Here is EBNF grammar https://github.com/d08ble/acpu/blob/master/acpul-EBNF-cocor/...
Here is demo project https://github.com/web3cryptowallet/Web3CryptoWallet
But powerful like LISP and I am building mobile OS, IDE and nocode environment with ACPUL https://twitter.com/acpustudio
No keywords, only 2 statements (if/while), no strings in code but bulitin i18n. Here is EBNF grammar https://github.com/d08ble/acpu/blob/master/acpul-EBNF-cocor/...
Here is demo project https://github.com/web3cryptowallet/Web3CryptoWallet
But powerful like LISP and I am building mobile OS, IDE and nocode environment with ACPUL https://twitter.com/acpustudio
I'd add Smalltalk to the other odd list suggestions given.
Assembly language for ARM or RISC-V. It will provide a better appreciation for what's going on under the hood.
You'll also see which high level languages fit (or don't fit) this underlying fundamental model which may help cut through the marketing fluff from their various proponents and provide an unpleasant appreciation of the performance costs of popular programming paradigms.
You'll also see which high level languages fit (or don't fit) this underlying fundamental model which may help cut through the marketing fluff from their various proponents and provide an unpleasant appreciation of the performance costs of popular programming paradigms.
Metamine - it seems to have been pulled from the internet by its creator, after having given some really cool demos.
What's weird: it allows a mix of declarative and imperative syntax in a style that seems like normal procedural programming. You have a "magical equals" that is actually reactive programming... if any of the terms change, ever, the result gets updated.
Here's a previous thread about it
https://news.ycombinator.com/item?id=27555940
What's weird: it allows a mix of declarative and imperative syntax in a style that seems like normal procedural programming. You have a "magical equals" that is actually reactive programming... if any of the terms change, ever, the result gets updated.
Here's a previous thread about it
https://news.ycombinator.com/item?id=27555940
I disagree with this at a very fundamental level. I'm not sure how to express my disagreement.
I'll pick a seemingly random point:
> Pick a language that most programmers consider weird but whose median user is smart, and then focus on the differences between this language and the intersection of popular languages.
This heuristic used to apply to Python, but it no longer does. (Partly thanks to the the "Python Paradox" essay I suppose; most people now think learning Python will give you a nice career path).
All this heuristic says is that this language has some novelty that attracts people who are interested in novelty. People who are interested in novelty in the field of computers tend to be smart people, but they are not reprsentative of the "population of smart people working with computers"; they are just a small slice of it.
I might even go so far as to say, it's a slice of people who are just interested in things but not particularly interested in making finished products.
Most of the people who work with or on various linux distributions also fall in this category: they are smart, but they are not interested in building a solid working desktop environment as much as they are interested in just playing around with things for fun.
For them, their subject of interest is like a puzzle game that they spend their time exploring. There's no specific end goal. No specific product to be built. Nothin to be delivered to end users.
That's also the appeal of weird languages: the novelty itself.
This might be a matter of definitions, but to me a good language is one that allows you to deliver a solid reliable end product.
Maybe something you write in 5 lines of lisp will take 30 lines in Go. But this is not an issue at all.
The mental energy it takes to write the 30 lines of Go is probably lower than the mental energy is takes to write those 5 lines of lisp.
I'll pick a seemingly random point:
> Pick a language that most programmers consider weird but whose median user is smart, and then focus on the differences between this language and the intersection of popular languages.
This heuristic used to apply to Python, but it no longer does. (Partly thanks to the the "Python Paradox" essay I suppose; most people now think learning Python will give you a nice career path).
All this heuristic says is that this language has some novelty that attracts people who are interested in novelty. People who are interested in novelty in the field of computers tend to be smart people, but they are not reprsentative of the "population of smart people working with computers"; they are just a small slice of it.
I might even go so far as to say, it's a slice of people who are just interested in things but not particularly interested in making finished products.
Most of the people who work with or on various linux distributions also fall in this category: they are smart, but they are not interested in building a solid working desktop environment as much as they are interested in just playing around with things for fun.
For them, their subject of interest is like a puzzle game that they spend their time exploring. There's no specific end goal. No specific product to be built. Nothin to be delivered to end users.
That's also the appeal of weird languages: the novelty itself.
This might be a matter of definitions, but to me a good language is one that allows you to deliver a solid reliable end product.
Maybe something you write in 5 lines of lisp will take 30 lines in Go. But this is not an issue at all.
The mental energy it takes to write the 30 lines of Go is probably lower than the mental energy is takes to write those 5 lines of lisp.
>> The mental energy it takes to write the 30 lines of Go is probably lower than the mental energy is takes to write those 5 lines of lisp.
I would use more mental energy to write 30 lines of Go, than 5 in lisp. Also if you take into account that you have a true REPL and you can do REPL driven development, which spares you some extra mental energy.
But to be fair, Paul is talking about macros, which Go doesn't even have.Macros are more complicated, but are often oversold and over hyped. Yes, they are great, you can extend the language and all, but macros are not that often used, you can probably pick a random lisp codebase and search for macros, I bet you won't find any or less than 2% of the entire codebase. If macros in lisp didn't exist I would still use it, because I love building expressions vs building statemets.
I would use more mental energy to write 30 lines of Go, than 5 in lisp. Also if you take into account that you have a true REPL and you can do REPL driven development, which spares you some extra mental energy.
But to be fair, Paul is talking about macros, which Go doesn't even have.Macros are more complicated, but are often oversold and over hyped. Yes, they are great, you can extend the language and all, but macros are not that often used, you can probably pick a random lisp codebase and search for macros, I bet you won't find any or less than 2% of the entire codebase. If macros in lisp didn't exist I would still use it, because I love building expressions vs building statemets.
Go doesn't have macros but it culturally encourages code generation. I myself generate hundreds of lines of code that would otherwise be annoying and error-prone to maintain manually.
This may be the first time I've ever seen code generation listed as a feature. Code generation may be the single biggest contributor to long-term maintainability problems I've ever seen, from `rails new` to create-react-app, over time it'll kill your momentum.
> I bet you won't find any or less than 2% of the entire codebase
One can look from another angle into some code bases:
https://github.com/McCLIM/McCLIM/blob/master/Examples/stopwa...
It uses a ton of complex macros:
Built in macros: DEFPACKAGE, DEFMETHOD, MULTIPLE-VALUE-BIND, LOOP, ...
Language extensions: WHEN-LET, ...
Library macros: WITH-OUTPUT-AS-PRESENTATION, FORMATTING-TABLE, DEFINE-APPLICATION-FRAME, ...
Even a generated macro: DEFINE-STOPWATCH-COMMAND (which was defined by DEFINE-APPLICATION-FRAME)
One can look from another angle into some code bases:
https://github.com/McCLIM/McCLIM/blob/master/Examples/stopwa...
It uses a ton of complex macros:
Built in macros: DEFPACKAGE, DEFMETHOD, MULTIPLE-VALUE-BIND, LOOP, ...
Language extensions: WHEN-LET, ...
Library macros: WITH-OUTPUT-AS-PRESENTATION, FORMATTING-TABLE, DEFINE-APPLICATION-FRAME, ...
Even a generated macro: DEFINE-STOPWATCH-COMMAND (which was defined by DEFINE-APPLICATION-FRAME)
There is only one custom macro definition in this code, 10 lines of code without docstring. Builtin macros are not an issue, why would that be an issue ? Those are just part of the language standard library. It's the same as when you use reserved words in other languages, like *import* statement in golang or *ns* macro in Clojure, it's just part of the language and you learn how to use it. I was talking about custom macros.
Disclamer: My goto lisps are Clojure and Janet, so I am not very familiar with CL.
That is the number one reason why I have tried languages like Lisp, Haskell or Smalltalk. Even Prolog.
You change your mindset in different ways in each of them. When you come back to your usual tool you expanded your thinking to what you could not conceive previously.
You change your mindset in different ways in each of them. When you come back to your usual tool you expanded your thinking to what you could not conceive previously.
Is there an "academic" subculture of, say, wood- or metalworking that derides craftspeople and engineers as "just glueing stuff together" or is this unique to programming?
Only on this site will they take the word of PG as gospel
rapping (sampling), DJing
I’ve run into this attitude among artists, musicians, and woodworkers, so I don’t think it’s particularly unique.
Scala is a good example of a weird programming language with smart users. The book Hands on Scala Programming is a great way to learn how to express code and think in new ways.
Paul Graham also talks about the power of different programming languages in Beating the Averages, see The Blub Paradox: http://www.paulgraham.com/avg.html
Powerful / weird languages usually aren't the productivity hack you'd hope. A few team members might be more productive with a weird language, but other folks will have trouble understanding their code, so they'll be less productive.
Weird programming languages also require different types of library support (programmers that are passionate about immutability can't use a JSON library that mutates stuff). So they'll build a separate JSON library, but that fractures communities.
It's great to learn about different languages, but programmers seem susceptible to the allure of extra productivity from weird languages and that's not what I've seen.
Paul Graham also talks about the power of different programming languages in Beating the Averages, see The Blub Paradox: http://www.paulgraham.com/avg.html
Powerful / weird languages usually aren't the productivity hack you'd hope. A few team members might be more productive with a weird language, but other folks will have trouble understanding their code, so they'll be less productive.
Weird programming languages also require different types of library support (programmers that are passionate about immutability can't use a JSON library that mutates stuff). So they'll build a separate JSON library, but that fractures communities.
It's great to learn about different languages, but programmers seem susceptible to the allure of extra productivity from weird languages and that's not what I've seen.
> but other folks will have trouble understanding their code, so they'll be less productive.
This assumes, you know, that other folks are incapable of learning anything new.
This assumes, you know, that other folks are incapable of learning anything new.
...and, then, there are the languages that we need to use, in order to accomplish our tasks.
Most engineers (as opposed to coders) are fairly results-oriented. We may have our differences about how to get the results, or even, what the desired results are; but we always have a deliverable in sight.
It's all about getting satisfactorily-functioning software into the hands of end-users. Put a bow on it. Stick a fork in it. It's done.
Speaking for myself, I write native Apple code (iOS/iPadOS, MacOS, WatchOS, and TVOS). I need to use Swift. I could use ObjC, but Swift is really where it's at, unless I'm doing really low-level stuff. Others may use JavaScript, or even C#, to write Apple software; using hybrid systems.
It is, indeed, mostly "gluing together calls to library functions," but there's a bit of algorithm, mixed in there, as well (not much. Many library functions provide better algorithm support than hand-rolled).
Other platforms have their most effective languages.
I probably could write Apple apps in FORTRAN. I think that there are FORTRAN compilers for Apple systems. I can use existing C or C++ code, to provide "business logic" (I used to run a shop that did just that), so I guess there's a lot of languages that I could use in the backend, and, maybe, some might be better choices, for certain tasks. Again, it needs to be results-driven. If a certain kind of algorithm is most effectively implemented in Lisp, wrapped in system calls, I could embed that in a Swift wrapper.
There's also something to be said for becoming a "native speaker" of a language. That means using it fairly exclusively, over and over again. Step and repeat. I have been writing Swift, almost daily, since the day it was announced, and I still discover new things, almost every day. I think that's pretty cool.
This is stuff that I would never have discovered on a "context switch." I've usually been fairly good at picking up new languages, but I am happy to be sticking with this one, for a while. In the past, I've had to know Pascal, Object Pascal, 68K Assembly, C, C++ (and simplified variants, thereof), and Objective-C, in order to program for Apple (yeah, I've been at it a while).
Most engineers (as opposed to coders) are fairly results-oriented. We may have our differences about how to get the results, or even, what the desired results are; but we always have a deliverable in sight.
It's all about getting satisfactorily-functioning software into the hands of end-users. Put a bow on it. Stick a fork in it. It's done.
Speaking for myself, I write native Apple code (iOS/iPadOS, MacOS, WatchOS, and TVOS). I need to use Swift. I could use ObjC, but Swift is really where it's at, unless I'm doing really low-level stuff. Others may use JavaScript, or even C#, to write Apple software; using hybrid systems.
It is, indeed, mostly "gluing together calls to library functions," but there's a bit of algorithm, mixed in there, as well (not much. Many library functions provide better algorithm support than hand-rolled).
Other platforms have their most effective languages.
I probably could write Apple apps in FORTRAN. I think that there are FORTRAN compilers for Apple systems. I can use existing C or C++ code, to provide "business logic" (I used to run a shop that did just that), so I guess there's a lot of languages that I could use in the backend, and, maybe, some might be better choices, for certain tasks. Again, it needs to be results-driven. If a certain kind of algorithm is most effectively implemented in Lisp, wrapped in system calls, I could embed that in a Swift wrapper.
There's also something to be said for becoming a "native speaker" of a language. That means using it fairly exclusively, over and over again. Step and repeat. I have been writing Swift, almost daily, since the day it was announced, and I still discover new things, almost every day. I think that's pretty cool.
This is stuff that I would never have discovered on a "context switch." I've usually been fairly good at picking up new languages, but I am happy to be sticking with this one, for a while. In the past, I've had to know Pascal, Object Pascal, 68K Assembly, C, C++ (and simplified variants, thereof), and Objective-C, in order to program for Apple (yeah, I've been at it a while).
Agree with you, and Swift is also such a great language. I went from it to Lisp, sometimes I ponder about returning back (however my use case currently is for Lisp).
What are you working on in Lisp, if I may ask?
Mostly text based mathematical analysis. I couldn't stick to Swift as it would rule out a large section of the potential audience (Linux / Win - although Kotlin, which is similar enough, could bridge the gap to some degree), so I'm going more down the Web App route. For now, most of my I/O is in Emacs and later I may plan to work on the GUI side (via Electron or Web App, maybe but very unlikely CAPI or some CFFI).
How about yourself? Do you still do programming in AI?
How about yourself? Do you still do programming in AI?
I do, and I use a Lisp language for almost half of my work.
I agree with you about Swift. I am fascinated by Apple's support for machine learning models as first class components in Swift applications. I have a Swift and SwiftUI app in Apple's store that is really a simple app (short code, written as a nice example for a "Swift AI" book I am writing) that leans heavily on two embedded deep learning models. Really great stuff from Apple.
> [Lisp macros] by their nature would be hard to implement properly in a language without turning it into a dialect of Lisp.
Camlp4, Template Haskell, and Rust procedural macros all serve as counterexamples to this claim.
Camlp4, Template Haskell, and Rust procedural macros all serve as counterexamples to this claim.
To the best of my knowledge, and I could be wrong, none of those languages/extensions allow for run time generation of code. I think there is a great deal of semantic difference between compile time code execution that enables syntax manipulation and the full scope of Lisp macros. I’m not making a judgment about the value of such capabilities, but I really think they make for distinct expressability classes.
Common Lisp macros are precisely "compile time code execution that enables syntax manipulation". If by "runtime generation of code" you mean to include executing that code after it's been generated, that's not macros, that's `eval`.
Just as use of `eval` tends to be discouraged in Lisp land, it's not something that a Haskell or Rust programmer would often reach for. But in Haskell, if you really want it, GHC has an API and you can have the whole power of the compiler available to you at runtime. This isn't really a language feature per se, it's literally just linking in the whole compiler and calling it like an ordinary library. I'm not aware of anything similar to that in Rust but I haven't really looked. However, if you're only trying to generate code and not JIT-compile or execute it, the same Rust crates that support compile-time AST manipulation (like `syn` and `quote`) can equally well be used at runtime.
Just as use of `eval` tends to be discouraged in Lisp land, it's not something that a Haskell or Rust programmer would often reach for. But in Haskell, if you really want it, GHC has an API and you can have the whole power of the compiler available to you at runtime. This isn't really a language feature per se, it's literally just linking in the whole compiler and calling it like an ordinary library. I'm not aware of anything similar to that in Rust but I haven't really looked. However, if you're only trying to generate code and not JIT-compile or execute it, the same Rust crates that support compile-time AST manipulation (like `syn` and `quote`) can equally well be used at runtime.
Are you saying that they were easy to implement, and that it was done properly?
Implementing a modern, production-quality compiler is not easy as a baseline, but nothing in the design of OCaml, Haskell, or Rust adds any significant obstacles, relative to Common Lisp, to supporting this feature. Slinging an AST around and dropping it into a quasiquoted template is a well-understood problem. The simplicity of Lisp's syntax is not a prerequisite and hasn't been since the parsing techniques that were developed in the 1970s.
Done properly? I can't speak to camlp4, but at least in the case of Haskell and Rust, certainly. Incidentally I just had my first occasion to write a Rust procedural macro last weekend. I had a significantly complex transformation written and working in half a day, learning curve included, and I found it all pretty frictionless.
Done properly? I can't speak to camlp4, but at least in the case of Haskell and Rust, certainly. Incidentally I just had my first occasion to write a Rust procedural macro last weekend. I had a significantly complex transformation written and working in half a day, learning curve included, and I found it all pretty frictionless.
The litmus test is being able to remove any phrase structure in the language and replace it by a macro.
Haskell and Rust both pass this. The input doesn't even have to be a production in the source language; you can parse it any way you'd like.
Paul Graham is not a complete idiot, and you are not disproving his statement "hard to implement properly in a language without turning it into a dialect of Lisp".
If you have to parse anything, it's not a Lisp-like macro, which is always an object arising from a production in the language.
Parsing can be hard, so he is right there too. If we take out some subset of Rust that has a significant syntax, and implement it in macros, that sounds like being up to the elbows in parsing.
If you have to parse anything, it's not a Lisp-like macro, which is always an object arising from a production in the language.
Parsing can be hard, so he is right there too. If we take out some subset of Rust that has a significant syntax, and implement it in macros, that sounds like being up to the elbows in parsing.
You're not up to your elbows if somebody else has already done the work for you. If the input to your macro is a valid production in Rust, then all the parsing work that's incumbent on the macro author is to write
let ast = parse_macro_input!(input as Foo);
Where foo is some type defined by the `syn` crate and there's one for every production in Rust's grammar. But neither are you limited to those. You can also extend or replace that grammar as you see fit, but in that case the added parsing is on you.[deleted]
> And macros are definitely evidence of techniques that go beyond glue programming. For example, solving problems by first writing a language for problems of that type, and then writing your specific application in it.
Is this fundamentally different from "writing your own library to solve a problem, and then using it"?
> So if you want to expand your concept of what programming can be, one way to do it is by learning weird languages.
Isn't the conclusion here "contribute to/write your own libraries" rather than "pick a weird language"? Or "solve problems from scratch instead of relying on libraries when learning"? I feel like the "weird languages" are shoehorned into a discussion about glue programming vs library programming.
Is this fundamentally different from "writing your own library to solve a problem, and then using it"?
> So if you want to expand your concept of what programming can be, one way to do it is by learning weird languages.
Isn't the conclusion here "contribute to/write your own libraries" rather than "pick a weird language"? Or "solve problems from scratch instead of relying on libraries when learning"? I feel like the "weird languages" are shoehorned into a discussion about glue programming vs library programming.
You can express things with macros that you can not with normal code. But with the advent of decorators and templates that gap has shrunk, and with C++ templates for example. It might almost be possible to do everything with templates that you can do with macros. That code might end up looking weird though.
> Isn't the conclusion here "contribute to/write your own libraries"
If you write your own library for a popular language, you're both competing with everyone else who has written a library to do the same thing and picking fights with those who just want tell you to not reinvent the wheel.
If you write your own library for a popular language, you're both competing with everyone else who has written a library to do the same thing and picking fights with those who just want tell you to not reinvent the wheel.
The article is mostly about learning. When learning, it's fine to do things people already did. I don't like the expression "reinventing the wheel". I don't know much about engineering, but I think most of our job as developers would be closer to finding a wheel for a specific case, mostly by adapting existing solutions to fit our use case, and sometimes designing a wheel form the ground up.
In serious engineering wheels are reinvented everywhere, but somehow in software you're supposed to use existing parts that do 90% of what you need and then struggle with the remaining 10%.
In my experience of programming so far, the 0.5% thing is signal in 2 basic directions.
It is either that the problem is really hard and so most popular languages haven't attempted a solution and just make do with what they have.
Or, the problem just isn't that interesting. Like, the solution is cool, but applies very rarely and even then doesn't matter all that much. Popular languages could easily implement it, but choose not to.
It is either that the problem is really hard and so most popular languages haven't attempted a solution and just make do with what they have.
Or, the problem just isn't that interesting. Like, the solution is cool, but applies very rarely and even then doesn't matter all that much. Popular languages could easily implement it, but choose not to.
I use ML-family languages for most of my work and I simply can’t express my code in mainstream languages in a reasonable way. I could solve the same problems in a different way, but it would be a lot more code and a lot less robust. People I talk to who don’t use these languages aren’t convinced by this claim; they seem to think I’ve joined a cult! Have I? It’s difficult to judge from the inside looking in.
Just another data point: I have written largely the same tetris program both in Haskell and C++.
At first, I was blown away how short the Haskell one was, but later someone wrote that actually, world-count-wise they were largely the same, and indeed he was right.
So in certain cases, ML languages are not terser, just more wide, rather than long.
At first, I was blown away how short the Haskell one was, but later someone wrote that actually, world-count-wise they were largely the same, and indeed he was right.
So in certain cases, ML languages are not terser, just more wide, rather than long.
But surely word count is not the only criterion that matters. What about safety properties of the two programs, or maintainability/refactorability?
Length of code is probably the wrong metric. What I mean is readability or intelligibility or code. Long code is rarely readable (too many files etc) but short code can be hard to read too (e.g. code golf). However, the most readable solution will tend to be short.
> 99.5% of programming
Pulling numbers out of thin air like this to support an argument is counterproductive. This should read “Most of programming”, unless there’s research that can corroborate the number.
Pulling numbers out of thin air like this to support an argument is counterproductive. This should read “Most of programming”, unless there’s research that can corroborate the number.
I think this is a common type of hyperbole and 99.5% of people who read it will understand it isn’t intended to be taken literally.
It's worse than just stringing together library calls: Life seems to be 98% just CRUD apps. What new thoughts do I need for that, and who even has the time? An analogy: There seem to be a lot of smart Russian writers, and there's no question it's a weird language, at least to an English speaker (the alphabet! cases/declensions! idioms!) and furthermore I don't even doubt that I would think new things or in new ways if I learned it. And yet here I am using good old English, because of its popularity and (mostly) because I already know it and I can use it to get stuff done.
I don't want to knock Lisp, or any other exotic language choices. They have their benefits, people have built successful things with them, and learning a different way of doing things can expand your thinking as a developer.
On the other hand, most of the world's most complex systems are built in boring choices like C, C++, Java, or Python. The claim that this or that can only have been built or get to market fast enough if it's in Lisp doesn't pass the smell test for me.
On the other hand, most of the world's most complex systems are built in boring choices like C, C++, Java, or Python. The claim that this or that can only have been built or get to market fast enough if it's in Lisp doesn't pass the smell test for me.
There is significant 'political' pressure to use whatever is already used and has the libraries. That's C, C++, Java, etc. most of the time. If the libraries and tools were truly language independent then I'm certain more companies would choose languages like CL more frequently for their merits.
"Whatever already has the libraries" isn't political. It's technical. It's thousands of lines of code that you don't have to write, and don't have to debug, and don't have to maintain.
And having relevant libraries is (at least part of) "the merits".
And having relevant libraries is (at least part of) "the merits".
Right, but at some point, Python didn’t have all those libraries. But it did have a growing community who wanted to write them, even when it was to wrap perform at C++ or Fortran code.
There's a huge ecosystem of old Java code that is fully usable from Scala or Clojure, including stuff like bindings for native SQLite. Good FFI lets us move beyond old languages.
Don’t know about Clojure but in Scala that tends to be awkward and not preferred.
From Clojure, Java interop is pretty smooth in most cases. Perhaps Clojure being dynamic helps in that regard.
It's not that it won't work; it's that the idioms Scala is written with are different than Java, so having Java-like code mixed in messes up the coherence of the project. Not such an obstacle that you wouldn't ever do it, but enough that you'd prefer one designed for Scala if it is available.
Also there's ABCL. Yet, I have never personally been in a company or heard of a colleague where they were allowed to deviate from Java or C#. Many times it was a struggle to even get IntelliJ licenses.
Well, as the Italians say, "yes, and if my grandmother had wheels she'd be a bicycle."
A) I would say lisps are rather boring. Clojure, one of the most recent ones hasn't changed in 15 years.
B) most systems are built in C, Java, Python. So no wonder most complex systems are written in those.
I don’t really see anything new in this essay. I read Beating the Averages a while back and it was pretty eye opening to me at the time. If this post struck you, it’s probably worth reading that essay, since it expands more on your Lisp Macros and the ideas being introduced here.
I know Fortran well and Python and R somewhat. Some "weird" languages I have thought about learning are APL and similar languages (J, K, kdb, Q) and Haskell. What else? Matlabe/Octave is widely-used but is not "weird" compared to what I know.
Anyone interested in learning APL, I can recommend https://xpqz.github.io/learnapl
Disclaimer: I'm the author
Disclaimer: I'm the author
Things worth looking at can be weird in various ways. APL and J show interesting ways of using layout to bind together capable and compact primitives, in a way that avoids naming intermediates. Forth shows another interesting way to connect together primitives and calls, but it also shows how simple a powerful language can be to implement. Haskell shows you how the structures of higher mathematics can be directly used in programming. Clojure shows you how a language can embed the concept of time in distributed systems, and how immutability is compatible with change. Lisp shows you how a program can comprehend its own representation.
You have your programming language. Now, you design a special-purpose DSL (using macros or whatever) in which to express solutions to your problem. Now you have two languages. (apologies to Jamie Zawinski)
The issue is: Management of Complexity, not how to efficiently express complexity. This is why we have layers - layers are a kind of DSL; and this is where most complexity lies. Clear layering -- including defining the functions of each layer -- is how Complexity is tamed. (And this can be successfully done in assembly language, if you want.)
The main reason to master weird languages is: Fun.
The issue is: Management of Complexity, not how to efficiently express complexity. This is why we have layers - layers are a kind of DSL; and this is where most complexity lies. Clear layering -- including defining the functions of each layer -- is how Complexity is tamed. (And this can be successfully done in assembly language, if you want.)
The main reason to master weird languages is: Fun.
I find synchronous languages like Esterel, Céu, or Blech both weird and eye opening.
I created a DSL for Swift (called Pappe) to bring some of the ideas to a more mainstream language.
> Pick a language that most programmers consider weird but whose median user is smart
This just comes across as arrogant. You can neither know how smart the median user is, nor does it say much about the merits of the tool. It encourages some weird sense of superiority by putting yourself in a group that's exclusive and think they're smarter than everyone else. There are better ways to pick programming languages than trying to maximise your own pretentiousness.
This just comes across as arrogant. You can neither know how smart the median user is, nor does it say much about the merits of the tool. It encourages some weird sense of superiority by putting yourself in a group that's exclusive and think they're smarter than everyone else. There are better ways to pick programming languages than trying to maximise your own pretentiousness.
I'm a javascript fan. I think it's a good language and for the most part I enjoy programming in it.
However I am not going to argue that the median javascript user is as smart as the median ocaml user. 99% of people learn javascript because they have to. Most people learn ocaml because they are enthusiasts. They're interested in programming language concepts and becoming more effective.
However I am not going to argue that the median javascript user is as smart as the median ocaml user. 99% of people learn javascript because they have to. Most people learn ocaml because they are enthusiasts. They're interested in programming language concepts and becoming more effective.
Why do you think JavaScript is a good language?
It is wildly flexible, aligned with how programming is taught, and infinitely documented.
It is the swiss army knife of programming. Even top-tier hackers use it as a primary tool. Check out Frida[1], it uses the Chrome v8 engine to inject parasitic tracing code written in JavaScript into any OS (incl. android & ios). There's no language that would have fit the bill like JS+v8.
[1] https://frida.re/
It is the swiss army knife of programming. Even top-tier hackers use it as a primary tool. Check out Frida[1], it uses the Chrome v8 engine to inject parasitic tracing code written in JavaScript into any OS (incl. android & ios). There's no language that would have fit the bill like JS+v8.
[1] https://frida.re/
Isn’t V8 written in C++? There’s no reason Python can’t be as much a Swiss Army knife, except that it doesn’t run in the browser, which was just a historical matter that it was JS and not some other language. Tcl was proposed, and Sun tried to get Netscape to run Java natively.
Thank god it wasn't TCL.
- Relatively expressive
- Relatively fast
- Enormous ecosystem - the "good parts" of which still have practically everything you need
- Top notch typechecker in the form of typescript
- Relatively fast
- Enormous ecosystem - the "good parts" of which still have practically everything you need
- Top notch typechecker in the form of typescript
I'm a big fan of Javascript. It runs everywhere, is easy to write, is brutally flexible.
I would never call it a "good" language. It is an abomination created by the dev teams at 4 different browser companies over the course of 20 years with no coordination between them.
I would never call it a "good" language. It is an abomination created by the dev teams at 4 different browser companies over the course of 20 years with no coordination between them.
And the original version was banged out in a very short time period to create a feature. Then everyone else just piled onto it w/o consideration for the consequences.
There is a useful and practical small diamond hidden in the big ball of mud.
Yeah, it's called Lisp.
For those who are downvoting me: Javascript was deliberately invented to be Scheme without the Lisp syntax... Jesus.
Javascript would be amazing with s-expressions and hygienic macros. One of the biggest missed opportunities in our field.
Via the Self programming language. That’s where prototypes come from. Self messages were closures, so JS functions are first class. Smalltalk was considered to be in the spirit of Lisp, and Self replaced classes with prototypes. That or Brendan Eich was mixing several features from expressive languages.
JavaScript is basically a lispy core with Java or C esque syntax and a bunch of features from all other programming languages incorporated over 20 years. It's fast, flexible and easy to learn. Just look at all the things that have been built in JavaScript...
Yeah that sentence felt quite weird. I’m not sure I would say that “smart” is a rigorously defined term.
Agreed, it is self-congratulatory.
Paul Graham essays decline in value exponentially with the number of times he mentions Lisp in them. He had one that went below 2^-20.
Paul Graham essays decline in value exponentially with the number of times he mentions Lisp in them. He had one that went below 2^-20.
Why do you think Paul Graham essays decline in value exponentially with the number of times he mentions Lisp in them?
I think a similar thing can be said about time. There were a lot of novel things to share in the early days, but these days it seems like his essays have taken a turn toward trite elitism. To be clear, I don't think this is specific to PG, but rather the case whenever someone feels the urge to continue producing for the sake of producing, nor am I saying that I'd be able to do any better. PG obviously has orders of magnitude more wisdom to share than me or most other people.
Needs to do a Daniel Day Lewis and go make shoes for a bit instead? (or whatever DDL is doing)
Probably a good idea for anyone that reaches the level of becoming a “public figure”. Log off, go do something with your hands, and come back in 4-6 months. Might reduce the incidence of formerly respected figures going full crank.
Yes !
Doing something outside of your bubble is great for learning some humility and G-d knows PG could do with some of that.
Doing something outside of your bubble is great for learning some humility and G-d knows PG could do with some of that.
Once your rich and have made it you can’t emulate hustle mode anymore. Sure you can shine shoes but in the back of your mind you know you don’t have to.
It seems like the trend for the past ~10 years has been towards public figures slowly becoming cranks online. I have no idea why, but it sure seems to be happening a lot.
It is true of those with a Facebook or Twitter account, and it is because they need to get increasingly cranky to maintain the level of attention they have got used to. I doubt a change in algorithm could help much, but it seems worth trying more than once.
I _really_ don't know how you got that from this article.
Yeah, this data simply doesn't exist and trying to judge languages by their community will often leave you with variable perceptions, depending on many factors.
I'm not entirely sure about that. Sure, it's probably not in good taste to claim that, however there are plenty of tricky languages out there that have steep learning curves but that are very capable in their own domains.
Even in lieu of that bad taste or elitism, I'd still like to suggest that it takes more patience, self discipline and perhaps a tinge of being clever to pick up something like C, C++, Rust, Haskell, Lisp, APL, Prolog or even regular expressions than it does Java, .NET, Node/JavaScript/TypeScript, Python and others and I say that as a person who relies on the latter for the most part in their daily life.
It's not that you have to be an outright genius to use any of them, but writing code in them well (for example, managing memory and avoiding C++ footguns) takes discipline and definitely could be applauded on some level, as could using APL, Prolog or regular expressions to efficiently solve problems in the few domains that they're actually good at and suited for.
Personally, some of these views of mine formed after listening to a podcast that talked about APL and someone's experience with it: https://corecursive.com/065-competitive-coding-with-conor-ho...
Even in lieu of that bad taste or elitism, I'd still like to suggest that it takes more patience, self discipline and perhaps a tinge of being clever to pick up something like C, C++, Rust, Haskell, Lisp, APL, Prolog or even regular expressions than it does Java, .NET, Node/JavaScript/TypeScript, Python and others and I say that as a person who relies on the latter for the most part in their daily life.
It's not that you have to be an outright genius to use any of them, but writing code in them well (for example, managing memory and avoiding C++ footguns) takes discipline and definitely could be applauded on some level, as could using APL, Prolog or regular expressions to efficiently solve problems in the few domains that they're actually good at and suited for.
Personally, some of these views of mine formed after listening to a podcast that talked about APL and someone's experience with it: https://corecursive.com/065-competitive-coding-with-conor-ho...
I think that you're moving the goalposts a bit by focusing on difficulty or complexity. Yes, of course some languages are more difficult than others. But the difficulty of a language is separate from the intelligence of the users of that language.
I think it has to do with active choice. The first programming language that people are introduced to are unlikely to be the "best" for them. The first programming languages are disproportionately java, c#, PHP these days. By extension the talented people mostly move on as they learn new and interesting ideas. This leaves the pool of developers poisoned by the mediocre or bad people who spend their entire careers being expert beginners in one domain. People come to the more exotic languages, like Haskell, as their second, third or fourth language. By default the average developer in that pool will just be much much stronger.
Just because the average developer in a language is bad it doesn't mean that the language itself is bad.
Just because the average developer in a language is bad it doesn't mean that the language itself is bad.
[deleted]
> The first programming languages are disproportionately java, c#, PHP these days.
I'd say it depends on what we're defining "first programming languages" as - first PL learnt in intro-level university lecture, or first PL learnt individually? But my impression is that the most popular PL for beginners seems to be Python. And while I'm not really a fan of Python, I understand where that's coming from: Python is relatively simple to learn, has a huge library ecosystem and comes with relatively few footguns.
I'd say it depends on what we're defining "first programming languages" as - first PL learnt in intro-level university lecture, or first PL learnt individually? But my impression is that the most popular PL for beginners seems to be Python. And while I'm not really a fan of Python, I understand where that's coming from: Python is relatively simple to learn, has a huge library ecosystem and comes with relatively few footguns.
+1 on this, maybe it was C#, PHP and Java ten to fifteen years ago but it's not the case now.
> But the difficulty of a language is separate from the intelligence of the users of that language.
I feel like this is obviously true when taken at face value, however in practice there are probably loose correlations (not causation) between those two, even if not for the reasons that you'd expect.
I'm not sure whether it was mentioned in the same podcast that i linked, or another one, but there was a very interesting example for Haskell that was offered in one discussion. The argument was that the people who utilize Haskell tend to be more likely than the average developer to have ties to academia (which may incidentally also speak of their cognitive abilities):
Now, the person might be wrong, since their observations are bound to be subjective and i might be wrong to assume that they hold true in many cases because of how believable all of that sounds, but to answer your question, i'd argue that the average user of Haskell is indeed a bit more intelligent than the average user of Java or many other general purpose languages (even though then we step on the mine of having to define what intelligence even is, where opinions can once again differ).
I'd say that simply happens, because some of those languages are far more approachable and therefore more widely used by a large audience of people, not all of which need to concern themselves with solving the issues that people in academia need to deal with. Of course, there could be the counterpoint that not everyone in academia is brilliant, but i remember seeing some pretty admirable professors and researchers back when i was in my university!
I feel like this is obviously true when taken at face value, however in practice there are probably loose correlations (not causation) between those two, even if not for the reasons that you'd expect.
I'm not sure whether it was mentioned in the same podcast that i linked, or another one, but there was a very interesting example for Haskell that was offered in one discussion. The argument was that the people who utilize Haskell tend to be more likely than the average developer to have ties to academia (which may incidentally also speak of their cognitive abilities):
- Haskell is popular for numerical processing, moreso than for the somewhat typical CRUD apps
- because of this, Haskell is more likely to have materials describing it which are aimed towards an academian audience
- ergo, those materials won't always be simple step by step tutorials on how to do things, but will sometimes assume familiarity with certain maths concepts and will also focus on solving a particular set of (advanced) problems
- and when these materials attempt to explain these simpler things, invariably you'll still end up with explanations of what monads are somewhere in there, whereas with something like Python you'd have less overhead and a less steep learning curve
- as a consequence of all of this, Haskell won't be as popular as Python, or similar languages
In the podcast, the person said that these "weird" (or perhaps "niche" is a better word) languages would be far more widespread if they were made more easily approachable, because right now there are no easy and simple to digest books to recommend to people who'd like to get started with them.Now, the person might be wrong, since their observations are bound to be subjective and i might be wrong to assume that they hold true in many cases because of how believable all of that sounds, but to answer your question, i'd argue that the average user of Haskell is indeed a bit more intelligent than the average user of Java or many other general purpose languages (even though then we step on the mine of having to define what intelligence even is, where opinions can once again differ).
I'd say that simply happens, because some of those languages are far more approachable and therefore more widely used by a large audience of people, not all of which need to concern themselves with solving the issues that people in academia need to deal with. Of course, there could be the counterpoint that not everyone in academia is brilliant, but i remember seeing some pretty admirable professors and researchers back when i was in my university!
What's interesting isn't the difficulty or complexity of the language, but the difficulty of the problems that language is typically used to solve.
Some languages are difficult to learn initially (like Prolog) but that's not because they are intentionally obscure, but because they need to be different.
Some languages are difficult to learn initially (like Prolog) but that's not because they are intentionally obscure, but because they need to be different.
By "problems to solve" do you mean
- programming language problems like making certain language features, paradigms and kinds of abstractions available (or not available)
or
- solving actual problems when building software - how to build a maintainable and performant server, OS, web UI etc.
For the second you're better off staying away from the 'weird' languages especially if you care about being productive.
- programming language problems like making certain language features, paradigms and kinds of abstractions available (or not available)
or
- solving actual problems when building software - how to build a maintainable and performant server, OS, web UI etc.
For the second you're better off staying away from the 'weird' languages especially if you care about being productive.
Well, lispers claim that lisp is really good for building programs where the specifications are complicated and not already a solved problem. Smalltalkers claim their environment is incredibly good for prototyping a solution. And array programmers would argue numerical computing is much easier in their languages.
I think by "smart" they mean "reasonably smart" or "smart about the programming language they pick". Some people just don't care and work 9-5 programming jobs without caring about what language they use as long as they get a paycheck.
No. He means "clever" or "inquisitive."
The way I think about programming changed a lot from having used different programming paradigms. Many programming paradigms have little real-world value, but they do make you think about computation, abstraction, and lots of other concepts differently.
That grows your brain in ways which are useful when you go back to your 9-5 Python/JavaScript/Java/C#/etc.
I no longer have time to do these sorts of deep dives, but I did this a lot when I was young, and I'm a much better programmer for it.
I'd look at what he's writing over how he communicates it. Perhaps the language might be arrogant or self-congratulatory, but it benefits you more to look at what he's saying than how he says it. (responding to thread here; you obviously didn't make this mistake)
The way I think about programming changed a lot from having used different programming paradigms. Many programming paradigms have little real-world value, but they do make you think about computation, abstraction, and lots of other concepts differently.
That grows your brain in ways which are useful when you go back to your 9-5 Python/JavaScript/Java/C#/etc.
I no longer have time to do these sorts of deep dives, but I did this a lot when I was young, and I'm a much better programmer for it.
I'd look at what he's writing over how he communicates it. Perhaps the language might be arrogant or self-congratulatory, but it benefits you more to look at what he's saying than how he says it. (responding to thread here; you obviously didn't make this mistake)
There's a good chance you misread it.
I interpreted it at second effort as:
"Pick a language that is famous for being an oddball but that has good credentials, since you have seen that people that to you are worth credit use it".
I interpreted it at second effort as:
"Pick a language that is famous for being an oddball but that has good credentials, since you have seen that people that to you are worth credit use it".
“Weird sense of superiority” is a very succinct way of describing most of PG’s takes on programming.
I’m reminded of his argument about how “hackers” choose languages that let them type the fewest characters possible, an argument that seems empirically unfounded to me.
I’m reminded of his argument about how “hackers” choose languages that let them type the fewest characters possible, an argument that seems empirically unfounded to me.
What is the most impressive programming feat PG ever accomplished? A Lisp dialect maybe?
I sort of get the sense that he doesn't realize how many crazy talented (but not famous) programmers there are out there. He's got a microphone and is determined to keep using it to tell us how great his ideas are, but the audience has gotten a lot more discerning since the 90s when producing a CRUD app in Lisp could still be considered a feat.
I sort of get the sense that he doesn't realize how many crazy talented (but not famous) programmers there are out there. He's got a microphone and is determined to keep using it to tell us how great his ideas are, but the audience has gotten a lot more discerning since the 90s when producing a CRUD app in Lisp could still be considered a feat.
> I’m reminded of his argument about how hackers choose languages that let them type the fewest characters possible
Ah yes, just like real writers write in Ithkuil, a language constructed to maximize the meaning encoded per syllable.
Ah yes, just like real writers write in Ithkuil, a language constructed to maximize the meaning encoded per syllable.
Some of PGs arguments against static typing (in hackers and painters, IIRC) were also completely unfounded. It turned out he was confusing static typing with explicitly having to type (keystrokes that is) the type of a variable or parameter. Utterly unaware of type inference.
Static typing and inference aside, I find that his arguments about language verbosity and character count utterly without evidence. A quick review of the startup scene will show a wide mix of programming languages, including a lot of Java.
It’s fine if that’s his preference, but the argument that the best programmers (“hackers” in his parlance) prefer what he prefers to be both self serving and contrary to actual real world evidence.
It’s fine if that’s his preference, but the argument that the best programmers (“hackers” in his parlance) prefer what he prefers to be both self serving and contrary to actual real world evidence.
I wonder how much coding PG does these days. He reminds me of Al Bundy, how Al constantly talks about his highschool football team years as his life's peak, 30 years after the fact.
There is nothing wrong with admitting that a certain group of people is smarter than another one. I would be very surprised if the members of the group I did my PhD in were not much smarter than the average programmer.
You think hiding behind academic trophys can raise your iq?
No. I am saying that the IQ of academics is higher in the first place. Not in general, but in that group for certain.
So, you think that hunting for academic trophys does not correlate with smartness? And the way to become smarter is cracking an IQ test to gain a high number to be hiding behind?
Richard O'Keefe (2013), erlang-questions mailing list:
Personally, I'd maybe not apply the adjective "smartness" here, but there is some sense in which some languages have better taste than others, and what drives language popularity is not usually good taste, and I interpret pg here to be saying he prefers to recruit programmers who show good taste in the languages they work with.
Once upon a time (about 1992ish) in a land where the moles
have beaks and swim and the deer jump on their hind legs
(Australia), a certain computer science department (RMIT)
decided that Pascal had reached its use-by date. What shall
we do? What shall we replace it with? Set up a committee!
I was on the committee. We set up a short list.
(1) Scheme.
Tiny language, amazingly capable, REPL so you can try
things out, implementations for all the machines we
cared about. And Rob Hagan at Monash had shown that
you could teach students more COBOL with one semester
of Scheme and one semester of COBOL than you could
with three semesters of COBOL.
(2) Miranda.
The commercial precursor of Haskell.
Melbourne University were also looking at this (or had
already switched to it) which would make it easier to
pick up some of their students.
(3) Ada.
Close enough to Pascal that our staff were comfortable
with it and our material would not need major revision.
A better Pascal than Pascal.
Handled concurrency about as nicely as an
imperative language can.
What was the deciding factor?
Schools.
Our deliberations leaked, and we started getting phone calls from
careers masters saying "if you go all theoretical [read: (1) or (2)]
we'll tell our pupils not to study with you."
http://erlang.org/pipermail/erlang-questions/2013-January/07...Personally, I'd maybe not apply the adjective "smartness" here, but there is some sense in which some languages have better taste than others, and what drives language popularity is not usually good taste, and I interpret pg here to be saying he prefers to recruit programmers who show good taste in the languages they work with.
My school started everyone with a semester of Scheme, followed by a semester of C.
I don't have any sort of legitimate control group to compare to, and I'm obviously biased as heck, but I do still hold the impression that I and others who learned that way can learn new languages and programming techniques much more quickly than acquaintances who were fed a steady diet of Java or Python. Many of them, even 20 years on, still don't really have a firm grasp of what single dispatch is in the first place, which hinders their ability to use it well. Which is ironic, considering it's all they've ever known.
I agree; I hate the "smart" perception. My guess is that, if there's anything there, it's just the gift of a stronger grasp of the fundamentals. Scheme brings you very close to the abstract foundation of computer science. C brings you very close to the technical foundation of computer engineering. I'd like to think there's a lot of value in starting out by establishing a firm foundation like that.
I don't have any sort of legitimate control group to compare to, and I'm obviously biased as heck, but I do still hold the impression that I and others who learned that way can learn new languages and programming techniques much more quickly than acquaintances who were fed a steady diet of Java or Python. Many of them, even 20 years on, still don't really have a firm grasp of what single dispatch is in the first place, which hinders their ability to use it well. Which is ironic, considering it's all they've ever known.
I agree; I hate the "smart" perception. My guess is that, if there's anything there, it's just the gift of a stronger grasp of the fundamentals. Scheme brings you very close to the abstract foundation of computer science. C brings you very close to the technical foundation of computer engineering. I'd like to think there's a lot of value in starting out by establishing a firm foundation like that.
This is a very nice combination to have for those students who want to go deep into language implementation and its interface with OSes. C is good for understanding how to write VMs, Scheme is great for code transformation.
For reference, this Richard O' Keefe:
Dr. Richard A. O'Keefe is a computer scientist best known for writing the influential book on Prolog programming, The Craft of Prolog.[1] He was a lecturer and researcher at the Department of Computer Science at the University of Otago in Dunedin, New Zealand and concentrates on languages for logic programming and functional programming (including Prolog, Haskell, and Erlang).
https://en.wikipedia.org/wiki/Richard_O%27Keefe
Dr. Richard A. O'Keefe is a computer scientist best known for writing the influential book on Prolog programming, The Craft of Prolog.[1] He was a lecturer and researcher at the Department of Computer Science at the University of Otago in Dunedin, New Zealand and concentrates on languages for logic programming and functional programming (including Prolog, Haskell, and Erlang).
https://en.wikipedia.org/wiki/Richard_O%27Keefe
This is both troubling and understanding as someone who has been on both sides.
As a student, we were required to learn assembly in a microcontrollers course. It was a disaster, because it was a very short semester and they were asking we learn microcontrollers and assembly at the same time when most of us could barely program to begin with. I left a review urging they change to C (still low level, but so much easier) and they actually switched the next year.
Learning ASM is indeed important from a theoretical stance (and practical for some jobs), but you can't expect students to just pick that up in a few weeks worth of classes.
Then when I got an office job, I learned a LOT of engineers do process automation programming. At that point I could see even something as hideous as VBA being used to efficiently save hundreds of hours of work.
What do students really need? It depends on a lot of factors. Are they going into academia to study PL theory? Then Lisp, Prolog, C, and Haskell are probably pretty important. Are 95% of your students going into industry? Then Python, C++, Java, C#, JS, Excel, and SQL are all going to be important.
I think the really theoretical stuff (Haskell, Prolog, Lisp) should only be briefly introduced in undergrad and expanded upon in grad school. Or you have specific academic or industry based programs.
As a student, we were required to learn assembly in a microcontrollers course. It was a disaster, because it was a very short semester and they were asking we learn microcontrollers and assembly at the same time when most of us could barely program to begin with. I left a review urging they change to C (still low level, but so much easier) and they actually switched the next year.
Learning ASM is indeed important from a theoretical stance (and practical for some jobs), but you can't expect students to just pick that up in a few weeks worth of classes.
Then when I got an office job, I learned a LOT of engineers do process automation programming. At that point I could see even something as hideous as VBA being used to efficiently save hundreds of hours of work.
What do students really need? It depends on a lot of factors. Are they going into academia to study PL theory? Then Lisp, Prolog, C, and Haskell are probably pretty important. Are 95% of your students going into industry? Then Python, C++, Java, C#, JS, Excel, and SQL are all going to be important.
I think the really theoretical stuff (Haskell, Prolog, Lisp) should only be briefly introduced in undergrad and expanded upon in grad school. Or you have specific academic or industry based programs.
> I think the really theoretical stuff (Haskell, Prolog, Lisp) should only be briefly introduced in undergrad and expanded upon in grad school. Or you have specific academic or industry based programs.
My experience is Haskell actually is highly practical for many tasks. So I think it’s misleading to call it “really theoretical”. It’s the reason you see FP in areas as diverse as spam filtering, distributed computing, smart contracts, various financial services, etc.
While less common, there absolutely are areas in industry that do tend to use FP, and I don’t think you should cut students off from easily entering those specialties (or having to plan to enter them ahead of time).
Additionally, there are concepts used in imperative languages which are not as easy to understand or express in those languages, e.g. promises, are more clearly expressed as monads in a language like Haskell.
My experience is Haskell actually is highly practical for many tasks. So I think it’s misleading to call it “really theoretical”. It’s the reason you see FP in areas as diverse as spam filtering, distributed computing, smart contracts, various financial services, etc.
While less common, there absolutely are areas in industry that do tend to use FP, and I don’t think you should cut students off from easily entering those specialties (or having to plan to enter them ahead of time).
Additionally, there are concepts used in imperative languages which are not as easy to understand or express in those languages, e.g. promises, are more clearly expressed as monads in a language like Haskell.
I think your view of Haskell's use in industry is skewed by HN. Yes there are SOME Haskell jobs, but it's not even in the top 50 languages last I checked (or if it is, it is still far down the list). A student getting a job doing spam filtering in Haskell for FB would be a nearly zero probability event in comparison to something in Java. Just go look for Haskell job postings. I bet it's 0.0001% of something like C#. So when you say uncommon, I see exceedingly rare. Every hour of student time is precious, so a single course covering PL theory in undergrad that introduces the concepts should be plenty. If someone really needs to learn Haskell in industry (a unicorn case), they can do it there. Otherwise the focus should be on practical experience and theory relevant to 95% of computer science and related jobs (object oriented programming, SQL or NoSQL databases, algorithms, web development, networks, operating systems, cloud computing...etc).
> I think your view of Haskell's use in industry is skewed by HN
It’s really funny you say that, I view HN as being frequently anti-FP. I guess when you split the difference everyone is a bit unhappy. In my case I’ve been programming for over 30 years and only on HN for a few months, so I don’t feel like it’s swayed me much, you never know. I’ve read Graham for years and he certainly has been an influence.
Overall Haskell alone isn’t that big in industry, but it most clearly illustrates many FP concepts and is the originating point (or an early adopter) of new tech that makes it into other languages.
If you look at all the jobs in Scala, Haskell, Clojure, F#, OCaml, Elm, Erlang, and PureScript. Then you throw in all the jobs in multi-paradigm languages Python, JS, etc. with managers or coding standards that dictate functional techniques, then subtract the particularly awful soul crushing dead-end jobs (that regardless of paradigm or language) probably none of us want, I think you may be underestimating the representation of FP.
Ultimately when I hire someone with a 4 year degree from a research university, I’m not expecting them to have 100% vocational training, they should be literate in at least a couple languages, but I’m much more interested in knowledge of concepts and adaptability.
The best Python programmer I’ve worked with described his junior year as being almost entirely Standard ML. I think he was better for it.
It’s really funny you say that, I view HN as being frequently anti-FP. I guess when you split the difference everyone is a bit unhappy. In my case I’ve been programming for over 30 years and only on HN for a few months, so I don’t feel like it’s swayed me much, you never know. I’ve read Graham for years and he certainly has been an influence.
Overall Haskell alone isn’t that big in industry, but it most clearly illustrates many FP concepts and is the originating point (or an early adopter) of new tech that makes it into other languages.
If you look at all the jobs in Scala, Haskell, Clojure, F#, OCaml, Elm, Erlang, and PureScript. Then you throw in all the jobs in multi-paradigm languages Python, JS, etc. with managers or coding standards that dictate functional techniques, then subtract the particularly awful soul crushing dead-end jobs (that regardless of paradigm or language) probably none of us want, I think you may be underestimating the representation of FP.
Ultimately when I hire someone with a 4 year degree from a research university, I’m not expecting them to have 100% vocational training, they should be literate in at least a couple languages, but I’m much more interested in knowledge of concepts and adaptability.
The best Python programmer I’ve worked with described his junior year as being almost entirely Standard ML. I think he was better for it.
This is a great quote:
> And Rob Hagan at Monash had shown that you could teach students more COBOL with one semester of Scheme and one semester of COBOL than you could with three semesters of COBOL.
Really makes the point about how studying uncommon languages can pay off.
> And Rob Hagan at Monash had shown that you could teach students more COBOL with one semester of Scheme and one semester of COBOL than you could with three semesters of COBOL.
Really makes the point about how studying uncommon languages can pay off.
I've known a great many programmers over many years and I've observed some patterns I'll note below. I'm not hypothesizing on why any of this is and it could be for any number of reasons. However, neither arrogance nor a desire to maximize pretentiousness has struck me as one of them, except for a handful of the most immature persons who quickly grew out of it.
Every single programmer interested in any language in the ML family or Haskell has considerably above average[1] intellectual horsepower. The syntax and type system can both fairly be called "weird."
The Lisp programmers I've encountered are along a wider range. They've ranged from average to ML tier, the latter being the ones that, as PG observes, are more interested in "weird" features like macros, call/cc, and so on.
And then you have extremely popular languages like C, C++, Java, JavaScript, Python, and so on. Virtually every programmer has used one or more of them to a significant degree, so the mean programmer using one of those languages is virtually the same as the mean programmer in the general population. This is expected since in cases like this the mean of a subset approaches the mean of its superset as the size of the latter approaches that of the former. Programmers who master C++'s template system are an exception to the above. They're also well above average.
[1] In this comment everywhere I say average or mean I'm referring to programmers and not the general population. Average isn't bad, the average person here is quite bright for example.
Every single programmer interested in any language in the ML family or Haskell has considerably above average[1] intellectual horsepower. The syntax and type system can both fairly be called "weird."
The Lisp programmers I've encountered are along a wider range. They've ranged from average to ML tier, the latter being the ones that, as PG observes, are more interested in "weird" features like macros, call/cc, and so on.
And then you have extremely popular languages like C, C++, Java, JavaScript, Python, and so on. Virtually every programmer has used one or more of them to a significant degree, so the mean programmer using one of those languages is virtually the same as the mean programmer in the general population. This is expected since in cases like this the mean of a subset approaches the mean of its superset as the size of the latter approaches that of the former. Programmers who master C++'s template system are an exception to the above. They're also well above average.
[1] In this comment everywhere I say average or mean I'm referring to programmers and not the general population. Average isn't bad, the average person here is quite bright for example.
> Every single programmer interested in any language in the ML family or Haskell has considerably above average[1] intellectual horsepower.
Just to point that there's nothing strange or unexpected about this. You will get people that are more intellectual than average it you filter by any niche intellectual activity with no immediate non-intellectual reward.
I mean, if you search for programmers that understand plant physiology, you will get the same effect. It basically means that smart people tend to be curious.
Just to point that there's nothing strange or unexpected about this. You will get people that are more intellectual than average it you filter by any niche intellectual activity with no immediate non-intellectual reward.
I mean, if you search for programmers that understand plant physiology, you will get the same effect. It basically means that smart people tend to be curious.
>The Lisp programmers I've encountered are along a wider range. They've ranged from average to ML tier, the latter being the ones that, as PG observes, are more interested in "weird" features like macros, call/cc, and so on.
I'd say that since there's lack of Haskell jobs, then non passionate people do not touch it since it's useless to them
Passionate people check it out cuz other passionate people recommended it
And circle repeats.
I'd say that since there's lack of Haskell jobs, then non passionate people do not touch it since it's useless to them
Passionate people check it out cuz other passionate people recommended it
And circle repeats.
Well, the current mode is to select by availability of cheap resumes (majority) or fashion (minority, hip places).
Whik I'm not sure I'd always agree with PG, a recent anecdata I heard was a company selecting for Lisp because picking Python meant wading through mountains of fresh bootcamp grads with (quote) "overblown sense of their own capability" (unquote) - same applied to JS, less so to C#/Java.
(Un)fortunately, the company noticed they didn't have resources to filter that, and decided that by going for "weird but capable" combined with global remote organisation they could filter for people experienced, or willing to experiment with weirder languages. Apparently ithe cost of having to sometimes implement things from scratch was lower than expected.
Whik I'm not sure I'd always agree with PG, a recent anecdata I heard was a company selecting for Lisp because picking Python meant wading through mountains of fresh bootcamp grads with (quote) "overblown sense of their own capability" (unquote) - same applied to JS, less so to C#/Java.
(Un)fortunately, the company noticed they didn't have resources to filter that, and decided that by going for "weird but capable" combined with global remote organisation they could filter for people experienced, or willing to experiment with weirder languages. Apparently ithe cost of having to sometimes implement things from scratch was lower than expected.
I'd say it's obviously true and right. And it doesn't require assuming arrogance and pretentiousness.
Niche languages, by definition, are not good investment if you're after a well-paying job. A niche language that requires understanding advanced programming concepts is, by definition, filtering for people who a) can understand those concepts, and b) have a non-monetary reason for doing so, which implies c) they're likely not faking it.
Whether or not such people would be good software engineers is another topic. Software engineering encompasses more skills than just raw programming ability. But a proficiency in advanced niche language plus proficiency in a mainstream language plus some work experience? It's hard to imagine how this would not be a good signal for smarts and skills.
Niche languages, by definition, are not good investment if you're after a well-paying job. A niche language that requires understanding advanced programming concepts is, by definition, filtering for people who a) can understand those concepts, and b) have a non-monetary reason for doing so, which implies c) they're likely not faking it.
Whether or not such people would be good software engineers is another topic. Software engineering encompasses more skills than just raw programming ability. But a proficiency in advanced niche language plus proficiency in a mainstream language plus some work experience? It's hard to imagine how this would not be a good signal for smarts and skills.
What a strange argument. What I've seen in other fields is that when the people who are clearly smarter than me in those fields (whether by natural ability or by experience and hard work) tend to use different tools than I do it is usually because those tools are better for work in that field. They might also be harder to learn or use, but for those who can learn to use them well they end up being more productive than if they used the tools I am using.
If I see just one smarter than me person using a particular tool for some task that I also do, it might be because they are using it as an intellectual challenge or for variety, but if I see a lot of smarter than me people using it for that task I've almost always found it is worth looking into it seriously to see if I should use it too.
If I see just one smarter than me person using a particular tool for some task that I also do, it might be because they are using it as an intellectual challenge or for variety, but if I see a lot of smarter than me people using it for that task I've almost always found it is worth looking into it seriously to see if I should use it too.
Maybe the following would have been more appropriate?
“Pick a language that most programmers consider weird but whose median user is curious and shows the initiative to explore strange new worlds of how to get things done.”
I consider myself a very capable hack. I am not really very “smart.” But I am motivated to learn more. And to improve the craft of software solutions.
“Pick a language that most programmers consider weird but whose median user is curious and shows the initiative to explore strange new worlds of how to get things done.”
I consider myself a very capable hack. I am not really very “smart.” But I am motivated to learn more. And to improve the craft of software solutions.
Oh c'mon. There are clearly languages where the median intelligence of the community members is higher than others -- I'm not a Haskell fan myself, but I have to concede that the community around Haskell is very obviously comprised of smarter than average people. Check out their IRC or Slack channel if you have any doubt.
I think it makes sense. For example, Erlang is a kinda weird (to me) language. Back in 2017, I went through a book on Elixir + Phoenix, and then spent some time going through Erlang topics. I mostly spend my day on mobile app and backend programming, in languages like Swift/Kotlin/Javascript/Go.
I believe I learned a lot, and most of the people I encountered on those slacks and forums seemed a lot more experienced and capable. That's also because the language is kind of niche but powerful, so not everyone is starting out their career trying to print Hello World in Erlang. It is a language one would discover when trying to solve a specific problem, in my opinion at least. Therefore, there are less noobs like me and the people I encountered were super helpful and thorough compared to my experience on other languages.
I believe I learned a lot, and most of the people I encountered on those slacks and forums seemed a lot more experienced and capable. That's also because the language is kind of niche but powerful, so not everyone is starting out their career trying to print Hello World in Erlang. It is a language one would discover when trying to solve a specific problem, in my opinion at least. Therefore, there are less noobs like me and the people I encountered were super helpful and thorough compared to my experience on other languages.
Yup, it feels like my disillusionment with SV and PG are tracking, this is comes across as someone that likes the smell of their own output and wants everyone to know.
I disagree. The quote only mentions that the median user should be smart, which means that you can also learn from them if you are inexperienced.
I also see no pretentiousness. With smart people hundreds of useless discussions are avoided in the first place. If you work in a popular language like Python that attracts all sorts of people, you have 10 preposterous technical and social discussions per day.
I think this essay isn't supposed to be anything comprehensive about Lisp, it's just encouraging his target audience to consider other options.
I also see no pretentiousness. With smart people hundreds of useless discussions are avoided in the first place. If you work in a popular language like Python that attracts all sorts of people, you have 10 preposterous technical and social discussions per day.
I think this essay isn't supposed to be anything comprehensive about Lisp, it's just encouraging his target audience to consider other options.
I understand your sentiment. Back when Coursera first started I took a class where 10 minutes into the first lecture the teacher said something like “This is the basic 3rd year calculus you did in highschool”. This was discouraging because it made a qualifying assumption about both me and my highschool that was far removed from my reality. In the end, that detail had no bearing on the class, and seemed to exist only to humiliate me.
But, many years later, I’ve learned I gain nothing from this kind of defensiveness, and simply keep a running list of things I’m “supposed” to know, but don’t yet. Of course, now that is a small list of very uncommon things, which itself shows how much I’ve progressed.
Point being, digging in your heels only hurts yourself.
But, many years later, I’ve learned I gain nothing from this kind of defensiveness, and simply keep a running list of things I’m “supposed” to know, but don’t yet. Of course, now that is a small list of very uncommon things, which itself shows how much I’ve progressed.
Point being, digging in your heels only hurts yourself.
In my experience there's a form of stupidity that comes from simply being incurious. Whether someone is interested in exploring languages outside the present set of mainstream imperative languages seems to pretty good indicator of that intellectual curiosity.
> So if you want to expand your concept of what programming can be, one way to do it is by learning weird languages.
This is surely the key line here - and the stuff about glue code and median users etc frankly just detracts from it.
It's true in any field. If you want to expand your ways of thinking look for stuff that has been reasonably successful but is outside the mainstream. Put it that way it's sort of obvious but probably easy to forget.
This is surely the key line here - and the stuff about glue code and median users etc frankly just detracts from it.
It's true in any field. If you want to expand your ways of thinking look for stuff that has been reasonably successful but is outside the mainstream. Put it that way it's sort of obvious but probably easy to forget.
For the non-lisp programmer, can someone explain how the Macro differs from a library call, or other function? If you're building the language, vs building your code, is this really that different?
Having read about this, the best analogy I can think of is that macros are like engineered wood. If you're building a structure, you can build bigger ones with engineered wood, than with run of the mill (literally) stuff.
Having read about this, the best analogy I can think of is that macros are like engineered wood. If you're building a structure, you can build bigger ones with engineered wood, than with run of the mill (literally) stuff.
Macros let you change the syntax, roughly speaking. With a library, you're still calling the library with standard syntax.
E.g. https://en.m.wikipedia.org/wiki/Anaphoric_macro
E.g. https://en.m.wikipedia.org/wiki/Anaphoric_macro
A macro is a bit like a template in web programming. You define a structure and some variables that will be filled in. The difference to a template is, a template does not respect context, a macro does.
For example, let's say your language had 'if' but not 'case', then it would be possible to write a case macro that in the end transforms at compile time into a bunch of ifs. Macros allows you to create new language syntax and express your intent more clearly.
For example, let's say your language had 'if' but not 'case', then it would be possible to write a case macro that in the end transforms at compile time into a bunch of ifs. Macros allows you to create new language syntax and express your intent more clearly.
Macros let you construct expressions at compile time (not run time). So one can basically create their own programming language in macros, which at compile time expands into the standard language (e.g. lisp). In this way they are powerful for being expressive and also for being highly efficient (as its compile time, not run time).
There are many other nifty things you can do as a result, but I am myself not that great. Paul Graham actually wrote the book on macros ('On Lisp'), he's legit :-)
There are many other nifty things you can do as a result, but I am myself not that great. Paul Graham actually wrote the book on macros ('On Lisp'), he's legit :-)
Most programmers STILL haven't experienced the absolute JOY of live coding languages.
https://news.ycombinator.com/item?id=28274069
https://en.wikipedia.org/wiki/Live_coding
https://news.ycombinator.com/item?id=28274069
https://en.wikipedia.org/wiki/Live_coding
I am extremely disappointed that the only example of a "weird language" is Lisp. These days — with Clojure, Common Lisp, Racket, Guile, Emacs Lisp, Chez Scheme, Fennel, etc. etc. — Lisp is hardly weird.
I'd love to see an expanded version of this article written by someone less focused on Lisp advocacy than Paul Graham seems to be.
I'd love to see an expanded version of this article written by someone less focused on Lisp advocacy than Paul Graham seems to be.
I agree. Lisp should be considered one of the most successful languages ever invented given the number of descendants it has sprout, as you mention. It's not a weird language at all.
Incredible projects like Guix, Emacs and Datomic are proof that Lisp is still alive and well and can create great things.
I would give Prolog or maybe Forth as examples of weird language that still have a "smart userbase".
Incredible projects like Guix, Emacs and Datomic are proof that Lisp is still alive and well and can create great things.
I would give Prolog or maybe Forth as examples of weird language that still have a "smart userbase".
Ummmm sorry to burst your bubble, all those languages you mentioned are considered part of the lisp family (I'm not sure what Fennel is, so can't comment), so actually you interpreted Paul's statement incorrectly - he didn't say Common Lisp or Scheme in particular, he said Lisp so was referring to all of them.
For what its worth, he's writing his own Lisps (Bel, Arc), is highly proficient in Scheme (just check out the book On Lisp), and is a true lisp polygot. I can't speak for him obviously but I don't think he has a super strong affiliation _just_ to Common Lisp.
For what its worth, he's writing his own Lisps (Bel, Arc), is highly proficient in Scheme (just check out the book On Lisp), and is a true lisp polygot. I can't speak for him obviously but I don't think he has a super strong affiliation _just_ to Common Lisp.
Apart from the technical benefits of languages like Lisp, OCaml, Haskell, these days one also needs to consider social aspects before one invests too much into a single language.
In terms of influence and earning potential, parochial and closed languages like Python are kind of a pyramid scheme:
The people who were there first occupy many of the top positions in industry, regardless of their contributions or competence. They actively harm and intrigue against dissenters, so be prepared to chant the religion of the day (which the powerful change from time to time).
This sort of thing cannot happen in languages with a standard and multiple implementations like Lisp or C++. Haskell and OCaml seem to be isolated from the most petty forms of intrigue because the average contributors are way smarter and care more about actual technology.
In terms of influence and earning potential, parochial and closed languages like Python are kind of a pyramid scheme:
The people who were there first occupy many of the top positions in industry, regardless of their contributions or competence. They actively harm and intrigue against dissenters, so be prepared to chant the religion of the day (which the powerful change from time to time).
This sort of thing cannot happen in languages with a standard and multiple implementations like Lisp or C++. Haskell and OCaml seem to be isolated from the most petty forms of intrigue because the average contributors are way smarter and care more about actual technology.
He's made this point before, more than once I think. But never so succinctly - well done.
The only thing his less succinct essays give you is his motivation for liking Lisp and macros in particular - it allowed him to build a successful business that gave him his big break in life.
The only thing his less succinct essays give you is his motivation for liking Lisp and macros in particular - it allowed him to build a successful business that gave him his big break in life.
>So if you want to expand your concept of what programming can be, one way to do it is by learning weird languages. Pick a language that most programmers consider weird but whose median user is smart, and then focus on the differences between this language and the intersection of popular languages. What can you say in this language that would be impossibly inconvenient to say in others? In the process of learning how to say things you couldn't previously say, you'll probably be learning how to think things you couldn't previously think.
or write compiler and experience the freedom
or write compiler and experience the freedom
Counterpoint is when you're spending cycles thinking about the weird language you're not spending cycles on creative programming, however adding chaos and restraint is a time-tested path to innovation.
Wouldn't you want a pl that makes that makes your 95% glue code easy to write, easy to code review, easy to debug in anger?
Stuff like "make this gql query, but with account spelled 'akkounte' b/c it's in language X, compute and add tax, then depending on the associated customer's SAAS, maybe stuff it into a REST call that has the account and tax as a CSV.
Or: convert this list of integers into f64, take the running average with a window of 5 entries (unless there's a holiday that week) then shove it into this C function that someone else wrote
Stuff like "make this gql query, but with account spelled 'akkounte' b/c it's in language X, compute and add tax, then depending on the associated customer's SAAS, maybe stuff it into a REST call that has the account and tax as a CSV.
Or: convert this list of integers into f64, take the running average with a window of 5 entries (unless there's a holiday that week) then shove it into this C function that someone else wrote
I don't get it. Lisp has been around for like 60 years. If these macros were an objectively better way to write code, why have they not taken over by now?
Because humans are funny creatures that take hundreds of years to convince about seemingly obvious (in hindsight) things? E.g. heliocentrism.
Good point, but you can't make money with heliocentrism.
OK, how about the flat-earth theory? Surely you can make a lot of money if you know the world is a sphere and how to get across it more efficiently than flat-earthers?
"99.5% of programming consists of gluing together calls to library functions."
This is also a statement about what kind of programming the speaker has done.
This is also a statement about what kind of programming the speaker has done.
I have a funny relationship with Common Lisp macros: I love the great book Let Over Lambdas, and also Paul Graham's coverage of this topic, yet, I hardly ever write macros myself.
For me, using different languages is a statement that I enjoy programming in different languages, and not a value judgement. There are so many great languages and I think some new languages like Swift and Rust are especially fun and useful.
For me, using different languages is a statement that I enjoy programming in different languages, and not a value judgement. There are so many great languages and I think some new languages like Swift and Rust are especially fun and useful.
We are moving towards a time where the entire notion of programming languages would be nothing more than compiling a proper dataset.
Programming languages will not become irrelevant but would be more akin to the fate of humanities, likely a personal passion. The economic value of learning programming languages in the distant future would be close to none.
Programmers should view languages as nothing more than a tool to perform some tasks.
Programming languages will not become irrelevant but would be more akin to the fate of humanities, likely a personal passion. The economic value of learning programming languages in the distant future would be close to none.
Programmers should view languages as nothing more than a tool to perform some tasks.
Why exactly? Current mainstream programming languages have just started to move away from the “fancy C” paradigm (only named functions, classes, imperative control flow constructs) to “prototype ML” paradigm (lambda functions, records, user-defined operators). These features make languages way more expressive (enabling things like SwiftUI), so understanding language nuances will become even more important as more advanced language features find their way into popular languages. Obviously you do not need to be a an expert on compilers, but most powerful languages need some time investment in order to be used at their fullest potential.
languages come with environments and libraries. Some environments are easier to use than others. For me, C/C++ is always painful because there is no standard build system or package manager and certainly nothing cross platform so integrating any random library is always work.
Conversely, I guess ruby, node, python, perl? all have fairly standard package managers so it's generally? easy to grab a library and it just works, no having to learn how to integrate it into your build system, only having to learn how to use its API
I do agree there are big things to learn from different languages. I haven't actually used F# but I did learn from this article (https://fsharpforfunandprofit.com/posts/designing-for-correc...), that I'm missing out on saving myself a ton of work by not using a better language that (a) builds new types for me easily (b) lets me switch on types easily.
I'm also mixed on lisp's macros. What I'd like is a language that can use itself at compile time. I hate that nearly every large C++ project integrates other languages (make, cmake, gn, python) somewhere in the build process. With a language that can run itself at compile time like lisp the build tools themselves can also easily be in lisp. I don't thing C/C++ though is particular good at simple string manipulation so using it to build itself sounds like it wouldn't be so nice. That might be another example where some languages excel over others in certain domains.
The downside to lisp macros is everyone builds their own DSLs and so I have to learn those DSLs. Of course maybe that's just the same as learning some C++ class hierarchy I'm unfamiliar or some template magic so possibly not a valid complaint. It's just a feeling from the lisp I've worked with.
Conversely, I guess ruby, node, python, perl? all have fairly standard package managers so it's generally? easy to grab a library and it just works, no having to learn how to integrate it into your build system, only having to learn how to use its API
I do agree there are big things to learn from different languages. I haven't actually used F# but I did learn from this article (https://fsharpforfunandprofit.com/posts/designing-for-correc...), that I'm missing out on saving myself a ton of work by not using a better language that (a) builds new types for me easily (b) lets me switch on types easily.
I'm also mixed on lisp's macros. What I'd like is a language that can use itself at compile time. I hate that nearly every large C++ project integrates other languages (make, cmake, gn, python) somewhere in the build process. With a language that can run itself at compile time like lisp the build tools themselves can also easily be in lisp. I don't thing C/C++ though is particular good at simple string manipulation so using it to build itself sounds like it wouldn't be so nice. That might be another example where some languages excel over others in certain domains.
The downside to lisp macros is everyone builds their own DSLs and so I have to learn those DSLs. Of course maybe that's just the same as learning some C++ class hierarchy I'm unfamiliar or some template magic so possibly not a valid complaint. It's just a feeling from the lisp I've worked with.
As a corollary:
“A language that doesn't affect the way you think about programming, is not worth knowing.” - Alan Perlis
“A language that doesn't affect the way you think about programming, is not worth knowing.” - Alan Perlis
Languages are (just) tools.
Pick and combine and switch as you go, tweak and create new ones if the availables aren't sufficient or are inaccessible. Worshipping and mantras are dead end.
It's that simple. (btw, a house is a tool to live inside it.. there was some Peter-Gabriel-wrote-music movie around this)
have fun
Pick and combine and switch as you go, tweak and create new ones if the availables aren't sufficient or are inaccessible. Worshipping and mantras are dead end.
It's that simple. (btw, a house is a tool to live inside it.. there was some Peter-Gabriel-wrote-music movie around this)
have fun
You can worship languages and build languages not because they are tools but because you have fun with them independent of them being tools.
For those who want to try out a quote unquote weird language, here is a cheat sheet I found helpful for Lisp: https://github.com/ashok-khanna/lisp-notes
So the Sapir-Whorf hypothesis[0] appears true for programming languages.
[0]: https://en.wikipedia.org/wiki/Linguistic_relativity
[0]: https://en.wikipedia.org/wiki/Linguistic_relativity
Russian translation: https://habr.com/ru/company/itelma/blog/575128/
If you think that 99.5% of programming consists of gluing together calls to library functions, you're also not making a statement about programming, but about the kind of programming you've done.
I new to this opinion, but I think more people should try to write non-trivial things in the Hindley-Milner family of languages. Just to get out of the rut.
Would Ada++ be considered weird xD?
http://www.adapplang.com/tutorial.html
http://www.adapplang.com/tutorial.html
99.5% of programming isn't actually about the coding at all. It is about breaking down a process to steps small enough to express in code. It is about figuring out what you want the app to do in the first place, and making it meets the goals of the end users. Or, to be more realistic, making it meet the goals that product owners have handed to you on behalf of the end users.
This whole article just feels like it is talking about code for its own sake, which I admit may be intellectually interesting, but has little to do with what we actually do day-to-day when building software.
Maybe that was really the point he was trying to get to - that building software is not the same thing as doing "interesting" code.
This whole article just feels like it is talking about code for its own sake, which I admit may be intellectually interesting, but has little to do with what we actually do day-to-day when building software.
Maybe that was really the point he was trying to get to - that building software is not the same thing as doing "interesting" code.
The irony is that a lot of "very popular" PLs are unergonomic for those 99.5% tasks, and sometimes worse when you take into account "best practices", like testing, documentation, CI/CD, version management (the tax rules will change!
But in november for these jurisdictions and September for these jurisdictions ) etc. PLs that are "clever" like pg advocates are often even worse.
Exactly. I don’t really like Java but if I were starting a business that required writing a CRUD backend, I would 100% chose a boring popular language like Java over something “smart”. Smart doesn’t scale - if there’s no tooling, bad library support, and no ecosystem, any gain you get by being clever gets erased by needing to reimplement the wheel. In many ways I’d say the language itself is one of the least important factors in choosing a language for a commercial project.
Java is one of the unergonomic popular languages I'm talking about. I'm never going back to that monstrosity.
I think he meant that
"there exist mental frameworks much more expansive for one's intellectual keyring than conditionals and loops («gluing [...] library functions») - for example «Lisp macros» -, so, «if you want to expand your concept of what programming can be» [presumably to acquire further hold of complexity, and new ways to navigate the solutions space], then explore weird languages with credentials".
"there exist mental frameworks much more expansive for one's intellectual keyring than conditionals and loops («gluing [...] library functions») - for example «Lisp macros» -, so, «if you want to expand your concept of what programming can be» [presumably to acquire further hold of complexity, and new ways to navigate the solutions space], then explore weird languages with credentials".
Paul Graham’s MO is using language as a startup secret weapon to outmaneuver established companies or lesser rivals (see his earlier writings about Viaweb). Spoiler they used lisp to implement multi tenant online store. He’s talking to startup founders, potential yc applicants. The reality is today, a lot of what they did in lisp is common functionality in every popular web stack out there.
In my view this programming language grand standing hasn’t been compelling for a long time, and now just seems kind of silly. Unless you’re working on really interesting problems, which the vast majority aren’t, judging from recent yc classes.
In my view this programming language grand standing hasn’t been compelling for a long time, and now just seems kind of silly. Unless you’re working on really interesting problems, which the vast majority aren’t, judging from recent yc classes.
Yeah it's kind of funny that there was a "controversy" in the very FIRST YC batch, when Reddit switched from Lisp to Python (~15 years ago!)
And there was data that showed that like 90%+ of YC startups use either Ruby (often Rails) and Python, including all the most valuable ones like AirBNB, Stripe, Doordash, etc.
So basically it's been 15 years since Ruby and Python have been acceptable (or even better) Lisps, according to PG's own metrics.
Ruby and Python both have garbage collection, REPLs, and enough reflection/metaprogramming to "compress" your code.
And there was data that showed that like 90%+ of YC startups use either Ruby (often Rails) and Python, including all the most valuable ones like AirBNB, Stripe, Doordash, etc.
So basically it's been 15 years since Ruby and Python have been acceptable (or even better) Lisps, according to PG's own metrics.
Ruby and Python both have garbage collection, REPLs, and enough reflection/metaprogramming to "compress" your code.
Here’s an article about the languages YC’s top startups use
https://charliereese.ca/article/top-50-y-combinator-tech-sta...
https://charliereese.ca/article/top-50-y-combinator-tech-sta...
About what they used not necessarily what they use today, the author does call this out.
For example it says Lisp for reddit but today it's Python.
For example it says Lisp for reddit but today it's Python.
In favor of Lisp I must say that having an image where you replace things instantaneously can be a big plus in exploratory workflows.
Same goes for Smalltalk in this regard.
I like Python a lot but I miss some kind of functionality like that.
Same goes for Smalltalk in this regard.
I like Python a lot but I miss some kind of functionality like that.
I think PG considered competitors hiring Python programers as "dangerous" or something like that.
Or just normal languages, used oddly: http://www.ioccc.org/
I think this applies to weird people as well. Some of the most interesting conversations I've had was with people that were misfits.
Languages to a programmer are like tools to a machinist. There's always some new goofy situation that requires yet another tool.
I heard this dude once claimed that lisp could've prevented 9/11. This seems like an elaboration on that claim! Javascript is kinda Lisp already and your glue languages do have their fair share of weirdness. Every industry and everything humans do is gluing crap together. The carpenter doesn't create his own synthetic wood or dig iron ore to make his own needles. He glues crap that was dug and cut with glued stuff.
This whole article is so short and generally vague as to be useless.
Does Paul Graham know Prolog or Wolfram or SAS?
If not then... isn't it ironic?
If not then... isn't it ironic?
Nim, Elixir, Rust, Zig, D and Jai would all like a word.
[deleted]
> 99.5% of programming consists of gluing together calls to library functions.
Actually, different languages do make this part different. Because you might glue together something other than "call", i.e. good functional languages have abstractions that blur the code and data boundary.
If all interesting ideas were at the expense of code reuse, learning new programming languages would be a fools errand. Improving the last mile of whatever you are doing is an O(1) improvement of total cost — it doesn't even show up in productivity expressed as a rate.
The real compelling belief behind programming languages is much more exciting, namely that we can express better ideas together in reusable ways, invest that productivity into better languages and rolls, and repeat that process ad infinitum. This is a crazy railgun of a concept.
Incidentally, this is why startups as PG likes are a failed way to advance technology. Startups, focused on a limited 5 year window and that last mile, are structurally incapable of working on generalized infrastructure. The proliferation of b2b over b2c on recent years belies that, but replacing the current ossified FOSS Monopoly (our commons) with b2b bulkanization could restore competition in the means of production, but that bulkanization will also prevent the code reuse that create enough payoff to power the continued reinvestmemt.
Tl;Dr PG sees good languages as a way to do one-off great man history-style heroic inventions, I see good languages as a way to unlock factorio-style continuous high capital investment.
Actually, different languages do make this part different. Because you might glue together something other than "call", i.e. good functional languages have abstractions that blur the code and data boundary.
If all interesting ideas were at the expense of code reuse, learning new programming languages would be a fools errand. Improving the last mile of whatever you are doing is an O(1) improvement of total cost — it doesn't even show up in productivity expressed as a rate.
The real compelling belief behind programming languages is much more exciting, namely that we can express better ideas together in reusable ways, invest that productivity into better languages and rolls, and repeat that process ad infinitum. This is a crazy railgun of a concept.
Incidentally, this is why startups as PG likes are a failed way to advance technology. Startups, focused on a limited 5 year window and that last mile, are structurally incapable of working on generalized infrastructure. The proliferation of b2b over b2c on recent years belies that, but replacing the current ossified FOSS Monopoly (our commons) with b2b bulkanization could restore competition in the means of production, but that bulkanization will also prevent the code reuse that create enough payoff to power the continued reinvestmemt.
Tl;Dr PG sees good languages as a way to do one-off great man history-style heroic inventions, I see good languages as a way to unlock factorio-style continuous high capital investment.
TL;DR - I only ever used LISP and nowadays I spend my time writing LISP dialects literally no one cares about but me.
"lisp..."
here we go again
here we go again
I prefer to use languages which have been stable for 20+ years.
Common Lisp, Prolog, APL, Fortran, C, OCaml, Ada.
Java, Python, Ruby, Haskell, C++, VB, C# too!
Common Lisp is ok then?
Such as Lisp?
Disappointed. I thought it was about languages such as Lojban /s
u'i xo'o xu la pygy ku jai logji .i pe'i so'i valsi .iku'i na'e logji
Strange that PG's site is served over port 80. Isn't he technical enough to have HTTPS on his site, surely? Anyway here's an Outline of it served over a secure channel:
https://outline.com/HY6aeR
https://outline.com/HY6aeR
Any reasons for PG's site to use HTTPS? Do you really want your ISP not to eavesdrop what PG has written about Lisp? It is slower than HTTP if a connection is really poor. It may be important for someone who wants to read anything while travelling.
This is one of the value propositions of language. It's one of the ways we learn new things, and thus become more capable of doing valuable work as people.
Criticisms of this essay in comments so far have seemed to fall into these buckets:
(1) and (3) are side points, unrelated to thesis. (2) is the interesting one, and at the heart of what the essay talks about.
I've always been in the pg camp on this one. Sure, systems are the thing, we can't be purists, etc -- but saying that languages don't matter, for us, would be like rocket engineers saying that materials don't matter.
If you're building a table, you can make it out of almost anything; a table is a solved problem. Wood, carbon fiber, steel.
But at the limits of what's possible, like a rocket, the material's properties, limitations, and weaknesses in extreme circumstances matter.
You can definitely imagine that important things are happening, in the maker's mind, when they start working with a new material, seeing what others are able to do with it, seeing how the making process is easier, or what steps are unimportant/unnecessary now vs. in their usual materials. And that informs their thinking, going forward, about what's possible in systems they might build.