3 ms·
> to write code for human readers first, and compilers second. I find this very ironic in this context. After all lisp is a language where the human does half
by zaro 7y ago
> to write code for human readers first, and compilers second.
I find this very ironic in this context. After all lisp is a language where the human does half of the job the compiler is doing, because you need to write directly in AST instead of higher level language.
- tl 7y agoIt's more of a compromise between the humans dealing with language (compiler, editor, DSL authors) and the humans who exclusive want to write application code. Common Lisp is far from the only option, but it's arguably the best compromise of popularity / feature set. There are a variety of s-expression, stack-based or simple syntax languages that could work. As a counter-example in a more popular language, look at how much effort went into "function builders" for Swift. They're solving a real pain point, but it took five years to get there, the feature isn't backward compatible to old versions (unlike a lisp macro), and the standards process was minorly subverted to add them.
- dreamcompiler 7y agoTwo points: It's easy to learn to think in ASTs; it just takes practice. No more practice than it takes to get good at any other programming language. Second: ASTs contain no ambiguity. English contains ambiguity. Javascript contains ambiguity. The full meanings of most programs cannot be discerned from just looking at them; you also need external documentation that describes the conventions in play (e.g. operator precedence). This is less true with Lisp than with any other language. Lisp novices complain about Lisp being write-only, but a well-written Lisp program written today will still be self-evidently unambiguous (and likely even runnable) in 1000 years. Try that with C++. Lisp is the Latin of programming languages.
- quixoticelixer- 7y ago> Lisp is the Latin of programming languages. Fuck I hope not
- Koshkin 7y agoThen Haskell is the Greek.
- _emacsomancer_ 7y agoLatin also contains ambiguities, at various levels (lexical, syntactic, &c.), just like any other natural language. Lisp is, however, rather similar to Montague Grammar-style analyses of natural language, assuming a modern Chomskian binary-branching tree structure.
- lispm 7y agoOne does not write 'directly in AST' in Lisp. Lisp is written in nested lists of prefix expressions. Instead of foo(bar(1,2)); one writes (foo (bar 1 2)) Instead of function foo(bar) { bar.baz = "hello"; } one writes (defun foo (bar) (setf (slot-value bar 'baz) "hello")) Instead of function(a) { a + 1; } one writes (lambda (a) (+ a 1)) Basically it's writing hierarchical lists of tokens in a externalized data structure: symbolic expressions. An AST would represent more information. For example a s-expression representation of an AST might look like: (anonymous-function-definition :argument-list ((variable :name a)) :body (function-application (function :name +) :arguments ((variable :name a) (constant :value 1)))) It would actually represent from parsing what the meaning of the tokens is (function, variable, constant, ...) and what the syntactic constructs are: function definition, function application, argument list, ... -> an AST is the result of a syntax analysis. see: https://en.wikipedia.org/wiki/Abstract_syntax_tree https://en.wikipedia.org/wiki/Abstract_syntax_tree The Lisp source representation lacks this information and needs to be parsed/interpreted to construct this information. The Lisp reader does not do a syntactic analysis of a program - it does not even know the difference between program and data. On the Lisp source level a program is just data and (+ a 1), (a + 1) and (a 1 +) are all valid expressions - but only the first is a valid Lisp expression.
- kazinator 7y ago> The Lisp source representation lacks this information and needs to be parsed/interpreted to construct this information. That information doesn't have to go anywhere into the tree though; a compiler can generate code directly from a macro-expanded top-level expression without constructing any class-based concoctions involving inheritance. The parsed Lisp data structure meets the textbook definition of AST in every regard, particularly after macro-expansion. All the nodes that are compound forms are clearly labeled and classified by symbols which denote the special operators. Recursive walks of the tree can readily branch to cases according to these symbols. It's just a smarter version of the diagram you see in that Wikipedia page's top diagram.
- lispm 7y ago
- TeMPOraL 7y agoExcept that requirement makes working on code as data trivial, which enables proper macros, which lets you raise the level of abstraction you're working on to arbitrary levels, and hide all the machinery supporting it. So in the end, you end up writing code much closer to the domain (and thus, more human-readable) than you would in a non-Lisp language.
- kazinator 7y agoThe idea that there is a man/machine trade off is a fallacy. In fact whatever is hard for the machine is also hard for the human and vice versa. Syntax requiring hard-core parsing techniques is also harder for humans to understand and to parse. If you're already thinking in abstract syntax, encoding it in concrete syntax is extra work. The more convoluted the concrete syntax, the more work it is. And then consequently to decode it. Analogy: "When you write plain text, you're doing the job that the machine should be doing for you because you're writing in the direct decoded output! You should type your data directly in compressed format; then you could take advantage of GNU gzip to decode for you! The gzip format has useful syntactic sugars for reducing verbosity, like indicating that some fragment of a few bytes is to be repeated. And you can further express yourself in fewer bits using convenient Huffman codes and such." The fallacy is rooted in taking it for granted that the convoluted representation is the more convenient one in which programmers actually think and, furthermore, that the only operation whose cost matters is the conversion of that representation to the abstract one, not vice versa.