8 ms·
Redundancy in Programming Languages
- kungato 7y agoYou use unit tests in Python and Javascript among other things to check for type/value in some places which can be easily avoided if you explicitly used types. Also I often see in imperative languages that unit tests are used to declaratively describe something which you had to imperatively implement. To me it often feels like declarative functional languages have these features immediately as you write the code but then you have to invest the mental effort up front so people rather do half the thinking first then wrap things up with unit tests. The problem is you have to go back to the initial code when wiritng unit tests which fail while you could have done the complete work the first time around. Often it feels like people don't want to do too much work so they choose the language which allows them to offload erorrs for later. It even makes business sense to finish sooner then charge for maintenance later. A shame really
- graham_paul 7y ago> people don't want to do too much work so they choose the language which allows them to offload erors for later Replace "people" with business and you are right. I feel many devs would prefer to invest the time once rather than hack it once then go back and add unit tests
- userbinator 7y agoProgramming languages extensively use this to reduce coding errors. If there was no redundancy at all in a language, then any random sequence of characters would be a valid program. This is completely opposite to the philosophy of the APL-family languages, and those who have learned them seem to also argue strongly that the conciseness reduces errors and makes for higher productivity. Probably the best example of redundancy in a programming language is unit tests. Some of my worst experiences have been fighting unit tests that were "overspecified", i.e. testing for inputs which would otherwise be clearly impossible in the context of the whole system, with the result that any trivial change to the code can cause test failures that consume time to diagnose, despite zero change to the ultimate functionality of the system.
- Supermancho 7y ago> testing for inputs which would otherwise be clearly impossible in the context of the whole system Off the top of my head... 1. When reusing code, unit tests that specify unexpected inputs are useful because you don't know the future use case. That's a rather weak reason to write the unit tests now, but a reason. 2. There is no way to enforce what is an expected input to a function, once a system grows large enough. Changes in the upstream dataflow being traced through the system by investigating every unit test is impractical. Being defensive up front, is reasonable.
- cageface 7y agoThere is no way to enforce what is an expected input to a function, once a system grows large enough. This is exactly what typechecking does for you and is the reason I think trying to build any large system without them is a bad idea.
- Supermancho 7y ago> This is exactly what typechecking does for you Having types, isn't a binary choice. eg Generics, plain objects, functions, pointers. There are inevitably gaps in how the type system can ensure your what your outputs will be (even if it's a halt).
- cageface 7y agoSure, in an absolute sense. But in practical terms they are fantastically helpful here.
- userbinator 7y agobecause you don't know the future use case ...and thus you shouldn't care about it. I've seen enough problems caused by attempts at "futureproofing" to know that YAGNI is always a good choice. When/if it does matter, then you can do the work; but inevitably, requirements always seem to change in such a way that your attempts to anticipate them results in code that's structured to be flexible in exactly the wrong way, adding unnecessary complexity, or even hinders the desired changes.
- ddevault 7y agoThere was some debate at an old job about whether or not to use semicolons in JavaScript. I would just like to remind everyone reading this that if you don't write semicolons in your JavaScript, you are doing it wrong, and we cannot be friends.
- jakear 7y agoI’ve said it before, I’ll say it again. Semicolon-free JS is much easier to edit, and the typical foot-guns associated with it can be trivially avoided with a formatter/linter.
- tylorr 7y agoSemicolons can also be automated, which is what I currently do at work.
- jakear 7y agoSee reply to sibling. It’s not about inserting the semi, that’s trivial.
- SPBS 7y agoSemicolon JavaScript is trivially easy to write with a formatter -- just hit format and it inserts semicolons for you. And has no footguns.
- jakear 7y agoIt’s not writing the semis themselves that’s the issue - obviously that’s trivial. It’s editing lines that have semis. Any “to end of line” operation (and there are tons) you have to think about whether you want the semi or not, which often depends on what the future context will be. This is one of those things where once you get used to “power-editing” in semi-free, it’s very difficult to go back. And note that the bulk of my work is semi-d, I only go semi-free on greenfield projects. So it’s not a case of having more experience one way or the other. Any lisper/schemester will tell you that reducing syntax makes power editing simple, but for some reason JS people love their semi’s. Beats me.
- WalterBright 7y agoAuthor here. AMA.
- scared2 7y agoWhy do you this authors of these programming languages try to creat a different set of keyword names and syntax. If google liked python why not follow the already familiarpython syntax to create go?
- jhanschoo 7y agoDifferent languages have different semantics, so the language designers choose to use a different syntax to reflect the different semantics.
- WalterBright 7y agoWe also use different syntax in places where the original was known to be a source of problems. For a trivial example, `unsigned long long` is annoyingly long to type, `ulong` is much better. `uint64` seems at first impression to be better because the bit length is in the name, but digits are harder to touch-type, not so pleasing to look at, and after using the language for a day the reminder that it is 64 bits gets tedious.
- tsegratis 7y agoI like your observations in this article, but I find them really hard to apply to design Redundancy is evil... but also essential. What characteristics distinguish one end of redundancy from the other?
- WalterBright 7y ago> What characteristics distinguish one end of redundancy from the other? Hard to say. Some call it simply "good taste".
- throw_m239339 7y ago
- closeparen 7y agoThere are similar stories for gendered articles and conjugation in natural languages. They don't convey any additional information, but in case you miss the word, they provide clues elsewhere in the sentence that significantly constrain what it could have been.
- therealdrag0 7y agoReminds me of a bug I found in some Scala code. def getString: String = { "I am a value to be resolved" } def wrapper1(auth)(thunk: => String): String = { if(auth) thunk } def wrapper2(auth)(valueAlreadyResolved: String): String = { if(auth) valueAlreadyResolved. // Auth check did nothing, code already ran!!! } wrapper1(auth)(getString) wrapper2(auth)(getString) These two method signatures/behavior are different but the syntax to call them is identical! One executes "getString" only when the parameter is referenced (v1), the other (v2) executes it before the wrapper is even entered. This sort of flexibility can be handy, but it can also shoot you in the foot. Some languages like I think Java make you do something like "::getString" to pass a function pointer. That redundancy makes it explicit and prevents the mistake above which could have serious implications.
- einpoklum 7y ago> Eliminating redundancy is often viewed as a way to streamline productivity and reduce waste AFAICT, that is much more often said about _programs_ (and perhaps libraries) than about programming _languages_.