11 ms·
We need less powerful languages (2015)
- tsbinz 6y agoPrevious discussion: https://news.ycombinator.com/item?id=10567408 https://news.ycombinator.com/item?id=10567408 - title probably should have a (2015)
- qz2 6y agoThis is why I like Go and hope they don’t ruin it with a poor generics implementation. It fits in my head. My other usual language is C# which is starting to feel like a London bus at rush hour with feature burden.
- jcelerier 6y agoThe alternative to Go having generics is not "a simpler language", it is "people reimplementing generics with their own code generators" à la https://www.reddit.com/r/rust/comments/5penft/parallelizing_enjarify_in_go_and_rust/dcsgk7n/ https://www.reddit.com/r/rust/comments/5penft/parallelizing_... You may not want more powerful languages, but as soon as a single person wants the power, they'll craft it themselves no matter what (and then it may end up being one of your dependencies :-) and the effect will be pretty much the same - you'll have to work with generics anyways, but with homebrew instead of "official" ones). So I am very very not convinced by the thesis exposed in that article - people will use whatever tool they find to automate what they think is automatable in the process of writing programs, even if that means creating ad-hoc AutoHotkey scripts that type repetitive macros according to a certain pattern (true story :-)). Having more powerful languages means that you have to spend much less time trying to inspect whatever eldritch horror combination of tool the people before you used there as you just need to check the language docs or StackOverflow.
- qz2 6y agoI just want nice generics not scary ones :) I’ve managed to generic myself into a corner before with type constraints in C# as an example.
- kungito 6y agoC# is a really bad example to say Go is good. I always felt people were too lazy to explore proper alternatives. People don't like something in C# or Java and jump to go because you can learn it in a day instead of investing 2 days to write in Rust or Erlang or Haskell or Ocaml or whatever. Go is just a better C with coroutines
- qz2 6y agoA better C with coroutines is what I wanted.
- vp8989 6y agoIt's certainly possible for individuals to swim against the current. I am not a Go programmer but all the Go open source code I have read has been brutally simple and easy to consume. I don't think that's a coincidence.
- valyala 6y agoI'm a Go programmer and I can confirm that Go code (both written by me and by anybody else) is easy to read, debug and refactor. This is thanks to simple yet powerful Go syntax, which doesn't allow constructing implicitly executed code. I.e. it doesn't support the following "features" from other programming languages, which instantly increase code complexity because it becomes impossible to understand the code by just reading it top down: * Operator overloading * Function overloading * Constructors and destructors * Implicit type conversion * Implicit types (classes) Go also doesn't support type templates and function templates yet (aka generics or contracts). This also plays significant role in easy-to-read Go code. P.S. I wrote many packages and apps in Go during the last 10 years [1] and I absolutely love Go! Check out my last project in Go - VictoriaMetrics - fast time series database and monitoring solution [2]. [1] https://github.com/valyala/ https://github.com/valyala/ [2] https://github.com/valyala/VictoriaMetrics https://github.com/valyala/VictoriaMetrics
- somebodynew 6y agoAs a C++ developer, highlighting the lack of destructors made me curious how resource closure is typically handled in Go. A brief review suggests that it is often handled using a "defer statement", which accumulates a stack of statements to be executed when the function returns, to execute a 'close()' method. While I can see some benefit to the explicit appearance of "defer" in the source code, I think it is outweighed by the risk someone forgets to write it (or tries to close something without defer but misses a path). The execution of a destructor is inevitable and automatic.
- valyala 6y agoThe main issue with destructors is that it is impossible to determine by reading the code which destructors in which order at which lines may be called. Actually, destructors can be called on every line of C++ code because of exceptions. This complicates understanding code flow and makes almost impossible to write exception-safe C++ code, which properly releases resources at any exception. While Go supports exception-like panics, they are mostly used for really exceptional cases, when the program cannot proceed further, such as out-of-range slice accces or nil pointer dereference. Almost all these cases are triggered by programming errors, which must be fixed after the panic occurs. Traditional error handling is performed explicitly in Go instead of relying on panics - the error is checked explicitly after function call. This simplifies code reading and makes easy to spot cases with missing or incorrect error handling. These tasks are almost impossible with try/catch error handling.
- deleted 6y ago[deleted]
- boltefnovor 6y agoSlightly off topic but collaborative programming seems to be a big unsolved and ignored problem in programming. A recent HN discussion on microservices had people saying (paraphrasing) “it’s the only way we can collaboratively build software”. Programming languages currently seem to be built for programming as a solitary activity. Seems to me that programming languages could be designed with the aim of solving the large scale collaboration problem.
- AdieuToLogic 6y ago> Slightly off topic but collaborative programming seems to be a big unsolved and ignored problem in programming. No, it isn’t. C, C++, Unix, and even Windows, have long sinced solved what you describe as being ignored. See also CPAN[0]. 0 - https://www.cpan.org/ https://www.cpan.org/
- 0x445442 6y agoNot sure why you're being down voted here. I see why the CPAN reference is relevant but maybe it in particular is viewed as an issue because of Perl's TMTOWTDI. I take your comment to be that code modularization and sharing was a problem solved long ago and that most collaborative programming issues are more social than technical.
- tluyben2 6y agoMaybe I misunderstand you (and I definitely misunderstand people who advocate micro-services like everything and the kitchen sink), but aren't we collaborating on enormous projects for many years already? Linux, Windows, all large open source projects (without them being micro-services) etc. But again, maybe I misunderstand what you mean.
- andrewjl 6y agoWhat's a possible way to design a language for collaboration besides encouraging ever more fine-grained modularization and code reuse? I can see collaborative debugging and sharing of environments, especially with web services, as possible avenues. Observability as well. I'm having a harder time coming up with specific language features though.
- AdieuToLogic 6y agoWhile semantically weak languages are appealing at first, all they end up doing is encoding the intrinsic problem domain complexity implicitly. This results in “brittle code” and the inability to adapt. In short, powerful languages exist because they need to exist.
- pydry 6y agoThis is a sign of a semantically weak language used in the wrong place.
- orbital-decay 6y agoWhich is inevitable, I guess. If it can be abused to make complex systems, it will be abused.
- pydry 6y agoIt's not inevitable. Carefully ringfencing the capabilities of a weaker language and making sure that it is as powerful as is necessary enables you to have something conceptually simpler, easier to maintain and easier to read while maintaining the necessary level of expressive power. There are lots of examples where DSLs achieve this goal and the result is really nice and, unfortunately, a lot where they don't.
- maweki 6y agoThat's not true though. SQL is not computationally complete. It does abstract over the complexity of access to relational data. And it is still used and useful. SQL is also not automatically brittle. There is a problem of a language gap, a mismatch between SQL structures and internal types, and all in all maybe a gap in typed code and unit tests. That does not mean you should implement your own database.
- deleted 6y ago[deleted]
- 6y ago
- maweki 6y agoIt's fun to think about useful languages that are not computationally complete. I am writing my PhD thesis about Datalog used as a general purpose programming language, specifically for robots and microcontrollers. And you know what? You don't need to be able to simulate a Turing machine for a lot of tasks. On the other hand, you have guaranteed termination. Excel (without scripting) uses a terminating (and therefore incomplete) model of computation and it still manages to do a lot of heavy lifting in the real world. I wholeheartedly agree with the author that declarative languages and Domain specific languages are great, and even if they do not have a (hidden) embedded lisp, they can still be useful. Once you are in a computationally complete language (and you don't just use a subset of language features that is "easy"), most problems are generally undecidable. Turns out, that's a bad property for static analysis.
- otabdeveloper4 6y agoShameless self-promotion: https://tkatchev.bitbucket.io/tab/index.html https://tkatchev.bitbucket.io/tab/index.html
- YeGoblynQueenne 6y ago>> It's fun to think about useful languages that are not computationally complete. I am writing my PhD thesis about Datalog used as a general purpose programming language, specifically for robots and microcontrollers. Interesting. What is the general area of your thesis (your field of research that is)? I study approaches that learn datalog (or Prolog) programs from examples. Good luck with your thesis!
- maweki 6y agoI have a variant of Datalog with an explicit model of time (like statelog or dedalus) and action atoms/external atoms from HEX (asp). Then I extract partial programs that provably use finite memory and construct finite state machines. Combined with a bit of runtime framework, I can compile to C which I actually run on arduino or lego ev3.
- 6y ago
- jiggawatts 6y agoFor over a decade now, I've been pondering a "perfect" language. Of course, such a thing is impossible, because we're always learning, and we can always do better, but it leads to some interesting avenues of thought. We can claim that certain concepts are mandatory, which can be used to reject languages that can never meet our ultimate requirements. For example, a common complaint is the "impedance mismatch" between, say, query languages such as SQL or MDX, and object oriented languages such as Java and C#. Similarly, JSON has become popular precisely because it has zero "mismatch" with JavaScript -- it is a nearly perfect subset. This leads one to the obvious conclusion: An ideal language must have subsets, and probably quite a few. If it doesn't, some other special-purpose language would be forced on the developers, and then our ideal language isn't perfect any more! The way I envision this is that the perfect language would have a pure "data" subset similar to JSON or SQL tables, with absolutely no special features of any type. The next step up is data with references. Then data with references and "expression" code that is guaranteed to terminate. Then data with expressions and pure functions that may loop forever, but have no side-effects of any kind. At some point, you'd want fully procedural code, but not unsafe code, and no user-controlled threads. At the full procedural programming language level, I'd like to see a Rust-like ownership model that's optional, so that business glue code can have easy-to-use reference types as seen in C# and Java, but if a library function is called that uses ownership, the compiler takes care of things. You get the performance benefit where it matters, but you can be lazy when it doesn't matter. Interestingly, C# is half-way there now with their Span and Memory types, except that this was tacked on to an existing language and virtual machine, so the abstractions are more than a bit leaky. Unlike Rust, where the compiler provides safety guarantees, there are a lot of warnings-to-be-heeded in the dotnet core doco. TL;DR: We don't need separate simplified languages, we need powerful languages with many simpler subsets for specialist purposes.
- shmageggy 6y agoI agree. For an extreme example, by taking an extremely restricted subset of Python, Numba is able to get crazy speed-ups, automatic compilation to GPU kernels, etc. I've been waiting for someone to implement the subset of Python that allows for no GIL and huge speedups by cutting out some of the dynamic stuff. I'd bet 99% of the code I write would fit in that subset.
- mlang23 6y agoIf you read this, you should probably also read this very recently blog post[1] by Neil Mitchell. http://neilmitchell.blogspot.com/2020/11/turing-incomplete-languages.html http://neilmitchell.blogspot.com/2020/11/turing-incomplete-l...
- Patient0 6y agoThanks I was just about to post the same thing
- slx26 6y agoI agree with the analysis of the problem, but disagree with the solution: while it's true that increased expressiveness in a system tends to increase the cognitive burden of understanding it, what you want is to maximize expressiveness at the smallest cognitive cost possible, not to limit expressiveness. I mean, sure, sometimes it's a good trade-off to limit expressiveness, but most often than not we could make a lot of progress by making certain features simpler, more accessible, or following a model that's easier to understand for humans (matching better human intuition, or more accessible, so it's easy to get easy things done, and you are not hit by complexity unless you really need it). I argue that we can still make a lot of progress and create better models for many things related to programming languages, including (but not limited to): unicode, interprocess communication (and in general compatibility of data across programs and languages), access to graphics and audio APIs, pass by value vs pass by reference, mutability vs immutability, transparency of memory models, cross-compatibility, database accessibility, etc.
- pydry 6y agoThat's a nice idea in theory but making something Turing complete with loops and conditionals etc. simply can't have the same low cognitive cost as decent languages which do not have such features.
- Geminidog 6y agoThere are problems outside of cognitive burden. More expressiveness actually leads to a higher error surface area. The more power you have the more opportunities you also have to shoot yourself in the foot. Removing mutability as a feature from a language also removes all mutable logic errors from a language. Removing null values from the language removes all null related runtime errors from a language.
- hliyan 6y agoI sometimes wonder why syntax (or in the case of this article, the "expressiveness") and runtime features of languages often come in package deals. Shouldn't it be possible to connect a preferred syntax system to a preferred compiler/runtime system? In other words, more modular programming languages?
- krab 6y agoI think that's what we see with a variety of JVM languages and to some extent with LLVM.
- munchausen007 6y agoClojure is not bad, sadly all “new” programming languages now just try to reinvent Lisp or fortran its a bit disappointing.
- augustk 6y agoThis comment section is not complete without mentioning Oberon, designed by maestro prof. Niklaus Wirth. First appearing in 1988 it may not be a new language but it has gone through several simplifications and the latest revision is from 2016. The programming language Go borrowed quite a few ideas from it although Oberon is simpler and has an orthogonal feature set. How many programming languages are defined in 16 A4 pages including examples? https://www.miasap.se/obnc/oberon-report.html https://www.miasap.se/obnc/oberon-report.html
- timbit42 6y agoScheme's specification is smaller than that.
- blandflakes 6y agoWe also have attempts to reinvent ML, more recently!
- jstimpfle 6y agoI 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...
- Geminidog 6y agoIt's well known that less power leads to less opportunities to shoot yourself in the foot. The article talks about "less" power from a qualitative perspective like how "Go" is less "powerful" than "C++" because the language primitives are less dense. It also talks about turing completeness as well but still from a qualitative perspective. There is actual benefits in removing fundamental core features of programming. You can remove iteration to make something not turing complete but before that you can maintain turing completeness while removing certain core programming features. In fact There is an entire style of programming that removes these core features and is "less" powerful and "less" expressive as well. It is called functional programming. Functional Programming is simply the same thing as imperative programming only without the power of mutability. No variable reassignment. No looping. The strange thing is I always hear people talk about things how functional languages like say... Haskell are more expressive and more powerful than imperative languages. They are technically wrong. These languages are LESS powerful. So yeah the author is really talking more about cognitive overload of say something like C++ but at a more fundamental level making our core programming model less powerful actually has some interesting benefits outside of just "cognitive overload" Modules in functional programs (called combinators) are the most modular primitives available in all of programming and FP pushes the programmer into encapsulating his logic into these primitives leading to actually more modular and better constructed programs. The structure of programs changes for the better when things are made less powerful.
- GavinMcG 6y ago> The strange thing is I always hear people talk about things how functional languages like say... Haskell are more expressive and more powerful than imperative languages. They are technically wrong. These languages are LESS powerful. You're just arguing from different definitions, here. In fact, it's worth checking whether your definitions match up whenever you find yourself saying "technically" since it suggests you're applying a particular definition.
- Geminidog 6y agoSo tell me what do people mean when they say Haskell is more "powerful"? Tell me the definition. I don't think there is a different definition. I think it's just that most people aren't sure why Haskell is "better" than say C++.... They know it's "better" but they can't put their finger on "why" and they mistakenly attribute it to a more powerful language without thinking that Haskell is actually less powerful in every possible way. The set of all things you can do to your computer with Haskell is less than the things you can do to it with C++. If you look at it from every possible angle you will see that either you do less with Haskell or Haskell makes it Much harder to do certain things. There's really no angle where you can say Haskell is more powerful than C++ unless you really stretch the definition which I'm sure your subsequent reply (if you reply at all) will be doing.
- gumby 6y agoThis was an explicit design goal of go. I've generally assumed that the goal of the GoF (design patterns) was the same: with a canonical and prescribed set of ways of doing certain things you're less likely to get into trouble and and your code more likely to be understood by another reader. While I believe the issue of cognitive overhead due to increased optionality (i.e. power in this case) the converse is also true: the additional expressive power of a language takes the place of an IDE and permits more compact code which can be easier to understand than the more diffuse and boilerplate-laden code of a less expressive language, where the scaffolding can obscure the place where the work is actually done.
- yogthos 6y agoOne of the things I appreciate about Clojure is its simplicity. Before I started working with it, I was of the mindset that having more features in a language was important because that's what made the language more expressive. After having worked with Clojure I realized that you can have a small and focused language that's incredibly expressive without being overwhelming. A well designed language will allow you to apply a small number of common patterns to a wide range of problems.
- blandflakes 6y agoClojure is really great this way. My fumbling about with argument order aside, I only had a couple complexity problems when I was writing it: 1. Holy hell, I always have to look up examples for the ns macro and imports. 2. Protocols, records, and reifying... there's a flowchart out there for this but it frustrated me that I didn't Just Know. Scala has a similar thing for this where sometimes Eta expansion happens and sometimes it doesn't, and you just need to know where you can use sugar.
- johnisgood 6y agoI am not going to stop coding in Forth!
- bliss 6y agoI interpret this to mean that human brains work best with constraints, artists do this all of the time, constraints are great
- sideeffffect 6y agoInterestingly, just recently, Neil Mitchell has published an article claiming that this is a fallacy and in practice, people are forced to back-pedal on it. Ban recursion and unbounded loops. Proclaim the language is "Turing incomplete" and that all programs terminate. Declare that Turing incomplete programs are simpler. Have non-technical people conflate terminate quickly with terminate eventually. Realise lacking recursion makes things incredibly clunky to express, turning simple problems into brain teasers. Add recursion. Realise that the everything is better. https://neilmitchell.blogspot.com/2020/11/turing-incomplete-languages.html https://neilmitchell.blogspot.com/2020/11/turing-incomplete-...