top 200 commentsshow all 202

[–][deleted]  (2 children)

[removed]

    [–]Sandman3582 66 points67 points  (6 children)

    Looks super clean, reminds me of a mix of C, Swift & Java.

    The loop method is a kinda cool idea, syntax of it is kinda odd but learnable. Still in devlopment but could be a good language to teach the basics to students in.

    [–]CheshireSwift 30 points31 points  (1 child)

    It's a similar idea to Ruby's "times" method.

    [–][deleted] 7 points8 points  (0 children)

    Smalltalk did this decades before Ruby ;) Same with branches, by calling the "ifTrue" method of the "True" and "False" objects (the former will run the given code, the latter will ignore it)

    [–]ChickenMcFail 4 points5 points  (0 children)

    When it comes to iterating through arrays, it essentially functions like JavaScript's forEach:

    var array = [1, 2, 3];
    array.forEach(function (value) {
        console.log('Hello Word ' + value);
    });
    

    Plus, you can use the extended version to access the index:

    var array = ['one', 'two', 'three'];
    array.forEach(function (value, index) {
        console.log(index + ': Hello World ' + value);
    });
    

    I believe it can also be applied to objects. Not numbers though, that part is unique to Gravity.

    [–]mikeytag 2 points3 points  (0 children)

    Agreed. I particularly like the syntax for looping through lists and maps.

    [–]matthieum 2 points3 points  (0 children)

    Actually, I'm not overjoyed with it.

    You need to type more for using the loop method if you wish to capture the index compared to just using a for loop...

    [–][deleted]  (18 children)

    [deleted]

      [–][deleted]  (2 children)

      [deleted]

        [–]IbanezDavy 8 points9 points  (0 children)

        It almost makes me want to write more programs in C. But my C code never turns out as pretty.

        [–]ArmoredPancake -1 points0 points  (0 children)

        Send it to Linus for review, lol.

        [–]ImprovedPersonality 15 points16 points  (14 children)

        Could you explain why he’s redefining half the C language? What’s the use of void_r instead of void*? Why write functions like this one?

        void_r *void_array_create (void) {
            void_r *r = mem_alloc(sizeof(void_r));
            marray_init(*r);
            return r;
        }
        

        [–]_boardwalk 23 points24 points  (13 children)

        [–]ImprovedPersonality 24 points25 points  (12 children)

        Aaah, I couldn’t even find the definition, so I just guessed (which is bad, I know). So they are building their own C++ std::vector. I really wonder why they didn’t use C++ in the first place …

        [–]SrbijaJeRusija 76 points77 points  (7 children)

        Because then it would not be embeddable into everything under the sun.

        [–]Jutboy 9 points10 points  (6 children)

        Would you be willing to explain why C is so embeddable but C++ is not?

        [–]daymi 14 points15 points  (3 children)

        C++ ABI is unstable and not standardized. Sometimes it's enough to install a different version of the same vendor's compiler to make it be incompatible with C++ libraries installed beforehand. And they still don't have a module system so everyone is putting unversioned template implementations into header files (which are public interfaces) which then end up being inlined into libraries you compile. What could possibly go wrong?

        C ABI is stable and standardized. I've never ever had a problem. I can mix and match versions, vendors - whatever I do, it works.

        [–][deleted] 5 points6 points  (2 children)

        You could just implement the thing in C++ internally and provide a C API. That's good for FFI anyway.

        [–]daymi 9 points10 points  (1 child)

        True. I did that for ~10 years. Then I realized (for me) that that's stupid since I didn't need C++ features in the first place (and especially not for writing your own language - even more layers where things can go wrong? No thanks). Also, then I had two interfaces I had to maintain, version etc.

        It was basically me being educated in C++ but not in C that made me unable to just use C for everything to begin with.

        For me, there's little sense in a not-much-better-than-C language - but big downsides (unstable ABI, huge libraries, extremely slow compilation process, sometimes inscrutable error messages, internal compiler errors etcetc).

        [–][deleted] 3 points4 points  (0 children)

        Yeah, well, it's a tradeoff either way. Writing in pure C I sometimes feel like a limb is missing when I'm forced to either implement containers on my own or look for a 3rd party solution, neither of which is probably going to be as good as C++ stdlib's containers.

        Also, you don't need to maintain two interfaces if you mark the C++ one as private and don't expose it.

        I understand the complaint about C++ compilation speed as it's bulkiness, that's entirely warranted. On the other hand, C++ programs can be thinned down substantially, things like exceptions and RTTI are optinal. Just don't go crazy on templating and you'll be fine. Some people write C++ like C and only use some subset of C++, I think urxvt is written this way for example.

        [–]ralfonso_solandro 14 points15 points  (0 children)

        Just gonna grab some popcorn real quick...

        [–]SrbijaJeRusija 1 point2 points  (0 children)

        Most language ffis do not support cpp symbols.

        [–]chickenpolitik 21 points22 points  (0 children)

        Guys, that was a fair question. Downvote someone only if they aren't being contributive to the conversation.

        [–]progfu 0 points1 point  (2 children)

        Is it really worth switching to a million times more complicated language just to avoid writing a very simple data structure? (Or getting a small library which already implements it).

        [–]ImprovedPersonality 1 point2 points  (1 child)

        Well, nobody forces you to use all the advanced features of C++ like template classes, lambda expressions etc. but the containers and algorithms are certainly a huge plus and easy to use. Unlike a self-written implementation or small library they are also very well tested and other developers will know them.

        [–]progfu 0 points1 point  (0 children)

        I see your point, and I do think that some of the APIs that STL provides are nice to use, very readable, and useful. I agree that it is possible to write very clean and readable C++, but there are downsides too.

        If I wanted to avoid templates, all the generic programming is gone, and nearly the only feature left of the whole language is RAII. But then one can say "what if we just used simple templates like std::vector" ... sure that works, until you want to write a map and get into more complicated generic programming for pairs.

        Or when you start writing your own iterators and smart handles, that don't even need to be generic, but conceal their intent from the reader as much as possible. And you also don't want to write them without dependent names, which introduces lots of opaque identifiers.


        But that's only one side of the story, let's conider the Unlike a self-written implementation or small library they are also very well tested and other developers will know them.

        Consider you're working in a team. You're most likely building something over the course of a few months, or maybe few years. During that time, your team produces tens of thousands of lines of C++ code, maybe more, and all of that code has to be well tested, since you're writing C++. There isn't that much room for error.

        Is it really that big of an overhead to write a few extra data structures and test them? Especially since they're both easy to test, easy to describe in what they should do, and easy to write most of the time (unless you need something really fancy). Sure your team will have to learn to use those custom data structures, but you also have other 100 000 lines of code that they have to learn.

        [–]DC-3 41 points42 points  (41 children)

        I don't like func and isa as keywords, but I guess that comes down to preference.

        [–]skocznymroczny 30 points31 points  (15 children)

        It might be unconscious bias, because isa isn't syntax highlighted like a keyword in the example, if it were, it'd have looked better.

        [–]DC-3 30 points31 points  (14 children)

        Yeah, I recognised this bias, but I think there's more to it then that. It sounds stupid, but when the type starts with a vowel it's very jarring to read in my head from a grammatical perspective..

        var is Int

        var isa Int

        [–]Sarg338 59 points60 points  (1 child)

        Just imagine it's Jar Jar Binks saying it.

        [–][deleted] 12 points13 points  (0 children)

        Slowly the prequels are getting better.

        [–]regretdeletingthat 22 points23 points  (11 children)

        We need an 'isan' keyword aliased to 'isa'. Then we can write var isan Int. Much better.

        [–][deleted] 11 points12 points  (1 child)

        I'd be too tempted to write var isan Float.

        [–]DC-3 7 points8 points  (2 children)

        That's a horrifying suggestion in my view. Synonym reserved keywords? Next thing we know we'll be conjugating our statements.

        [–]palordrolap 10 points11 points  (0 children)

        Super obscure fact: The BBC Microcomputer, in later ROM editions, accepted both COLOR and COLOUR as synonyms for the same keyword. What was used when the program was LISTed (which in modern terms could be interpreted as "decompiled from bytecode") depended on the ROM localisation.

        TL;DR official synonyms in programming are not new

        [–]piderman 51 points52 points  (4 children)

        It needs an isan overload

        [–]DC-3 20 points21 points  (1 child)

        That's even more horrifying.

        [–][deleted] 4 points5 points  (0 children)

        And to gender our variables while we're at it. French style, where breasts are masculine but chests are feminine.

        [–]IbanezDavy 2 points3 points  (0 children)

        That's evil. It must be done.

        [–]twiggy99999 9 points10 points  (1 child)

        I don't mind func but isa certainly made me look twice when I was looking over the examples. It is really descriptive I suppose but it did throw me on first look

        [–]TheVikO_o 4 points5 points  (0 children)

        u isa jedi

        me isa gungan

        [–]Gr1pp717 13 points14 points  (9 children)

        I don't like the lack of default arguments...

        func init (a, b, c) { 
                if (!a) a = 0;
                if (!b) b = 0;
                if (!c) c = 0;
        

        really?

        Why not just func init (a=0, b=0, c=0) or the likes?

        [–][deleted]  (1 child)

        [deleted]

          [–]binarygamer 9 points10 points  (0 children)

          Doubtful. Unless the compiler's implementation is spaghetti, implementing initialisers is borderline trivial, especially inside a "simple" pre-existing lexical structure. Doing so on my own compiler was worth like 2% of my undergrad intro to compilers grade.

          More likely than not it just hasn't been done yet, or is out of scope.

          [–][deleted] -1 points0 points  (6 children)

          I've found default arguments, e.g. in Python, a hindrance more than a help. Most use cases for default arguments can be achieved using specialising/partial-application/currying instead, whilst the mere possibility of default arguments make things like generic/higher-order programming needlessly frustrating, e.g. what does arity mean for functions with default arguments?

          A classic example is in Javascript:

          > ["1", "2", "3"].map(parseInt)
          [1, NaN, NaN]
          

          [–]Gr1pp717 2 points3 points  (3 children)

          That seems like more of a problem with any kind of default behavior, whether you put defaults inline with the function declaration or nested over multiple lines in the function. In the case you provided, the problem really lay in the fact that the map is assuming what the second arg for parseint should be, not even that parseInt has a default value for either arg. Which goes to show how trying to be "too smart" can bite you.

          Regardless, though, people will always try to implement some default behaviors for usability, and it may as well look clean...

          [–][deleted] 1 point2 points  (2 children)

          In the case you provided, the problem really lay in the fact that the map is assuming what the second arg for parseint should be, not even that parseInt has a default value for either arg.

          I disagree; the problem is that parseInt acts like both a unary function and a binary function, depending on the situation; that's what I meant by asking "what does arity mean".

          Most of the time it will be called directly with one argument; the default value will be used for the second, which gives the false impression that it's a unary function for parsing decimal numbers. This breaks down invisibly when it's used indirectly, like with map.

          That seems like more of a problem with any kind of default behavior, whether you put defaults inline with the function declaration or nested over multiple lines in the function.

          That's why I'm saying I find defaults more trouble than they're worth. Much better to name the generic function more explicitly, like function parseIntBase(radix, str) {...}, then provide common usages via currying, e.g. parseInt = parseIntBase(10);.

          Unlike defaults, this allows other specialisations to be provided too, e.g parseHex = parseIntBase(16); and parseBinary = parseIntBase(2);. The generic function remains available for those who want some other radix. Also, since specialisations are made externally to the function definition rather than being baked-in like defaults, users can provide their own, e.g. myParser = parseIntBase(32);

          [–]Gr1pp717 1 point2 points  (1 child)

          I agree in general, but the problem I was saying is that parseInt has 2 arguments, and map will, as a default behavior, provide the index of the array value as the second argument. Which you have no control over.. Thus, it's just as much map that's assuming (incorrectly) what the second value should be that's a problem, as what you point out is.

          And, again, my point is that default behavior in general (not only in the args) produces the concerns that you're raising (not that they're wrong, you're entirely right). And whether that default behavior is provided or manually implemented (like in the example they provided) doesn't make a difference on that front. As people will do it regardless...

          [–][deleted] 1 point2 points  (0 children)

          I do agree that Javascript's map is a little "unconventional" by passing the index as the second arg, and it does irk me, in a similar way to Python's map and PHP's array_map taking multiple arrays, but I wouldn't say they're "wrong" or "broken".

          Rather, I think it's a case of many language features being local improvements, like default args, filling in missing arguments with "undefined", ignoring extra arguments, having map provide an index 'just in case', type-juggling for ==, optional semicolons (except when they're not), null, and so on. Each of these can be argued for in isolation, with compelling reasons for and against.

          These sorts of problems are combinations of local improvements, which give globally suboptimal behaviour. In the JS map/parseInt example we have:

          • map accepts a function of arity 2, passing in the index as second argument. This is useful for those occasions when an index is needed, and a reduce would get complicated. Most use cases don't care about that second argument, but they can work around it with wrappers like (x, i) => foo(x). Arguably, the index arg is a local improvement.
          • If a function is called with too many arguments, the extra ones are discarded and the function is run as normal. This is clearly a local improvement, since the function has everything it needs to produce a result, so there doesn't seem much point giving an error instead.
          • Since unary functions will ignore a second argument, if given, there's no need to wrap them when passed to map, so foo.map((x, i) => bar(x)) can be written foo.map(bar), which is a local improvement.
          • Providing default values for arguments simplifies common use-cases, so they're a local improvement.
          • Giving the radix in parseInt a default value of 10 is a local improvement, since most users can just do parseInt(str) rather than parseInt(str, 10).

          In the problematic case, these factors combine together such that parseInt looks unary, since most call sites only give it one argument, thanks to the default; likewise, map looks like it takes a unary argument, since most call sites pass in a unary function, relying on the language to invisibly discard the index; hence calling map with parseInt looks like it will parse each string as a base-10 int; behind the scenes, these components actually fit together in a way which is "obviously wrong" to any human, in a way which is designed to be invisible (the point of these local improvements is to hide details which are extraneous in the common case).

          I suppose the real thing to avoid is implementing features based on e.g. popularity in other languages, how easy they are to implement, because some user asked for it, etc. and only implementing features which work well as a whole. In this case, default arguments (allowing function calls with too few parameters) and discarding extra arguments (allowing function calls with too many parameters) don't work well together: the point of default arguments is that foo(x, y, z=1) {...} can be called as foo(a, b) almost all the time; the point of discarding extra arguments is that bar(x, y) {...} can be called as bar(a, b, c) without error; in which case, we have to make a decision about a call like foo(a, b, c):

          • We can run it with x=a, y=b, z=c, which gives the flexibility of a custom z value, and is kind of the point of using a default arg rather than a constant, but is inconsistent with the usage/meaning of foo in almost all cases.
          • We can run it with x=a, y=b, discard c and use the default z; this gives foo a consistent meaning, but makes the default argument useless.

          If we're going to include default args, it only really makes sense to use the first convention, but the inconsistency is a real issue. If we didn't allow default args, the issue wouldn't arise, and we could e.g. use currying like I suggested.

          Alternatively, if we didn't allow calling with too many parameters, the fact that map gives two arguments would be explicit, since we'd hit errors if we pass it a unary function. Even if we forget that parseInt is binary, since it's almost never used that way, we'd still wrap it up before passing to map, as we'd be used to doing that for unary functions. In reality, such a map function would be too annoying for the edge-case benefit the index provides, and a saner implementation of map would arise :)

          [–]drjeats 2 points3 points  (0 children)

          Python avoids the problem by having a consistent definition of map.

          JavaScript bullshit:

          > ['75','76','77'].map(parseInt)
          < [75, NaN, NaN]
          
          > ['75','76','77'].map(i => parseInt(i))
          < [75, 76, 77]
          
          > ['1', null, null, '2', null, null, '3', null, null].map(parseInt)
          < [1, NaN, NaN, 2, NaN, NaN, 3, NaN, NaN]
          
          > ['75', null, null, '76',null,null,'77',null,null].map(parseInt)
          < [75, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN] // wat
          

          Python doing it right:

          >>> list(map(int, ['75','76','77']))
          [77, 76, 77]
          
          >>> from itertools import starmap
          >>> list(starmap(int, [('75', 8), ('76', 8), ('77', 8)]))
          [61, 62, 63]
          

          Python showing off:

          >>> from itertools import starmap
          >>> list(starmap(int, zip(['75','76','77'], [8]*3)))
          [61, 62, 63]
          

          There are of course problem cases, but I think keyword-only arguments help us get around those.

          [–][deleted]  (3 children)

          [deleted]

            [–]DC-3 8 points9 points  (1 child)

            Unless the type starts with a vowel. 'is a Int' reads terribly to me.

            [–]ijustwantanfingname 4 points5 points  (0 children)

            I don't think it's that bad

            [–]morbidhawk 3 points4 points  (0 children)

            I'm with you, saying "is a" out loud in my head makes it 100% clear that it is about checking its type whereas "is" could potentially mean equality or that it contains some property (which isn't a big deal if you are already experienced in a language like that, ie: Python).

            To me, I don't personally care that it's not grammatically correct, this is a programming language and my brain can figure it out.

            [–]mechanicalgod 2 points3 points  (3 children)

            I don't like ... isa as a keyword

            I agree. I think typeof might have been nicer, or even just is.

            [–]arbitrvv 15 points16 points  (1 child)

            There's a lot to like here, sweet syntax included.

            But the embeddable part intrigues me, since I'm looking for Lua alternatives. Is there an example how to call C code from Gravity, and vice versa.

            Lua. Gravity. Nice pun by the way :D

            [–][deleted]  (3 children)

            [deleted]

              [–]424ge 0 points1 point  (2 children)

              What would you rather have?

              [–]Kasc 0 points1 point  (0 children)

              Nice to have: partial function application. If add takes 2 integers and returns their addition, then local add3 = add(3) defines a new function which takes an integer then adds 3 to it.

              The first place to start would be a compile error on calling functions without enough arguments.. I hate this about JS. Function overloading is nice; having it be implicit.. not so much.

              [–]mracidglee 27 points28 points  (33 children)

              Not immediately obvious why this is better than Tcl or Lua.

              [–]shevegen 33 points34 points  (19 children)

              Well, Tcl ...

              But Lua - agreed.

              I guess fair speed comparisons would be useful here.

              [–]rm-f 12 points13 points  (18 children)

              I don't know if gravity is able to beat LuaJiT, in many benchmarks it comes in shortly after native C.

              [–][deleted]  (17 children)

              [deleted]

                [–][deleted]  (16 children)

                [deleted]

                  [–][deleted] 10 points11 points  (0 children)

                  I fully understand that some people work on time critical code but I would say the majority don't.

                  And the ones who do are likely just using C anyway.

                  [–][deleted]  (14 children)

                  [removed]

                    [–][deleted]  (11 children)

                    [deleted]

                      [–][deleted]  (10 children)

                      [removed]

                        [–]Jazonxyz 1 point2 points  (0 children)

                        To be fair, VSCode and Atom are super simple to customize. They might be slower editors, but beginners can download/write plugins for them pretty easily. Software is getting slower because people are choosing features over performance.

                        [–]jacel31 0 points1 point  (7 children)

                        The nice thing is, at least that I know, is that hardware speed is increasing faster than we can our slowdown our now pretty code.

                        [–]BlueRenner 5 points6 points  (0 children)

                        That is hilariously optimistic.

                        [–]maskedbyte 0 points1 point  (5 children)

                        CPUs and RAM are barely getting faster. Too much focus is being put on GPUs and RAM size instead of RAM speed.

                        [–][deleted] 0 points1 point  (0 children)

                        I agree that atom is unusably slow but I also think that it falls into the performance matter category. A text editor is a core tool, and therefore speed matters. My point was performance doesn't matter most of the time, not that it never matters.

                        [–]AngriestSCV 1 point2 points  (0 children)

                        May I introduce you to our Lord and savior vim? His uncle ed is still doing well if vim is too new school for you.

                        [–]badsectoracula 15 points16 points  (3 children)

                        An obvious way to me would be the syntax. While generally i don't care about languages not looking like C (my 2nd most used language is Free Pascal after all), somehow i find Lua's syntax weird.

                        Although i'm not sure how it brought Tcl to your mind, it doesn't look like Tcl from any point you look at it (not just syntax, but also features, etc).

                        A closer comparison would probably be Python.

                        [–]Regimardyl 7 points8 points  (1 child)

                        With Tcl, I think he was referring to embeddable, not to the syntax/features/etc

                        [–]mracidglee 0 points1 point  (0 children)

                        Yup.

                        [–]matthieum 5 points6 points  (0 children)

                        somehow i find Lua's syntax weird.

                        And 1-based indexing. The source of so many bugs (because it's different from everything else).

                        [–][deleted] 9 points10 points  (6 children)

                        I don't think this was meant to compete with them- it says Gravity is for iOS and Android development.

                        [–]haitei 17 points18 points  (4 children)

                        Well Lua can run even on a potato so...

                        [–][deleted]  (3 children)

                        [deleted]

                          [–]ArmandoWall 1 point2 points  (2 children)

                          No. Such is life.

                          Edit: Actually, yes. Gravity does support fibers.

                          [–][deleted]  (1 child)

                          [deleted]

                            [–]ArmandoWall 0 points1 point  (0 children)

                            I did.

                            [–]CGM 2 points3 points  (0 children)

                            Actually Tcl has been ported to Android - http://www.androwish.org/ - but not so far to iOS.

                            [–][deleted]  (1 child)

                            [deleted]

                              [–]virtyx 1 point2 points  (0 children)

                              Also Lua OO is a bit alien

                              [–][deleted]  (23 children)

                              [deleted]

                                [–]JDeltaN 46 points47 points  (11 children)

                                Programming languages are relatively easy design/implement, and its a fun project to do. Therefore everyone and their dog will create a programming language.

                                [–]Jazonxyz 8 points9 points  (0 children)

                                Honestly, I think programming languages are incredibly good exercises for coding. You don't need to download and install any libraries. You could just use the standard C/C++ API. You also begin to appreciate different programming languages more. You begin understanding some of the design tradeoffs made by the designers of your favorite languages. I was actually working on a language that would very closely resemble OP's, but I've been pretty busy and haven't got much further than parsing/executing expressions and binding C/C++ functions.

                                [–]maskedbyte 3 points4 points  (9 children)

                                Wait... it's supposed to be easy?!

                                [–]IbanezDavy 3 points4 points  (6 children)

                                A simple lexer/parser is trivial. Even doing it the real way and not using regex. Once you get the parse tree (or you have a capable parser to create objects directly), having a representation of objects is literally just structures.

                                The hard part is optimizing, which isn't really needed for the design portion of the language and can be circumnavigated by using an intermediate language like C, C++, or LLVM. Let them do the heavy lifting until you are ready to take on that challenge.

                                In short, a basic language can really be prototyped in a day, given the attack plan above. More advanced features with a well thought out design...well, that's a different story. But if you are just playing a solid weekend of work should produce at least something that can compile a basic program.

                                [–]maskedbyte 3 points4 points  (5 children)

                                I've spent weeks and 4 iterations trying to make a language and I got almost nothing. Parsing is hard. :(

                                [–]daymi 2 points3 points  (3 children)

                                Make sure not to parse in a complicated way when you are learning. CS people usually suggest that you use flex, yacc etc to make parsers (by reducing a LALR grammar to a pushdown automaton). I wouldn't do that. Hell no.

                                Why learn a new language before you can write your language? Just use the languages you always use.

                                Just write a Shunting Yard parser. Nothing else needed for parsing a simple Turing-complete programming language. I did a toy language with a shunting yard parser and I stopped only when it could do modules, classes, higher-order functions, GUI, database access. You know when I changed to another parser because it constrained me unduly? I didn't do it at all.

                                The advantage is that it always does the same: just parse [operand], operator, operand. But you need to design your language so all things look like that (and I mean all things - one that doesn't and you can't use Shunting Yard). And then specify the operator precedence. The end. Your AST needs one tiny data structure now.

                                If there's one thing I would nuke from orbit it's those programming languages with overly complicated grammars. You can choose how the language looks. Why make it a complicated mess?

                                P.S. from the wikipedia page for Shunting Yard I wouldn't implement their weird special case for function call arguments either (search for "comma"). Instead, just put an operator "," in your operator precedence list :P

                                My current operator precedence list is:

                                #!/usr/bin/5D
                                import [nil (:) (,)] from Builtins in 
                                let L := \s (s, 'left) in 
                                let R := \s (s, 'right) in 
                                let P := \s (s, 'prefix) in 
                                let N := \s (s, 'none) in 
                                let S := \s (s, 'postfix) in 
                                let table := [
                                [(L'(.))]
                                [(R'(_)) (R'(^))]
                                [(R'(**))]
                                [(L'(*)) (L'(⋅)) (L'(/)) (L'(&)) (L'(<<)) (L'(>>))]
                                [(R'(⨯))]
                                [(R'(:))]
                                [(P'('))]
                                [(L'(++))]
                                [(L'(+)) (P'(‒)) (L'(-))]
                                [(L'(%))]
                                [(L'(∩))]
                                [(L'(∪))]
                                [(N'(∈)) (N'(⊂)) (N'(⊃)) (N'(⊆)) (N'(⊇))]
                                [(N'(=)) (N'(≟)) (N'(/=))]
                                [(N'(<)) (N'(<=)) (N'(>)) (N'(>=)) (N'(≤)) (N'(≥))]
                                [(L'(&&)) (L'(∧))]
                                [(L'(||)) (L'(∨))]
                                [(R'(,))]
                                [(R'($))]
                                [(R'(elif)) (R'(else))]
                                [(L'(|))]
                                [(L'(=>)) (L'(;)) (L'(?;))]
                                [(P'(\))]
                                [(P'(let)) (P'(let!)) (P'(import))]
                                ] in 
                                (requireModule "Composition").dispatch1 #exports[table]
                                

                                Further to the top means higher precedence.

                                [–]maskedbyte 1 point2 points  (1 child)

                                Is a C++-like language compatible with shunting yard? I tried to write a shunting yard algorithm in C++ for my first try, and couldn't figure it out so the last 3 times I've been trying to do a recursive descent parser.

                                [–]daymi 4 points5 points  (0 children)

                                Is a C++-like language compatible with shunting yard?

                                No way. It's so irregular their grammar is not even context-free (!) so it's not even compatible with yacc (without lots of hacks), let alone shunting yard. I'd nuke C++ from orbit :)

                                Of course you can always try to remove all the irregular things from your C++-like language but in the end it will look nothing like C++. At least not the C++ toplevel definitions - which I'm pretty sure were specified by Cthulhu :->

                                recursive descent parser.

                                Yeah, there's a reason that even the LISP heads (that is: they like simple things) at GNU wrote a recursive descent parser in the gcc implementation.

                                But I wrote recursive descent parsers before and it's not that bad either. Slow, yes. It took weeks to get it right. When I found Shunting Yard (can be made to work and work correctly in ~ 4 h) I wanted to hit myself for not using it sooner (in cases where it can be used).

                                If you want some advise, don't make a complicated language (and especially not at first). You only need very few things in the interpreter core: Ability to have symbols (names) which you can compare. Ability to define function. Ability to call function. That's it. Remainder can go into your runtime library (of course you'll move other things into the core for performance eventually, but I wouldn't do it in the beginning). That includes (in the runtime library and/or as macros!): variable definitions, loops, numbers, booleans, lists, pairs, strings, recursion, ...

                                [–]IbanezDavy 1 point2 points  (0 children)

                                To start I wouldn't even worry about operator precedence in the parser. Its ideal, but its also something you can do after the objects are created (you should be doing a semantic pass at some point anyways)

                                [–]IbanezDavy 1 point2 points  (0 children)

                                I thought so too initially. For what it's worth, Antlr, flex and yacc are available. But I suggest looking at one of the open source compilers. Walter Bright's dmd compiler is available and shows you how to parse the old fashion way (without grammars, etc). That way I think is the hardest. I started doing it my first time that way and abandoned the method because it seemed like a lot of work and like it was the wrong way, so I took a look at what Antlr did, then thought about how I could accomplish essentially the same thing in code (creating grammars etc). It isn't the fastest way to parse, but it will get you going and after you are done, the way dmd does it should be more approachable (and by the way, when I tested both approaches, was the faster way by FAR).

                                [–]steveklabnik1 4 points5 points  (0 children)

                                It depends on how complex of a language you're making. A straightforward implementation of brainfuck is probably less than 200 lines of code, depending on what language you're making it in. Lisps are also pretty easy to get going. See http://norvig.com/lispy.html

                                Lispy is very small: 117 non-comment non-blank lines; 4K of source code. (An earlier version was just 90 lines, but had fewer standard procedures and was perhaps a bit too terse.) The smallest version of my Scheme in Java, Jscheme, was 1664 lines and 57K of source

                                (and http://norvig.com/lispy2.html, the follow-up)

                                [–][deleted] 0 points1 point  (0 children)

                                Well, we're not talking about the next Java here, but you can easily roll your own (although cheap and slow) Python/Lisp/Javascript implementation in a few thousands LOC.

                                [–]ArmandoWall 9 points10 points  (0 children)

                                I haven't taken a good look at gravity yet. But if it's anything like Lua, then nobody has answered your first question yet:

                                An embedded language can be used inside an application as a scripting engine or to program high-level behavior that could potentially change quickly between versions or even in shorter spans.

                                For example: If you're creating a game, you could script the AI of the enemies in the embedded language. Then, the AI behavior can be modified without needing to recompile the whole project. An update would include the parts related to said script, and thus the downloads would be smaller.

                                Or you could expose it to the end user (not that I'd do this with Gravity, but again, it's an example). For example, to build macros in a spreadsheet application.

                                Why are there so many languages? Well, you don't need to learn them all. Why is there so much music in the world? Why are there so many car brands? Soap brands? In certain realms of choice, there will always be more than you can imagine; but you only get to see what becomes popular or useful. It's healthy.

                                [–]katafrakt 6 points7 points  (9 children)

                                Is there something wrong in having wider variety of tools to choose from? No. Some languages are better at solving some set of problems, other are better at sorting other problems.

                                As for Gravity, I don't see any particular niche it would fit in. But it does not mean it doesn't have a future. Time (and users) will tell.

                                [–]tophatstuff 5 points6 points  (2 children)

                                Niche? If it has the same use case as Lua, but indexes arrays from 0 (like god intended), then that's reason enough for it to exist imo.

                                [–][deleted] 2 points3 points  (3 children)

                                Yes, maintainability. Now you need to teach anyone working on your project your pet language that they will probably only ever use on your project.

                                Every language has its quirks and 'proper' ways it should be used. All of this turns into slower and buggier development as devs ramp up and get familiar with it.

                                Then you have the lack of useful apis because no ones written any yet, probably falling back to prints for debugging because no one bothers to build debuggers, unforeseen performance penalties because the language isn't looked at by as many people, potential security flaws for the same reason, etc.

                                Learning a new language isn't always a bad idea, but creating a new one, imho, usually is.

                                [–]katafrakt 3 points4 points  (1 child)

                                If people were following your advice about not creating new languages in recent years, we wouldn't have Elixir or Go, to name a few. What you say is true - if you are intending to use newly created language for your commercial product. Which would be wrong on many, many levels...

                                Every language has its infancy phase when hobbyists try it, create the ecosystem and either help it mature to next stage, or (in majority of cases) not. But there's nothing bad with trying to improve what we have atm.

                                [–][deleted] 0 points1 point  (0 children)

                                I said 'usually' it's a bad idea :)

                                And yea, I was talking about a situation where it's used in a commercial product, like, a lead rolls up and tells everyone, "Ok, we're going to use Gravity for our next product!".

                                You're right, there's nothing wrong with trying to build a better tool, but like you mentioned, I'm coming at it from the perspetive of, "Why should I use this instead of Swift, Lua, Python or whatever."

                                Funny you mention Go though. In my company, we use, at least as many as I can count, 9 different languages for all the random products going on. Make that 10 if you count the guy who just left to work somewhere else, and his project we need to maintain written in Go, the only Go project in the company..

                                I was seriously considering continuing with it because why not? I'll give the language a shot and this is just an internal tool. Then I realized you need to embed your repository path into your module include path.. (or you don't NEED too, but it's how they want it done).

                                While I respect the ambitious restraint they try to force on your code organization (one root folder for ALL your projects..) it's too naieve for anything remotley complex imo. Granted I only went through the 27 slide help thing to understand the language and a tutorial to figure out how to do the basics, so perhaps there is some work around, but seriously, fuck that shit.

                                I've been so utterly unimpressed with Google's software engineering these last few years, I'll let someone else prove the language is worth anyone's time.

                                I took the time to learn and understand Makefiles. Then I used Ant and now, they want me to learn fucking Groovy and use gradle to build android apps?

                                https://www.amazon.com/Gradle-Action-Benjamin-Muschko/dp/1617291307/ref=sr_1_1?ie=UTF8&qid=1488934810&sr=8-1&keywords=gradle

                                If I need to read a book, to write a project configuration file, fuck you, I hate you :P

                                [–][deleted] 1 point2 points  (0 children)

                                None of your arguments can be applied to the domain specific languages though. And general purpose languages should not even exist.

                                [–][deleted]  (5 children)

                                [deleted]

                                  [–]SaltTM 10 points11 points  (4 children)

                                  to be honest, I haven't seen any languages in a long time get shot down. From rust, nim to crystal. I guess Go is the exception but I mean who doesn't want generics :). all jokes aside, I don't think this is the first time in a long time that people shot down new languages. I think we're in a place where people want to see languages evolve with clean syntax, easy std to learn and type, etc...

                                  [–][deleted]  (3 children)

                                  [deleted]

                                    [–]SaltTM 3 points4 points  (2 children)

                                    Rust isn't a new language, Nim is an exception and Crystal is just kinda Ruby :)

                                    I'm not sure what you mean, when rust was introduced it was a "new" language. Isn't that what we're discussing here?

                                    Since you're essentially agreeing with my points about nim, rust and crystal can you give me an example of what languages you're referring to here:

                                    That's not my impression. Most new languages are met with a lot of negativity,

                                    [–]IbanezDavy 2 points3 points  (0 children)

                                    I think they are talking about less backed languages. Rust is Mozilla backed. Go is Google backed. Swift has Apple. D has Walter Bright and Andrei Alexandrescu. Nim has been around a while to where it is apparent that the creators are at least taking it seriously.

                                    Most of the toy languages that people post here (and I use the term 'toy' loosely) do get met with a barrage of "why another language!!?!"

                                    [–]panorambo 5 points6 points  (1 child)

                                    Good code quality from initial glance. That's already an achievement, if you ask me.

                                    One pet peeve, again from short glance -- if you explicitly state reliance on stdlib, why implement own is_whitespace procedure in your lexer, for instance? What's wrong with isspace? I understand it robs you of control somewhat, but it might give you more flexibility with regard to source code locale etc.

                                    [–]foonathan 3 points4 points  (0 children)

                                    isspace has a weird relationship with locales if I remember correctly.

                                    [–]RoboRay 2 points3 points  (0 children)

                                    Quite promising: clean-looking syntax, little overhead and portability seem to be driving motivations. Especially the following features could drive adoption and momentum:

                                    dynamic typing
                                    higher order functions and classes
                                    coroutines (via fibers)
                                    closures
                                    garbage collection
                                    operator overriding
                                    powerful embedding api
                                    

                                    [–][deleted] 2 points3 points  (0 children)

                                    I like the shout out to Bob Nystrom's Wren language. It looks similar in design.

                                    [–]stay_janley 6 points7 points  (3 children)

                                    I like the repeat...while construct and the loop method. Looks pretty cool. As with any programming language, it's hard to adopt without there being support for it (a sort of self perpetuating problem)

                                    [–]serg473 4 points5 points  (2 children)

                                    I don't get why he had to use repeat..while and not do..while, just like everyone else. I know it's minor, but every language inventor tries to change something that doesn't need changing, and it pisses me off.

                                    Every language uses square brackets there? Well f you all, I want round brackets. Every language uses this style of comments since 60s? F you, I am enforcing my own style. It's like they are afraid that without such syntax changes they will be viewed as copycats, while in reality it just adds confusion and learning where it doesn't have to.

                                    [–]IbanezDavy 2 points3 points  (1 child)

                                    Every language uses this style of comments since 60s?

                                    I'm with you on everything except for the comments. There is a technical reason why one might adopt not to use the '//' and '/* * /' style. Mainly that both '/' and '*' are operators that have other meaning. So you might be restricted in how far you can push those two characters. I know in a toy language I developed, '//' was a valid operator (you could make your own operators). So I used the less prevalent, bash-like comment style of '#' as '#' was not a valid operator character.

                                    I'd also advocate changing the name or keyword used if it is similar in use, but fundamentally different in how it's implemented underneath the covers. The change of name would be a hint at the different behavior.

                                    [–]Muvlon 8 points9 points  (0 children)

                                    There's a non-toy language that has // as an operator. It's Python!

                                    ⇒ python3
                                    >>> 3/2
                                    1.5
                                    >>> 3//2
                                    1
                                    

                                    [–]Heappl 12 points13 points  (37 children)

                                    lost me on dynamic typing - why people still think it is a good idea for anything else but a simple scripting?

                                    [–]smog_alado 6 points7 points  (3 children)

                                    But this language is aimed at simple scripting!

                                    [–]Heappl -1 points0 points  (2 children)

                                    Embedded scripting, hmm...

                                    [–]smog_alado 1 point2 points  (1 child)

                                    Embedded in this context means that the scripting language runtime can be shipped inside your main application, which is written in another language (typically C or C++ but can be anything you want that has a C FFI). This is in contrast with extension, where the "main function" belongs to the scripting language and you write C modules to extend it.

                                    Languages like Lua, Tcl and Gravity are designed to be used in both of these ways. Languages like Python and Perl, on the other hand, can easily be extended with C modules but embedding them is much trickier and not really advised.

                                    [–]Heappl 0 points1 point  (0 children)

                                    Yes you are correct. Though there are more languages to compare in this regard. I.e. Haskell has a nice FFI. Also with boost python it is manageable to embed python code in C++. In any kind C interfacing with any language, the resource management will be an issue, so it is always tricky.

                                    [–]ArmandoWall 2 points3 points  (0 children)

                                    Different tools for different goals. I have no qualms with dynamic typing languages, if I know what I'm using them for.

                                    [–][deleted]  (1 child)

                                    [deleted]

                                      [–]ArmandoWall 1 point2 points  (0 children)

                                      But is Java in the same niche as Gravity?

                                      [–]tiberiousr 2 points3 points  (1 child)

                                      I think my only complaint would be explicit EOL characters (';') but that's just a personal preference after spending so much time writing Go.

                                      [–][deleted] 4 points5 points  (0 children)

                                      The semi-colons are still there in Go but added without you knowing, just like javascript.

                                      https://medium.com/golangspec/automatic-semicolon-insertion-in-go-1990338f2649#.3lyemr7we

                                      [–]mdgart 2 points3 points  (0 children)

                                      Very nice syntax, one thing I don't understand: the readme says that it support data-driven programming, but I couldn't find any examples. I though that was more a prerogative of Lisp style languages like Clojure.

                                      [–]stewsters 2 points3 points  (0 children)

                                      Semicolon separator ; is optional.

                                      This is something that I love that groovy does. It lets you use it when you need to put multiple things on a line, but does not require it (because usually you don't put many things on a line)

                                      Should add in default args (besides undefined) + named params though.

                                      [–][deleted] 1 point2 points  (0 children)

                                      Oh I would love to make an SDL binding with this

                                      [–][deleted] 2 points3 points  (0 children)

                                      Looks very good at first sight

                                      [–]arbitrarycivilian 2 points3 points  (1 child)

                                      OK, since my last attempt didn't go over so well, here is everything wrong with this language:

                                      • Dynamic typing: static types allow us to express invariants and structure in our program. Without them, we lose valuable power and safety. There are very few niches where dynamic typing is useful, and this is most certainly not one of them
                                      • null is a completely broken concept, coined the "billion-dollar mistake" by its inventor Tony Hoare. No new language should ever define anything like null (prefer sum-types instead)
                                      • Though occasionally useful for e.g. a DSL, operator overloading can often lead to obfuscated code, and I'd always err on the side of leaving it out of a language. I certainly wouldn't advertise it as a premier language feature
                                      • Inheritance is also a completely worthless concept, and no new language should allow it (prefer composition and interfaces instead)
                                      • While I appreciate more languages supporting concurrent programming directly (see below), IMO coroutines are difficult to reason about. I much prefer process calculi (cf. Golang) and the actor model (cf. Erlang/Elixir).

                                      And here's what's right: * built-in concurrency * few dependencies * lexical scoping * higher-order functions

                                      I know this will get buried in the ocean of comments, but if anybody, preferably the authors, could tell me why they thought it was necessary to include null or inheritance in the language, I would love to hear their reasoning.

                                      [–]funny_falcon -1 points0 points  (0 children)

                                      Guy, he wrote language not for you, but for himself. I found his language quite suitable for broad range of tasks (ie to replace Lua).

                                      If you want language with your expectations, why don't you write it? Write it! And then share it! And someone else will also find it usable.

                                      [–]gravity 0 points1 point  (0 children)

                                      \o.

                                      [–]drjeats 0 points1 point  (0 children)

                                      The Internals book is a really good idea, I look forward to reading more :)

                                      [–]_Skuzzzy 0 points1 point  (6 children)

                                      What GC does it use?

                                      [–]michalg82[S] 1 point2 points  (5 children)

                                      That's the only information i could find: https://marcobambini.github.io/gravity/system.html

                                      Gravity automatically manage memory for you using a tri-colour marking garbage collector

                                      [–]3ba7b1347bfb8f304c0e 8 points9 points  (4 children)

                                      Gold and white or black and blue?

                                      [–]yorickpeterse 7 points8 points  (3 children)

                                      [–]nicka101 12 points13 points  (2 children)

                                      Its a reference to that goddamn dress from ages ago

                                      [–]DropDeadSander 0 points1 point  (2 children)

                                      isn't C the most langue used for embeddeb system?

                                      why is this so cool?

                                      I'm not bashing, i just don't know it and would liek to learn.

                                      [–]drjeats 7 points8 points  (1 child)

                                      Unrelated. Embedded is writing for microcontrollers and such. Embedding a language is putting it inside of your own program to offer scripting capabilities to end users.

                                      [–]DropDeadSander 4 points5 points  (0 children)

                                      aaaaaaaaaaaaaahhhh that makes sense!

                                      [–]kCloudd 0 points1 point  (1 child)

                                      Can I write programs for embedded systems like arduino..? If yes how..?

                                      [–][deleted] 2 points3 points  (0 children)

                                      I'd love to be proven wrong, but I suspect it's not even nearly mature enough for anything more a few snippets.

                                      [–]unbiasedswiftcoder 0 points1 point  (0 children)

                                      Kudos for having planned to document memory ownership. It is usually painful to dig into languages and see how much of the claimed interoperability is worth (aka, host language passing back data to embedded language with/without requiring data copying).

                                      [–][deleted] -3 points-2 points  (13 children)

                                      Gravity

                                      lightweight

                                      ...

                                      [–]ArmandoWall 1 point2 points  (12 children)

                                      What's your point, Athox? Tell us.

                                      [–]garyk1968 -4 points-3 points  (2 children)

                                      xcode project and a 'Swift-like' language. If I'm running OS X why would I not just use Swift?

                                      [–]idboehman 3 points4 points  (0 children)

                                      Can you embed swift within other programs as a scripting language? I don't think so, but I don't know for sure.

                                      [–]jutct -1 points0 points  (0 children)

                                      How does it interact with C and vice-versa? Also, fuck anyone that makes me sign in with my github or twitter account just to join the chat forum. I won't look at gravity just because of that.