6 ms·
What I Expect From a Programming Language
- jfb 14y agotl;dr: OP likes Eiffel. A perfectly reasonable post, but not a very interesting one. I could probably write something similar: - homoiconicity - tail-call elimination - s-expressions Can you tell what my first language was?
- unimpressive 14y agoScheme?
- kenjackson 14y agoNope. Must be XML.
- jfb 14y agoXML used to be a very easy way for my coworkers to get a rise out of me. Thankfully, I haven't had to think about it since I left Apple.
- jfb 14y agoChicago's version of 6.001, straight from SICP.
- jQueryIsAwesome 14y agoClojure.
- jfb 14y agoI'm a little older than that. Also, the JVM precludes TCE.
- jQueryIsAwesome 14y agoWell, there is trampolines: http://clojuredocs.org/clojure_core/1.2.0/clojure.core/trampoline http://clojuredocs.org/clojure_core/1.2.0/clojure.core/tramp...
- jfb 14y agoWhich is useful, sure. But when you're conditioned to write in a tail-recursive style by the language environment, it still pulls one out of the flow. That said, I've only written Clojure for amusement, never on anything large, so it could simply be a matter of getting used to new convention. I'm also come around to strong, static type systems since my Scheme days, but that's a different kettle of fish entirely.
- tikhonj 14y agoI think "one way to do it" Java and Python philosophy is overrated. Sure, when it's presented that way, it sounds great! Why wouldn't we want one way to do things? I like to think about it differently: instead of trying to coerce my problem to fit the language, I want to mold my language to fit the problem. It's easier to think about the problem in its own terms--the terms of its domain--than in those terms filtered through a "one-size-fits-all" language design. I want code that is declarative and closely reflects its underlying logic. And this means there will be more than one way to do things--while many problems are similar mechanically, their actual meaning is vastly different. So there really is a benefit to having more than one way to do things: you can choose a way that's appropriate for the problem you're solving. Of course, this puts a bit of trust into programmers to have good taste: while it allows you to write far better code than a one-size-fits-all language, it also allows you to write far worse code. I personally think this is a worthy compromise. Another interesting thing I've found is that having more than one way to do things naturally emerges when you have a distinct set of powerful primitives. This is most evident in math: for any given problem, there are often a ton of different ways to arrive at the same solution. Each of these ways emerges naturally from the fundamental building blocks of math. Coincidentally, these different ways of looking at the same thing are not only natural but actively useful: they give you different perspectives on the same idea. An example I recently encountered was with lattices. There are two different ways to define a lattice--one in terms of partial orders and one in terms of algebras. The former gives you an intuition on the structure of a lattice; in a sense, it tells you what a lattice "looks like". The latter makes it easy to see relationships between lattices and other algebraic structures: for example, Boolean algebras are just a special kind of lattice. You can then even combine the two and start thinking about Boolean algebras in terms of orders. So to me, having multiple different but equivalent ways to do things is both useful and natural, especially if these different ways emerge naturally. I much prefer this approach to something more prescriptive and monolithic, where the language designer has tried to guess exactly what and how I will be doing and explicitly provided a way to do it.
- tubbo 14y ago> I like to think about it differently: instead of trying to coerce my problem to fit the language, I want to mold my language to fit my problem. THIS is why I like Ruby so damn much! Typically, "one way to do things" breaks down when you need to be expressive about the conceptual nature of your program. Python is too rigid for me, it expects that all of my problems can be written in a mathematical and structured way. And realistically, that's just not how I think.
- darrencauthon 14y agoHe wrote: "As much static checking as possible: Static checking is good. Did you ever write a larger piece of code in one go, compiled it and it produced tons of errors? All these error would still be there, if you would not have static checking. You err much more than you think." I think he errors much more than he really thinks. If errors are what he's truly trying to avoid, he'd be more focused on unit testing and TDD than passing syntax. Descriptions like his make me wonder how many static typing proponents have actually spent any legitimate amount coding in a dynamic language for a production application. It seems all scary to code applications without a big IDE, but I promise that it's possible and a lot of people make it work.
- jfb 14y agoI think that static and dynamic type systems are classic incommensurable goods [1]. There's no way to pick between them based on some sort of value calculus; you just have to toss your hat in one ring or the other and live with the weaknesses as well as the strengths of your chosen approach. [1] http://plato.stanford.edu/entries/value-incommensurable http://plato.stanford.edu/entries/value-incommensurable
- jacques_chester 14y agoI think people pick dynamic more often because of the reward schedule. Dynamic languages don't dish out as many errors upfront; most of the time it'll "work"-as-written. Immediate positive feedback. Meanwhile the static typing compiler is spitting grumpy errors about some nitpicktastic piece of fluff it spotted. Immediate negative feedback. So given the weekend-new-language thing, which example leaves a better impression? Basically -- generalising enormously -- dynamic languages reward in the short term and punish in the long term; static languages are the opposite. But human cognition is dreadful at long term prediction or comparison. So static languages will always be underrepresented unless, I dunno, Haskell compilers start doling out XP for fixing errors in your code.
- jfb 14y agoBut the overall calculus, in terms of, say, "productivity" (which is the hand-waviest of hand-waveries) is going to zero out. Or at least, that's my contention, based on these facts (∅) and twenty years of opinion and anecdote.
- PuerkitoBio 14y agoInterestingly, these qualities all apply to Go: - easier to read than write : it has been said a lot that go (esp. its error handling) was somewhat verbose, though very readable. - Not tricking the programmer : this one is a bit subjective, go does use the equal sign as assign operator, but the required braces for if-else, gofmt tool and strict compiler help in not tricking you. - one way to do things : go (its community) is very actively promoting the idiomatic way of doing things. Also consider, no while/do loops, only for. - as much static typing as possible : maybe not as much as rust, but yeah, very static typing (array length is part of the type, for example) - no warnings : exactly that! Unused variables and imports are errors. - coding conventions part of the language : the gofmt tool does that. Don't publish code that is not gofmt'ed!
- chimeracoder 14y agoI read the article and then came to the comments looking to make this exact point. Gofmt is my favorite example of why coding conventions can, and should be part of the language.
- msutherl 14y agoPrograms should be easy to write and easy to read Formatting should delineate structure wherever useful Syntactical noise should be avoided Should provide powerful tools for expressing ideas succinctly Static checking should be available but not required Should provide a rich set of built-in tools Should support runtime program manipulation
- zem 14y agoit's interesting how his entire class of expectations is different from mine. my focus is mostly on what facilities for abstraction and safety the language gives me; i hold that if you have powerful enough abstraction facilities to factor out boilerplate, your code can be made to be way more readable than the "only one way to do it" class of languages, and if you have safety features built into the language (static typing, abstract datatypes, contracts, linear types) it will be forced to be more reliable.
- pcwalton 14y agoMaking unused variables and code formatting issues into errors was considered and rejected for Rust. The reason is that much of debugging consists of commenting out pieces of code and rebuilding. Often this results in variables becoming unused and formatting becoming messed up. I've worked with systems that threw errors here (FxCop), and it was terribly inconvenient in practice. I think the optimum is just a loud set of warnings, a community expectation that all code be warning-free, and a pretty printer included with the language to get the ecosystem to standardize on a style.
- ced 14y agoI don't understand how he can want static checking, but no warnings. "x is declared but never used" has saved me so many times. Maybe he's used to languages where warnings cannot be locally disabled? In Common Lisp I can (declare (ignore x)) to "shut up the compiler", and it works really well.
- michaelfairley 14y agoHe wants "x is declared but never used" to be an error that halts compilation. Go's philosophy on this[1] is "if it's worth complaining about, it's worth fixing in the code." 1: http://golang.org/doc/go_faq.html#unused_variables_and_imports http://golang.org/doc/go_faq.html#unused_variables_and_impor...
- bo1024 14y agoI agree with most of the post, but this: > Programs have to be easier to read than write I think is impossible.
- webreac 14y agoIt was one the main motto of Ada. Ada is very easy to read (to be honest, it is less true since Ada95) but when I do not use it during a long time, I forget how to write in Ada.
- aidenn0 14y agoI think this is off base with regards to warnings. Warnings are the sign of a language that has been widely used. There is something that is now known to be bad (i.e. error prone), but previously was not known to be bad. If you make it an error you break lots and lots of code. If you totally ignore it, you allow more preventable bugs to be introduced. Thus the warning is born.