4 ms·
> 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
by 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?