9 ms·
Should programming languages be safe or powerful?
- deleted 2y ago[deleted]
- kazinator 2y agoProgramming languages should be safe by default, except in clearly delimited sections of code (as small as a single expression) where the programmer requests less safety. Safety is the property that erroneous situations are intercepted and diagnosed, rather than running off with incorrect results or behaving unpredictably. It can be a continuum based on the number and kinds of situations that are treated safely.
- doublerabbit 2y ago> Programming languages should be safe by default I disagree. Programming languages should teach you how to program safely. It's the same with construction, here's your brick. You can either use cement or not. Both will build a tower but one will topple and one will not. Programming is the same. Here's your compiler, program your tower without garbage collection and watch it topple. If you don't wish to learn how to program safely then choose a language that does it for you. But don't moan because you refuse to learn how to program safely. Most languages are derived from C anyway so your coding in C but just in the way how the developer wants you to code in C.
- kazinator 2y agoYou can't program safely in an unsafe language. You can program correctly so nothing bad happens, but it's still unsafe code. Just like a tightrope walk between two buildings without a safety net is unsafe even if you're very good at it and never fall down. A programming language has multiple safety modes and is safe by default could be used as a tool for teaching a range of concepts.
- doublerabbit 2y agoIf nothing bad happens when something unsafe happens then code is safe. If you don't use the feature set that declares the code as unsafe then it's safe. A knife is unsafe, but when a chef uses it correctly it's safe. As is code. It's only when you use syntax incorrectly does it become unsafe. A tightrope is still unsafe and now you're relying on the safety net to catch your fall. What declares the safety of the safety net? However both standards should apply. But as programming is now more rapid rather than a dedicated skill, prototyping of new code landing in production. We are tend to rapidly program ignoring the correct way to program and now relying on the language to do the checkup. That itself is still just as unsafe and now passing the buck of lousy code on to as a fault of the language itself. Safety doesn't come from the language. It can, mainly it comes from the code. Use syntax incorrectly and you have unsafe code in any language.
- kstrauser 2y agoWe need to accept that humans are not capable of writing safe code in unsafe languages. Brilliant, dedicated, diligent programmers still write busted C code all the time. If the OpenBSD team still makes critical mistakes today, what hope do the rest of us have?
- kazinator 2y agoIt is selection bias at work. Only programs in which an issue is found are the targets of reports like CVE.
- kazinator 2y agoAlmost all code in an unsafe language will misbehave on bad inputs. The program is put together in a way such that it avoids stepping on those cases. For instance, by validating and diagnosing inputs so as to avoiding executing that code. You would think that a program which has been deemed "correct" cannot misuse any of its own code with undefined results. Alas, that is not the case. Such a program is called a "robust" program. A correct program is one that meets all of its functional requirements; does eveything right with correct inputs. Whether robustness is required for correctness depends entirely on how the program is specified: does the specification explicitly call for robustness (grace on bad inputs) or not? For instance, the memcpy() function in your C library is a correct program (hopefully). When you use it correctly, it does its specified job. Most implementations of it are not robust, though. Most memcpy functions cheerfully accept overlapping objects and do something, and are easily crashed by bad pointers. Robustness is related to security. It is often in the areas of the software that lack robustness that attackers find exploitable surfaces! Safe languages contribute robustness to programs. It's as if the requirements were added to the spec of every program. The programmers working with these languages, and their users, get accustomed to this and then expect robustness out of programs as a tacit requirement. Note that an incorrect program can be robust! A program that due to some coding mistake or misunderstanding calculates the wrong thing for correct inputs (not meeting a functional requirement) can still be impervious to misuse. So in a nutshell, safety is more concerned with robustness than correctness. That's why we can talk about languages and libraries being safe, in the absence of a program being specified. Those tools are still safe when they are used to put together a program that doesn't meet its functional requirements. The safety mechanisms in safe languages may not be enoguh for some desirable level of robustness. Users don't want programs to stop with a diagnostic message because they gave bad inputs. Modern safe languages have tools like exception handling. Some wrongheaded programmers think that just because the default robustness provided by safe languages is not always good enough for many kinds of professional or industrial applications, those robustness features are therefore not worth it. ("If I'm going to have to check for bad inputs and take special action, what's the use of the language doing the checking robust.") The safe language can make it much easier to do that, though. For instance, we can often let an entire module execute freely and just catch an exception in one place. Say, inside a CAD program, some calculation over a model could divide by zero. We just catch that somewhere, put up a dialog (or log something in a log window) and the CAD program keeps running.
- nicoburns 2y ago> > Programming languages should be safe by default > I disagree. Programming languages should teach you how to program safely. One of the best things about safe-by-default languages is that they do teach you to program safely! If your program fails to compile you then have to go and find out why, and that's a fantastic learning opportunity. In languages where there are no guard rails, it's much more difficult to work out what you don't know that you don't know.
- doublerabbit 2y ago> In languages where there are no guard rails, it's much more difficult to work out what you don't know that you don't know. I don't disagree. But the above is what's not taught anymore. Which what Computer Science taught you about; a subject that has now been watered down. It's great to have languages that have guard rails. And sure helps you learn shaving time off your project/life. However if you're using syntax you have no idea about that can cause system damage than the fault is on the programmer not the language. It exists to be used, but use it wrong it becomes unsafe. I know i'm not right, but i'm not wrong either. It's a double edged sword.
- kstrauser 2y agoHas computer science ever been primarily about programming? I don’t think that’s the case.
- nicoburns 2y ago> It's great to have languages that have guard rails. And sure helps you learn shaving time off your project/life. It also means that beginners can reasonably use the language for production projects. Including those who have never had the opportunity to study computer science. To me, it reflects poorly on a language if pretty much the only reasonable way to learn it such that you can use it safely is via computer science course (or another similarly structured environment - perhaps a work place with senior mentors). Of commonly used languages, that's pretty much true only of C and C++.
- kazinator 2y ago
- CJefferson 2y agoLet's compare to building (this is in the UK, but I think most countries have similar rules). If someone asks you to build a house, you need to make a plan, and get it signed off. There are lots of rules on what you can, and can't do. If you build a house without cement, by just piling bricks up, you will get fined and be told to take it down and build it again. If that house you badly built falls down and kills someone, you go to jail.
- rikroots 2y agoIn theory. We're still waiting to see if anyone will be prosecuted for the Grenfell Tower fire ... https://www.bbc.co.uk/news/articles/c6pp46z93k6o https://www.bbc.co.uk/news/articles/c6pp46z93k6o On the software front - there may finally be some progress on prosecuting the people responsible for the Horizon system, whose faults directly led to the Post Office scandal? https://www.bbc.co.uk/news/articles/cvgr19lwgv0o https://www.bbc.co.uk/news/articles/cvgr19lwgv0o
- CJefferson 2y agoYou are right that there are terrible issues in building (Grenfell being an obvious, terrible example). But I'd say, in general, building is in a much better state. There are fairly standard rules, which are mostly followed, and most building stay standing, year after year, without the need for constant maintence. On the other hand, software is still really pre-fire of london (at best) in terms of quality and standards.
- yearolinuxdsktp 2y agoI bet we disagree on what unsafe means. Many here think tåhat shipping a non-final/open/inheritable class is unsafe. I think doing so stunts your code base’s and ecosystem’s evolution. And when push comes to shove and you have to address an issue in a 3rd party library, and you are unable to override a single thing that would fix your problem because everything is closed by default, then you will tell your manager it can’t be done, and serious money or opportunity will be wasted and customers will suffer for longer, because you are coding in a really safe language. Is this progress for humanity? I think not!
- mike_hearn 2y agoThat's a slightly different issue. I don't think people consider visibility attributes under the rubric of safety, usually, except in sandboxed contexts. That's more a problem of build tooling. It should be possible to modify visibility/finality levels in libraries as you download them. Gradle can do something like this with some work, but someone should make a plugin to automate it. That way the upstream can set things private/final/sealed as correct for their API guarantees and design, and downstream can apply hacks to open things up if that's easier than forking the source code, and there's a single place in the build system that collects all the places where there's a mismatch.
- yearolinuxdsktp 2y agoJeez what an ugly option.
- kazinator 2y agoI've made it explicit what I believe safe means. I could discuss it in more detail, but I won't be changing my definition. I would never do such a barbaric thing as adding a non-inheritable class to an object system. Or, if I were convinced to, it would be purely for performance, not as a way of restricting the programmer; i.e. for speeding up things due to the compiler knowing that the class is final.
- tasuki 2y agoComposition over inheritance! (If you absolutely must do OOP)
- buggy6257 2y agoFor those skipping to comments based on title alone, this isn’t really much discussion about a trade off. It starts that way and then goes “but with my favorite language you can have both!” And spends 3/4 of the article telling you about it. The most value from this article is the clickbait title yielding some interesting discussion from people on that question outside of the actual article contents. This article isn’t bad but the name is terrible and a bit clickbaity
- zahlman 2y agoSince we're avoiding clickbait: the language in question is Racket.
- zelphirkalt 2y agoHa, funny, because I thought: "Both, of course. Like for example Schemes." and while Racket is not a Scheme according to the maintainers, it certainly shows the similar safety and power that other languages like it show.
- packetlost 2y agoIt started as a Scheme and one of it's #langs implements a Scheme these days, but Racket itself is strictly more powerful than Scheme.
- roca 2y ago> If you want to write device drivers, then C is great for you. No, it really isn't. It's 2024, people who should know better should stop saying this.
- yjftsjthsd-h 2y agoAlright, I'll assume you know better; what should we use? Preferably on a variety of OSs; ex. I imagine you can write Windows or Haiku drivers in C++, but I'm only aware of C being an option in any BSD, and Linux support for anything but C is spotty (obviously Rust is making headway, but last I heard you could only write certain kinds of drivers using it as the underlying support is built out).
- samatman 2y agoIf your platform is supported by LLVM, Zig is worth serious consideration. It is able to target any of the operating systems you mention, from any of the operating systems you mention. Linking to the syscall interface / libc / C libraries is straightforward, exporting functions which respect the local ABI is quite simple.
- whobre 2y agoLatest release of zig is 0.13. I guess it’s fine for hobby projects and learning…
- samatman 2y agoIt's true that, as a pre-1.0 language, choosing Zig means taking on the implementation burden of changing code to keep up with language changes. But it's already being used in production in a surprising number of places. Wanting to wait until 1.0 to get started is a respectable choice. I prefer to get a head start, compile against master every few weeks, and change what needs changing.
- thefaux 2y ago
- AzzieElbab 2y agotldr - should your language be Lisp or Haskell?
- lizzas 2y agoHard and soft tacos :) Racket is both.
- sourcepluck 2y agoCould you elaborate? Motivation: looking at racket these days, and have ordered "how to design programs" in the library :)
- spintin 2y ago[dead]
- CodeWriter23 2y agoI think the emergence of the LLM-integrated IDE can be leveraged to transform a powerful yet unsafe language like c into a safe language.
- superb_dev 2y agoHow? I don’t see the connection
- wffurr 2y agoGenerated C code can be safer than hand written C code if you can prove properties of the generator or carefully test and review the generator itself. 2 examples that come to mind are wuffs and wasm2c. Both produce C code that can be shown to be safe due to the properties of the code generator and its input language. I am not sure LLM output is amenable to same kind of analysis, but you could conceive of an LLM trained on exclusively safe code.
- bmicraft 2y agoAn LLM trained on exclusively safe code could can still combine it in unsafe ways.
- glouwbug 2y agoStatic analyzers be entering a new era
- stvltvs 2y agoFunny, I would expect the opposite, or at least there would be a different class of problems with LLM assisted C. What guardrails would prevent this, and if there are no tradeoffs with the power of C, why haven't we put those guardrails on for human crafted code?
- ashton314 2y agoStrong disagree. Unless you're talking about using an LLM to help transform C into e.g. Rust. I don't see formal methods being unseated by probabilistic techniques (LLMs included) any time soon.
- MrMcCall 2y agoRegardless of the safety constructs or lack thereof in a programming language/environment, our job as software engineers is to construct programs that perform as per their dataflow requirements. That is the only kind of safety I"m concerned with. That can be accomplished for most software projects in most programming environments and their languages, to more or less extent within their limitations, given a proper amount of hard graft to choose the proper constructs and then brutally test them. Power, on the other hand, must be dependent on what is required to wring safety out of the limitations, weaknesses, and pitfalls of the chosen implementation tooling. Power can include speed of development, speed of execution, amount of concurrency, fault tolerance, and so on. Regardless, power must be built upon safe software constructs, safe in the sense that the resulting system performs as intended. A civil engineer will know that a specific kind of bridge constructed out of certain materials using certain techniques will be able to withstand certain events like an earthquake of a certain magnitude and will be able to perform at a certain level, such as tons of traffic at a time or somesuch. As well, they will have a pretty good idea of how long it will take to build it. Such is the maturity (and relative simplicity!) of bridge building. We have no such framework in our industry. Focusing on programming languages shows the immaturity of our industry, which is the most difficult we have yet undertaken as a technological civilization. The proof of that statement is that all our technologies depend on software systems.
- kstrauser 2y agoIt doesn’t help that the customer asks us for a bridge for a bicyclist, uses it as a highway for semi trucks, and refuses to perform scheduled maintenance on it while attackers shoot rockets at the foundation. There are many parts of our discipline that are immature, in addition to the implementation bits.
- MrMcCall 2y agoNothing could be more immature, in my experience, than the non-technical folks that ask for software from us within the corporate environment. And, yes, you are bang-on correct. For one thing, our specifications, themselves, are sorely lacking in specifications! It's half-assed all the way down.
- Animats 2y agoThis article is mostly about macro systems. Those are usually troublesome. But they are independent of run-time safety issues. Macros tend to be hard to read. LISP macros and C++ templates are the usual bad examples. As the article points out, Rust procedural macros are not all that great. They do, though, power Rust's "derive" facility and the serialize/deserialize functions. Those have a simple user interface which hides the internal complexity.
- throwaway17_17 2y agoI know, based on your very informative and large post history, that your point is surely more nuanced. But this just reads as any macros that are not Rust macros are wrong, even when they are very similar. I just do not understand the implied difference (and I have seen comments similar to this sentiment more than just this once). Rust has macros, both of the procedural and ‘syntax-case’ style. Semantically, AFAIK, they are true macros like in Racket or any other language with full meta-syntactic programming options. They are not better typed nor more resilient to errors, nor are they used less pervasively that other languages with macros. Why is it that Rust gets a pass, when other language receive the ‘Macros is bad’ treatment?
- lizzas 2y agoThey mean bug unsafe generally not memory unsafe specifically. I was gonna say "what about Racket"! And that is what they land on.
- FpUser 2y agoSummary: Ode to the things author loves - immutability and Racket. >"name = get_user_name(user)" >"and I didn’t have to worry about user getting modified in the call to get_user_name." If you have this case it is not the language you should worry about but a moron programmer you work with.
- rafram 2y ago> Rust doesn’t have null like in Java, but you know when you get a pointer, you can safely dereference it and you don’t have to do all the null checking that you have to do in Java. thread 'main' panicked at 'called `Option::unwrap()` on a `None` value'
- ashton314 2y agoWhen you call `unwrap` you know that you’re opting-in to unhandled panics at that specific point. At no time to you have to assume something is null—the type system prohibits consuming a value of type Option<T> as if it were a naked T.
- winstonewert 2y agoBut the great thing about Rust is that the panic traces back to the exact place where I thought something couldn't be None, but it was. In Java, I frequently found it mysterious why some variable or parameter was unexpectedly null.
- mike_hearn 2y agoKotlin fixes that, fwiw. Nullity is checked and casted away at the earliest possible time (modulo some ergonomic constraints like a.b.c but modern JVMs give better errors for cases like that).
- bobnamob 2y agogrep for .unwrap() and you now have a handy list of every (potential) “null ptr” deref in your rust codebase, try doing the same in Java. You’d need to grep for “.”, I’m sure that’ll be a nice short list
- lilly-lizard 2y agofor me personally, the trade off between me writing in memory safe rust vs comparably "powerful" C++ is coding speed. I think C++ is a mess and have been using rust for my personal projects for the past 2 years but I still feel like I code faster in C++ because I don't lose time wrestling with the borrow checker. Rust has some fantastic design decisions and features (despite it being a relatively immature language) so I've always thought it was weird how people discuss the trade-off as safety vs powerfulness
- jasfi 2y agoI find Nim to have excellent trade-offs for writing system software. It's so much easier to write than Rust, but is also safe.
- oneshtein 2y agoC++ has ASAN, valgring, and other checkers to wrestle with.
- seanhunter 2y agoI wonder how it will pan out in aggregate when you amortise the productivity of sprinting to produce something vs crawling to fix the problems. In C++ although you are not wrestling with a borrow checker you do find yourself going fast down deep dark tunnels that take ages to get out of. In rust it might be you move instantaneously slower but faster on average but it might take time to gather that data. For exampe I once had to help someone debug some C++ memory leaks in a vast codebase in jobs that took hours for each valgrind run. It was two of us for two weeks to eventually find and fix the problem and the fix was maybe (from memory) 10 lines tops. Not exactly productive. But the person writing the couple of hundred lines that created the problem probably felt quite productive while doing so.
- lincpa 2y ago[dead]
- mock-possum 2y agoIn my experience that it’s uncommon to find yourself thinking “I wish this language was less powerful” - far more common to find yourself thinking “I wish this language was less safe.” Less safe more powerful gives you more options. You can always make things less safe - it’s hard to make them more powerful.
- ChadNauseam 2y agoOn the other hand, when writing C++, I very regularly wish it was more safe, even if that would come at the cost of it being less expressive
- tbrownaw 2y agoIsn't a language being "powerful" mostly about having comprehensive libraries ("import antigravity" and such)? And then of course "safe" means you can't express things you shouldn't want to express, like buffer overflows or arithmetic overflows or SQL injections, or these days prompt injections.
- bobnamob 2y agoIme, language “power” is usually used to describe the expressivity and flexibility of the language itself. As an extreme example, Starlark isn’t a powerful language, it isn’t even Turing complete afaik. This is advertised as a positive attribute for a build description language (I don’t have an opinion, never used it myself). Conversely, C would classify as a powerful language even considering how barebones it is from a “feature” perspective . Poke any memory however you like is a pretty powerful power
- more_corn 2y agoShould all arguments be phrased using the false choice fallacy or should we have ice cream for dinner?
- bmicraft 2y agoYes.
- ashoeafoot 2y agoBoth. It should be a inverted pyramid,starting at the likes of lua, condense to something c#, then the training wheels come off for deep low level access and stranger high level concepts. All within one engine, your elders giving and taking your freedom.
- deleted 2y ago[deleted]
- ramses0 2y agoI actually like Deno's take on things, the ability to "drop privs" (or "allow-list") is super powerful. Starlark is supposedly a limited version of python (https://github.com/bazelbuild/starlark https://github.com/bazelbuild/starlark), but what if you could say in python itself: def foo(): """use strict; use no_func_calls; use idempotent; use no_loops; ...""" ...checked python here... ...or being able to make assertions within a body of a for loop or something. I feel that programming languages need to evolve to deal with a hostile dependency ecosystem, eg: import leftpad as lp with { network: false, filesystem: false, environment: false, max_cycles: 100_000, max_mem: 10_000, ...etc... } ...this is purely arbitrary and hypothetical, of course, but programs become safer when made from safer, more-structured components. We're long past the "single programmer write all the code" phase, and in to the spiral of exponential code+complexity, but no programming languages give you the ability to wrestle with that complexity.
- 0points 2y agoBoth, see rust.
- sega_sai 2y agoAs mentioned by others, the article does not really tackle the question. But it is an interesting question, and I think it would be great to have a language that you could adjust the safety without major rewrites. I.e. various degrees of strict modes. At the times of LLMs, I wonder if anyone looked into some sort of sliding-scale transformation of code from safer, to easier to write. (although I am not sure there are good languages that are expressive enough for that).
- evoke4908 2y agoC# is the first thing to come to mind. If you so choose you can more or less inline C and trample all over memory, or you can write very strict, statically typed, safe code.
- HdS84 2y agoC# has unsafe, which extremely powerful. See ravens repo for heavy usage of that. Otherwise python is also a good example of that. First start out in python. Not fast enough? Bring in python, which compiles down to c. Id that's not enough, drop to raw c.
- sega_sai 2y agoI mostly use python, but switching from python to C is IMO too much work. What would be great if within one language, there was an access to much stricter/faster language. I.e. imagine writing a python function that is strictly typed, and does not use any of the python-isms with __methods that would be more verifiable and faster. I guess cython has a bit of that approach, but it's not that compatible with regular python.
- LectronPusher 2y agoYou would likely be interested in Jamie Brandon's work on the Zest language [1] which has planned "lax", "strict", and "kernel" modes for varying levels of performance/safety [1]: https://www.scattered-thoughts.net/writing/zest-dialects-and-metaprogramming/ https://www.scattered-thoughts.net/writing/zest-dialects-and...
- awinter-py 2y agohave had this argument for library code I have met a style of programmer who thinks, on some level, that generally reusable code is unsafe -- like the `sum` function (stupid reductive example) is not okay unless it has a bunch of business logic restricting the range of the numbers and takes a logger just in case, and the function name is eight words describing exactly what's happening, and the base and the mantissa have different types and you end up with no general code anywhere because reusability is not even an afterthought, it is counter to the project if you've never met this person I sound insane but I swear they exist
- 2OEH8eoCRo0 2y agoIs it really programming if you can't do pointer arithmetic and poke memory addresses? I suppose so but you're not really programming for a machine you're playing in some language developer's bubble-wrapped sandbox.