文档结构  
可译网翻译有奖活动正在进行中,查看详情 现在前往 注册?
原作者:Will Crichton    来源:notes.willcrichton.net [英文]
CY2    计算机    2016-08-04    0评/220阅
翻译进度:33%   参与翻译: 我呀我 (1)

编程语言的效率和类型安全常常被评估,但友好呢?我在探索人类的价值观是怎样被应用于编程语言环境,特别是童子军法律中的12点:值得信赖、忠诚、乐于助人,友好,有礼貌,善良,孝顺,开朗,节俭,勇敢,干净,和虔诚的。

警告:此帖子对编程语言有很强的主观意见。观众自由定夺。

简介

    在讨论编程语言时,我们倾向于关注数学/逻辑对象。这种语言精准并模块化,那种缺乏正式语义,这种严格遵循范式,那种很好匹配公式。但是,语言及其相关的编译器最终不是抽象的概念,而是人们实实在在使用的工具,带有更多的价值而不仅是纯粹的数学。作一个有趣的思想实验,如果我们把期望从别人身上得到相同的价值观这一现象归因于编程语言会怎么样?

    关于良好的价值观,我们可以看到经典的组织致力于向年轻人灌输老式的美国价值观: 美国童子军[1]。具体来说,所有的童子军被要求遵守童子法,奉行以下12点价值观: “童军是值得信赖、忠诚、乐于助人,友好,有礼貌,善良,孝顺,开朗,节俭,勇敢,干净,和虔诚的。” 在本文中,我将探讨如何将这些价值观应用于编程语言的上下文中。

第 1 段(可获 2.89 积分)

APPLYING THE LAW

A brief preface: for brevity, I will lump together programming languages and compilers, referring to them interchangeably. My interpretation of broad human values like "friendliness" is obviously not authoritative, but just intended to spark further discussion on the topic. 

  1. Trustworthy. A trustworthy language is one you can believe will protect your secrets and not go behind your back to mess with your program semantics. Such a language should have ASLR enabled and should have crypto libraries made by experts so users don't roll their own. You should be able to trust that your language will make reasonable decisions on your behalf. For example, a language should notcoerce your types in unreasonable ways when you're not looking—we ought not confused dynamic typing (checking types at runtime) with weak typing (coercing types instead of failing in the presence of type errors). Trust is an essential element of productivity. When a programmer does not trust his language, he is forced to program defensively and must battle both his own bugs as well as the compiler's. A trustworthy language permits the programmer to feel comfortable in his environment and to focus on the task at hand.

  2. Loyal. A language is loyal when its design evolves with the preferences of its users, not its owners or corporate overlords. One should feel comfortable that a language will not turn around and get you sued for using its basic features.

  3. Helpful. A language can be "helpful" in a myriad of ways, but one aspect often missing from newer languages is a means to help the programmer understand his errors. It should have a battle-tested debugger. You should not need an additional piece of software to decipher your compiler's dense and enigmatic build output. For brownie points, your compiler should explain why the programmer has encountered an error, and for the gold medal it should propose a solution.

  4. Friendly. For a language, it makes the most sense to interpret this as "open to newcomers," e.g. Python is simple to start with whereas Standard ML can be aformidable foe when first learning functional languages. Having a REPL is a crucial part of a friendly language—it allows new programmers to play around with syntax and get a quick feel for a new language without having to wade through a hundred compiler errors or a monstrous IDE. As a corollary, dynamic languages often feel more friendly since they can be run in small pieces. They permit the programmer to make small errors which the user doesn't need to concern himself with until necessary.

  5. Courteous. Any language should follow common courtesy: it should clean up after itself (compiler-managed memory) and talk respectfully to its elders (have FFI out to C).

  6. Kind. For me, the distinguishing factor between kindness and other values like helpfulness and courtesy is intention. For a language to be kind, its designers need to be kind in turn. I have never met or heard of a language designer intentionally create a language harmful to its users or its community (although you have to watch people like Ken Thompson), but one should always be careful, particularly with closed-source languages. Language designers should have a clear, open dialogue with their community so as to not have their intentions misconstrued or turned against them.

  7. Obedient. Similar to being trustworthy, an obedient language will always do what it's told and no more. The language's libraries should be clearly named and documented. If a function has to fail, it should not do so silently, and the programmer should handle the error (error codes considered harmful). The language should be formally specified, and the compiler should adhere strictly to the specification, loudly telling the programmer where it does not.

  8. Cheerful. This is perhaps the least applicable to programming languages, as there's a fine line between cheer and condescension. After all, nobody wants a compiler like this: 

    However, arguably to be cheerful it means one should at least be more upbeat. Doom and gloom and vitriol are not essential parts of a compiler (or any piece of software).
  9. Thrifty. A language should do a lot with a little, or prefer a smaller number of powerful abstractions to a larger number of weaker ones. More concretely, do not make concepts first-class in the language unless they need to be, otherwise implement them in libraries. For example, Rust implements iterators as traits and Clojure implements gradual typing as a library (!). Similarly, a thrifty language should only pay for what it needs and prefer zero-cost abstractions where possible. If your quick script takes 0.5 seconds to run but 3 seconds to start the garbage collector, then the language is not thrifty. If your build takes an hour to compile against a library from which you only need one or two functions (cough OpenCV), then the language is not thrifty.

  10. Brave. As a language designer, do not be afraid to be brave when creating a new language. Although I received overwhelmingly positive feedback on one of myrecent posts on language design, there are many naysayers stuck to their paradigms and editors who will be washed away with the flow of time and progress. Make that new type system. Change up the syntax. Just do so while trying not to violate the other principles of good language design.

  11. Clean. Just as people should look and smell clean, so should the syntax of a programming language. Although programmers often like to think in abstractions, the concrete syntax of a language really does matter. In most software development, code is meant to be read and not written, so the more legible your language, the easier it is to maintain. Remember that the language designers often dictate style used by the community. Avoid the majority of naming conventions brought from mathematics (e.g. one letter variable names) unless no one will read your code or it actually improves legibility. Naming is important!

  12. Reverent. Whether you belong to the Kingdom of Nouns or the Church of Lambda, be respectful of all faiths. Better yet, take the best of all worlds when designing your language (see: my previous post). Don't force users to pick one paradigm over the other, but rather be flexible enough to accommodate all walks of life.

第 2 段(可获 13.13 积分)

CONCLUSION

The inevitable counterpoint to this post is this: "but Will, I don't care if my language is friendly. I just need it to work. We should care about efficiency, not these abstract notions of human good." And this is a fair point! I wouldn't use a language that was trustworthy but didn't actually do anything. However, we shouldn't let goals like efficiency wash away all else in the discussion. If we promote programming languages that have values like those discussed above, we can create a better world both for existing programmers as well as those seeking to enter the craft. Language designers should remember that their end users are people, not robots [2], and design accordingly.

Please direct your opinions to my email at wcrichto@stanford.edu or discuss this on Hacker News.

REFERENCES

[1] Yes, I know the Boy Scouts are not always paragons of good values, and yes, I know the Boy Scouts are originally from Britain.

[2] Unless, of course, your language is LLVM.

第 3 段(可获 2.15 积分)

文章评论