5 ms·
I tend to think that languages aren't that important. A basic imperative languages has you covered for the vast majority of tasks. Having spent some time chasin
by jstimpfle 6y ago
I tend to think that languages aren't that important. A basic imperative languages has you covered for the vast majority of tasks. Having spent some time chasing languages, I've come to think that there is no silver bullet, and while looking at ongoing efforts is inspirational and insightful, switching languages is no fast path towards solving hard problems.
What we have are in fact imperative state mutating machines. A language can pretend otherwise by trying to encapsulate the associated complexity of translating between these models. Or it can just let the programmer do it.
Specialized languages have syntax that is more streamlined towards specific domains, but they lock the programs into their narrow world views, requiring possibly more effort than what was saved to shovel your way out.
Looking at some really good programmers it is remarkable how elegant and efficient (measured in LOC) they can do some things in simple procedural languages that one would normally think are poster child use cases for some of the more limiting approaches and techniques (GC, DSL, OOP/FP/whatever).
For some balance, I do agree that ergonomics around tooling matters a lot. I believe this requires similar tradeoffs - a narrow world view can make it easier to write tools that understand the structure of the code, and can assist in the development. For example, C is a pain to write tooling for. On the other hand, it is still one of the faster languages to compile and build because there are fewer tasks that it tries to free the programmer from.
- waynesonfire 6y ago> Having spent some time chasing languages, I've come to think that there is no silver bulle It must be your IDE then... Have you tried VS Code? Joking aside, I agree with you and have experienced the same insight. It has since helped me focus on what matters as I attempt to solve problems a bit outside my abilities.
- chriswarbo 6y ago> I tend to think that languages aren't that important. > switching languages is no fast path towards solving hard problems If you're talking about switching from one mainstream, general purpose language to another, then I mostly agree. Some tradeoffs can be definite wins for particular domains, e.g. for Web development Go is almost always a better choice than C (in terms of memory management, string handling, buffer overflows, etc.). Other choices can just shift problems around, e.g. in Python it's easy to get something running, but it requires a lot of testing to avoid errors. However, when it comes to domain-specific, non-general-purpose languages I strongly disagree! There are certain problems that are incredibly difficult to solve (often undecidable) in the context of some generic language; which become trivial when the language is designed with that problem in mind. For example: - Incremental computation https://inc-lc.github.io https://inc-lc.github.io - Resource handling https://en.wikipedia.org/wiki/Substructural_type_system https://en.wikipedia.org/wiki/Substructural_type_system - Client/server/DB consistency https://en.wikipedia.org/wiki/Ur_(programming_language) https://en.wikipedia.org/wiki/Ur_(programming_language) - Ruling out unwanted effects https://deno.land/manual@v1.0.0/getting_started/permissions https://deno.land/manual@v1.0.0/getting_started/permissions https://en.wikipedia.org/wiki/Purely_functional_programming https://en.wikipedia.org/wiki/Purely_functional_programming - Hard realtime timing https://en.wikipedia.org/wiki/Esterel https://en.wikipedia.org/wiki/Esterel There are a load more examples on sites like http://lambda-the-ultimate.org http://lambda-the-ultimate.org Such languages certainly introduce a bunch of problems, like lack of libraries, but they might be the difference between something being difficult, or it being impossible. Another thing to keep in mind with domain-specific languages is that it's often useful to "embed" them inside some other, general-purpose language. This lets a DSL avoid the need for its own parsing, tooling, etc. For example https://wiki.haskell.org/Embedded_domain_specific_language#Examples_of_Domain_Specific_Languages https://wiki.haskell.org/Embedded_domain_specific_language#E... https://beautifulracket.com/appendix/domain-specific-languages.html https://beautifulracket.com/appendix/domain-specific-languag...
- jstimpfle 6y agoI am well aware of most of the efforts you've linked, and those are what my comment was about. > There are certain problems that are incredibly difficult to solve (often undecidable) in the context of some generic language That statement is objectively wrong. Was the use of undecidable here intentional?
- chriswarbo 6y ago> That statement is objectively wrong. Was the use of undecidable here intentional? It was intentional, and here's a proof (sketch) that it's objectively right. Consider the question of whether a procedure's return value (if it halts) will be a string? We can prove that this question is undecidable in Python, by considering procedures of the form: def foo(): if bar(): return "hello" else: return 123 The answer to our question will be true if 'bar' returns a truthy value (or doesn't halt), or false if 'bar' returns a falsy value. Since the truthiness of bar's return value (if it halts) is a non-trivial property of the (partial) function it implements, it is undecidable for arbitrary 'bar' (via Rice's theorem). QED. Yet in Java this question is trivially decidable, since all return values must have the same static type; i.e. procedures like the above aren't valid Java programs, and this can be determined statically, so they present no difficulties. In this particular case, Java's static type system makes this a trivial question about the procedure's syntax; rather than a non-trivial question about the (partial) function it implements. This same argument applies to all sorts of DSLs too. Many use a similar type-based approach, e.g. linear types forbid expressions like 'if (bar()) { free(myMemory); }'. Others work by providing an extra semantics, alongside the normal result-calculating one; e.g. incremental lambda calculus has a semantics for calculating changes; differentiable languages (e.g. provided by machine learning libraries) have a semantics for calculating derivatives; probabilistic programming languages have a semantics for sampling and induction; etc. We generally can't apply these semantics to other languages, due to the existence of language constructs which don't exist in that semantics (e.g. exceptions, or GOTO, or whatever).
- jstimpfle 6y agoI thought you were talking about the actual problems - the ones that you use a programming language to solve. But here it's really comparing apples vs oranges. Of course you can find questions that don't have a definitive answer for programs (or program parts) written in any programming language. Much more so in a less rigid language. That doesn't say anything about problem solving abilities, though. > This same argument applies to all sorts of DSLs too. Many use a similar type-based approach, e.g. linear types forbid expressions like 'if (bar()) { free(myMemory); }'. That's nice, but the concern I expressed in my original post is - at what cost?