11 ms·
Sylph: the programming language I want
- okasaki 12y ago>If your language has braces, then you are indenting for the sake of humans (because humans are good at noticing alignment and edges), and bracing for the sake of computers. That’s double the effort for something as mundane as where a block ends. If they get out of sync, then your code naturally breaks in a way that’s very difficult for you to detect. No, I use braces for the computer, and the computer automatically and unambiguously indents it for me. If anything the wasted effort happens in whitespace significant languages like Haskell and Python where the computer can't tell what you want and you have to cycle through all sensible indentations (for every line!)
- vertex-four 12y ago> you have to cycle through all sensible indentations What? My editor indents stuff for me as per PEP8. I don't have to think about it. Why do you?
- okasaki 12y agodef fun(): for x in xs: if a: b c There's no way for an editor to know where to re-indent c to. You have to cycle through the indents manually.
- seanmcdirmid 12y agoAuto indent, tab, and shift tab are your friends. Really, it isn't that bad, considering the curly brace alternative is even worse from an effort perspective.
- okasaki 12y agoTo each their own. I came to C++ from Haskell and found braces to be superior (except visually).
- vertex-four 12y agoHow did you end up with c there, honestly? It's not a thing that's ever happened to me.
- nothrabannosir 12y agoPerhaps I misunderstand, but vim, not a particularly uncommon editor, treats backspace at the start of a line by removing one indent level. So, you're at `b`, you hit enter: next line, same indent level. Now you hit backspace: indent level matches `if`. Again: indent level matches `for`. Type c, there it is. If you had curly braces, you'd use } instead of backspace. Literally the same number of keystrokes, no? Or were you talking about something else and did I misunderstand?
- seanmcdirmid 12y agoThe computer is really quite proficient at inferring block structure from indentation, and if you use a modern editor this structure is manipulated rather effortlessly. The main problem with indent oriented languages is that not everyone is or wants to use a modern editor. Then there are LISPers who think braces everywhere are a swell idea.
- marcosdumay 12y agoWhat's effortless is putting begin and end of blocks symbols only where they matter. Haskell is particularly guilty of creating several different indenting possibilities, and does require constant intervention. Python is less bad, but still requires more effort than C for example.
- seanmcdirmid 12y agoYou really have to design your language around it for it to work well. Haskell has a a lot of syntactic craziness in the name of simplicity.
- masklinn 12y agoWhat? Haskell has a base language expressed in terms of braces and semicolons, and a relatively simple set of layout rules defining how the compiler can insert these braces and semicolons automatically.
- seanmcdirmid 12y agoRight. I meant that Haskell has a whole lot of other weird syntax to consider, that make it hard to read compared to Python. It's use of indentation is not one of the problems.
- codygman 12y agoCharitably speaking, that is very confusing considering you responded to: > Haskell is particularly guilty of creating several different indenting possibilities, and does require constant intervention with: > You really have to design your language around it for it to work well. Haskell has a a lot of syntactic craziness in the name of simplicity. Where "it" would seemingly be indentation, implying Haskell wasn't designed around making indentation simple.
- gnuvince 12y agoI like writing compilers, how do languages like Haskell and Python handle blocks-by-indentation? I figure you have some sort of INDENT token, but how do you know its width? Also, in specifying the grammar, with explicitly delimited blocks you just say `block := OPEN stmt_list CLOSE`. What about with indentation?
- TazeTSchnitzel 12y agoI think they specify "INDENT foo DEDENT" and the lexer tracks indentation and issues INDENT/DEDENT as appropriate.
- falcolas 12y agoThis is correct. A bit of state (an indentation width stack) in the lexer creates the block boundaries as clearly for the interpreter as normal braces does. Any problems in parsing are typically only encountered by stateless parsers.
- dochtman 12y agoI have one (probably quite naive) implementation here: https://github.com/djc/runa/blob/master/runac/parser.py#L54 https://github.com/djc/runa/blob/master/runac/parser.py#L54 (Runa uses tabs for indentation, not spaces, but it's basically the same thing.) Whitespace at the start of a line is a separate token, then I add a thin layer of processing that turns a change of indentation level (i.e. count chars in the token contents) into INDENT or DEDENT tokens.
- zak_mc_kracken 12y agoYou're using a double standard, here: if the computer is good at indenting brace based languages, then it is equally good at indenting languages without braces just based on the grammar.
- mindslight 12y agoNot at all. In this case, by 'languages without braces' we mean languages where indentation is part of the grammar. Python's grammar includes explicit INDENT/DEDENT tokens. It is impossible to reindent this mangled python: if z: print 'a' print 'b'
- adrusi 12y agoWhy would it be improperly indented in the first place? How is removing the indentation any different from removing braces? Sure, when you paste code somewhere that expects prose (Facebook status updates, for example), it will consolidate consecutive whitespace and thereby remove the indentation, but you shouldn't be pasting code into a place like that anyway, because no matter what you do it'll be unreadable, and most people aren't going to be interested enough to put it into their editor to autoformat.
- mindslight 12y agoI did not make the value judgment you are arguing against.
- mixmastamyk 12y agoEditors know that a python line ending in a colon must be indented and so indent it automatically. It wouldn't be hard to use the same method to reindent it.
- unwind 12y agoNo, lines following a line ending in a colon must be indented. But the OP's point is that you can't know how many lines make up the indented block, since there is no explicit block-end-marker left if the indent is gone.
- k__ 12y agoI would usw tab instead of space, so everyone can adjust their indentation width.
- paxcoder 12y agoThat's fine for indentation, but all of it must be exclusively tabs, no spaces. But then to align other things, you have to hold space and do it manually.
- one-more-minute 12y agoFor some of the stuff about types and optimisation in particular, you should check out Julia's type system [0]. First-class types, avoiding inheritance, optional type restrictions, and (albeit early) support for static checking [1], it's all there. It'd be worth taking a look at things like its macros as well – I actually think Julia hits on a lot of the points in this post really well, though of course no language is perfect. [0] http://docs.julialang.org/en/latest/manual/types/ http://docs.julialang.org/en/latest/manual/types/ [1] https://github.com/astrieanna/TypeCheck.jl https://github.com/astrieanna/TypeCheck.jl Minor nitpick: > Tut, tut. That should really be a set! It’s much faster, O(1). Structures like sets have a lower complexity but higher constants (i.e. the overhead of hashing the value etc). When you have a small number of values, a straight linear search over an array will often be faster (which is why it's useful to have the explicit choice).
- octatoan 12y agoI kind of like languages that require "a complete upheaval of [one's] mental model of the universe". :)
- sparkie 12y agoI think it's necessary to look for such alternative approaches when the ones we're using are resulting in ~5 bugs per 1k lines of code on average, frequent security issues, crashes, race conditions, etc. Plus the hundreds of man hours spent fixing these problems. With technology coming more and more into our lives, such that our lives will depend upon it behaving as was intended, we're really going to reach a point where we've got to say enough is enough. The languages (and approaches to development) we're using are not fit for purpose anymore.
- ahoge 12y agoThe inference example is actually a good illustration for why you want to add types to a function's signature. As the author mentioned, a machine can look at how the arguments are used and make some educated guesses. The big problem is that humans have to do the same. That's why I like optional types à la Dart. Not only do they help with static analysis, they also act as documentation. With a good editor, this documentation is right at your fingertips. When you type a function's name, a call-tip will remind you of the expected arguments. If you've added type annotations, the types will be there, too.
- DanWaterworth 12y ago> a machine can look at how the arguments are used and make some educated guesses. The big problem is that humans have to do the same. Why? Just get the machine to do it. It's like when you see programmers doing arithmetic in their heads. "You're sitting in front of a glorified calculator!"
- falcolas 12y ago> Just get the machine to do it. Exactly. Many people already use IDEs, or programs which provide auto-completion or hinting of the types a function accepts when writing out a function name - the type does not need to be explicitly written for the machine to identify the type of the function.
- xxgreg 12y agoWhat types does the following function expect for the arguments a and b, and what type does it return? What should an IDE tell the user about the types of a and b in the completion popup? function foo(a, b) { return a + b; }
- the_af 12y agoIn some static languages, the inferred type for a and b could be Numeric, and foo's type could be: (Numeric, Numeric) -> Numeric Which seems good enough to me. But what if + is also String concatenation? Or any other overloading of "+". Then maybe the type of a and b is Something_that_can_be_+ed. The user can then think "ok, I'll pass a couple of Ints to obtain an Int, or a couple of Strings to obtain a String!". This also seems useful to me.
- deckiedan 12y agoA lot of syntax / spacing / etc. problems would go away if we stopped using completely plain text as the medium for programming languages. Or rather, if we extended plain text, or got our editors to understand the languages a bit more thoroughly than just highlighting keywords and giving us autocompletion or whatever. This has been explored a bit by michaelw and others (http://www.foldr.org/~michaelw/emacs/ http://www.foldr.org/~michaelw/emacs/) for lisp. Imagine a syntax aware editor which could display code from a language using the syntax or style of another. (This might only work from a single base language, there are too many "odd" features in languages which couldn't translate universally). So, since I like python, it could be displayed PEP8 style. Someone else could see it with LISP braces everywhere. Another could have it with 2 spaces and 'end' keywords, or {curlybraced;} (in K&R style, or whatever you like).
- brudgers 12y agoLisp programs are data for the reader ~ in contrast to text for a lexer as is typical in other language families. So long as AST's are in the pipeline from source to execution, the options are lexing [or its equivalent] or writing an AST directly.
- one-more-minute 12y agoThis really assumes that syntax is a purely superficial thing, but in reality syntax reflects the underlying semantics of the language as well. For example, a typical C program (sequence of imperative statements) displayed with lisp syntax will look awful, yes, but so will a typical lisp program (deeply nested expressions) rendered with C syntax. Getting rid of text doesn't change the fundamental issues: Languages would still have different semantics (and thus suit different/custom representations) and it wouldn't make any more sense to mix-and-match than it does now.
- sparkie 12y agoDifferent semantics can be approached by several different methods though - one can simulate an interpreter for a "guest" language in a host language - or the languages can provide an FFI for interoperability. While we have various means to combine the two different semantics of a language, we have no means to combine their syntax without encountering ambiguity problems. This is why storing code in a structured format rather than plain text could be so valuable, because it would enable us to mix and match languages in whatever way we wanted - rather than resorting to putting code inside strings, loading up new files, or complicating the syntax of our language to provide the expressivity we would like (eg, LINQ). Diekmann and Tratt have a theory of Language Boxes[0][1] which provide the groundwork for achieving this kind of editing. They enable language quotation without the need for introducing per-language delimiters, the need to quote code in strings, and the need for escaping characters when hosting one language inside another. The editor is aware of where the language boundaries occur because they are specified by the programmer. The semantics of hosting one language in another are left up to the programmer to specify. [0]:http://lukasdiekmann.com/pubs/diekmann_tratt__parsing_composed_grammars_with_language_boxes.pdf http://lukasdiekmann.com/pubs/diekmann_tratt__parsing_compos... [1]:http://soft-dev.org/pubs/html/diekmann_tratt__eco_a_language_composition_editor/ http://soft-dev.org/pubs/html/diekmann_tratt__eco_a_language...
- brudgers 12y agoThis reminds me of reading a typical zoning ordinance: more an historical sack of bandaid reactions to specific but unrelated past problems than a positive program generating a bounded creative domain. Addressing gripes is not evaluating tradeoffs. Successful languages start with a clear idea of what problem they want to solve, creating coherency at a high level. Values are ranked and might be nice is distinguished from what is held dear. The starting point is identifiable and the passion positive. Saying "the ending point is not here," isn't enough.
- falcolas 12y agoIt actually reminds me of a first draft mind dump. From here, some aggressive refactoring could turn this into a very nice language specification. Brain-dumps are valuable for discussion and as a first step. From there, we just need to follow our normal programming routines: Write, refactor, test, repeat.
- brudgers 12y agoI hated sounding negative on the article. It represents a lot of admirable effort. My point is that the effort is not directed in a particularly constructive direction in regard to creating a new programming language. There's a clear goal when writing a language that is both a floor wax and a desert topping. On the other hand, all writing a language with the goal of being neither floor wax nor desert topping just gets us a floor topping and a dessert wax. There's no problem solved. Griping isn't brainstorming. Brainstorming is structured. Productive brainstorming is constrained by reality. By which I mean that brainstorming about something like type inference acknowledges that type inference is subject to the Halting problem and that dynamic typing as in Python does not entail type inference. Starting with Assembly, all higher level programming languages are DSL's over machine code. Things I hate is not a domain that leads to insight or a coherent minimum language. Python's core was addressing pedagogical problems such as beginners learning to format code well. Google's Closure compiler addresses the problem of JavaScript performance. Rust is intended to address client server programming. For each there is something that can be measured objectively and improved. Don't misunderstand me, there's nothing wrong with writing a programming language as a learning exercise or to scratch one's own itch or solve the world's problems. But it is an engineering design exercise not a poem. The facts of computation make it so.
- zak_mc_kracken 12y ago> it’s sometimes asked why len in Python is a function, rather than a method. The answer is that of course it is a method, called __len__. The real answer is that Python pointedly and deliberately does not reserve any method That's some comical post rationalization. The reason why len is a function is because it was in Python before Python started receiving OO features. As a result, Python is a crazy hodge podge of imperative, OO and functional semantics where you never know if you should be calling `o.foo()` or `foo(o)` unless you've been writing Python since the late 90s.
- pekk 12y agoThis is a myth. Python supported classes close to the start of its existence, way before it became popular.
- sanderjd 12y agoI really like the approach of allowing either kind of call, with the "dot" style mere convenience over the function style. Rust has that sort of thing: let v = &vec![1u32,2,3]; println!("{}", v.len()); println!("{}", Vec::len(v));
- kibwen 12y agoIn general this feature is sometimes called "Universal Function Call Syntax" (UFCS), though interestingly Rust does it exactly the opposite of most other languages with this feature. In Rust, defining a method lets you use it as a free function; in C# and D, defining a free function lets you use it as a method.
- deleted 12y ago[deleted]
- skatenerd 12y agoI always thought this was a weird nod to typeclasses
- andybak 12y agoIf you have some evidence to back that up then you'll want to correct http://en.wikipedia.org/wiki/History_of_Python http://en.wikipedia.org/wiki/History_of_Python "In February 1991, Van Rossum published the code (labeled version 0.9.0) to alt.sources. Already present at this stage in development were classes with inheritance, exception handling, functions [...]"
- nathell 12y agoI find myself nodding along as I'm reading this.
- frik 12y agoThe lang I want would be mixture of C, C++, Go, Rust, Julia, JavaScript 6, PHP 7, Swift, Lua. * Optional typing (like PHP7/Hack/ES7) * support for compilation (statically linked native binaries) and JIT (like Visual Basic 6 with its P-Code) * memory safety (no null/dangling pointers like Rust) * procedural & object oriented & functional style (like JavaScript/PHP/C++) * modern base standard library / API (like C/Go/JavaScript/PHP but more modern with better naming, not as heavy as Java class libraries or .Net Framework) * third party libraries (like Nodejs NPM) * online documentation with code samples and community comments (like PHP.net) * good debugger * IDE plugins for IDEA/Eclipse/VS * good OS support (32 & 64bit) for: Windows & OSX & Linux & BSD & iOS & Android. Edit: * Actor model (like Erlang) * Built-in concurrency primitives: ° light-weight processes (like Fibers in WinAPI, Coroutine in Lua, Goroutine in Go), ° Channels (interprocess communication and synchronization via message passing like in Go and OCaml)
- izietto 12y agoI would add the Actor model of Erlang.
- ICWiener 12y ago"modern base API", what does that mean?
- frik 12y agoI meant "language standard library" (I updated the text). C/C++/Object-C/PHP have short functions with names like strlen, strstr, etc. Java/C#/JavaScript have .length() and things like System.out.println()/Console.Write(). Ideally, I would like a middle ground. The Java/C# standard library is too verbose and the C standard functions are a bit cryptic. It's great one can use different programming styles in JavaScript/PHP/C++. In PHP many functions are available in procedural and object oriented style, e.g. http://php.net/manual/en/mysqli.query.php http://php.net/manual/en/mysqli.query.php
- ICWiener 12y ago
- Zelphyr 12y agoIn many respects I think what you want is Rebol.
- CyberDildonics 12y agoWhenever I see something like this I feel like it is someone unfortunate who has thought a lot about language design but unfortunately hasn't heard of julia. His list is almost a checklist of the reasons julia was created.
- zem 12y agothe section on loops, in particular, really captured a small but ubiquitous frustration in every language I've used. we really should be able to say "this is the first iteration", " this is the last iteration" (though that one might not always be possible) and "did the loop run at all?" without getting into index comparisons or manually setting and modifying flags.
- pnathan 12y agoThis is a great bag of "Hum, these things irritate me, let's do better". Couple critiques come to mind: - too Rust/Python focused - the author needs more rounding of PL experience. I would suggest spending some more time with Haskell/ML and then some time with Common Lisp/Scheme. Reread the Programing Languages survey textbooks from college. - not really enough familiarity with the theoretical side of PL. A metric ton of work has been done in academia, some of the listed problems have been solved, and at the worst, will give the author a nice way to go to sleep at night. This kind of relates to the previous point. The concept of Locality I think is an important one and a real take-away from this essay. You want to be able to ensure that your code is meaningful locally without bouncing around half a dozen modules and inheritance trees just for basic understanding.
- bsder 12y agoThis bothered me a lot: > I seem to have a knack for trying to write things in Rust that rely on intertangled references and mutability: first a game, then a UI library… First of all, a UI library is EXACTLY the kind of thing I want you running through Rust and having a long, drawn out fight over mutability. Every UI we currently have absolutely sucks in a multi-threaded context. I want the compiler to make you think long and hard that maybe, just maybe your ideas about how to architect a GUI library are very broken and that you have to restart from a clean slate. As for a game, do you really have that much mutable state, or are you just conditioned to use mutable state by default? Games do have lots of mutable state, but games also have lots of bugs due to multi-threading that being forced to analyze mutable state exposes.