
Gravity: a new programming language and VM written in C - creolabs
https://github.com/marcobambini/gravity
======
dualogy
Quite promising: clean-looking syntax, little overhead, portability seem to be
driving motivations. Especially the following feature could promise adoption
and momentum:

    
    
        dynamic typing (not a fan myself, but for scripting: OK --- would be great if all such languages had a statically&strong-typed option --- after all the compiler/JIT needs to guess/work much less)
        higher order functions and classes
        coroutines (via fibers)
        closures
        garbage collection
        operator overriding
        powerful embedding api
    

Very neat- _sounding_. Will have to keep watch. Not as low-level as Go ( _can_
become wordy!), not as "foreign" initially as Rust (what, no GC, borrowing, a
borrow checker, what?), not (yet!) as "haphazard" as... the _majority_ of
shell-scripting/server-scripting/client/web-scripting approaches.

~~~
SomeCallMeTim
For simple apps, dynamic typing may be OK, but I'm always writing complex
apps, and static typing just seems like a minimum required feature for any
language I want to use for complex apps.

So I guess I'll stick with TypeScript or C# for writing my cross-platform
apps. The ecosystems for both are much more robust anyway.

~~~
dualogy
I think a problem is that complex apps are made with _scripting languages_.
This nasty practice seems to have finally become widespread habit in earnest
with Perl in the hey-days of CGI httpd, and then of course came along Python
and JavaScript and here we are!

I agree that strongly & statically typed languages allow for and indeed yield
more robust ecosystems and complex apps.

But scripting languages have their place, roughly at the level of
bash/.sh/.bat scripts IMHO .. the issue is that as LoB apps evolve from
"simple one-off experiments" and "just a quick'n'dirty prototype to see if-
and-how" to "mission-critical infrastructure" there just seems to never be a
good time for anyone to say "we stop here, let's transfer this to a more
stringent language early on first now, better today than too late".

Best would be if "scripting languages" actually had Haskell levels of type
inference, even if not the rich type system, this way there wouldn't be type
annotations (just like in scripting) BUT with a toggle-able "scripting-like
lenience" that can be turned off to make the type-checker brutal, or initially
during prototyping/scripting turned on by default to allow for ambiguous /
uninferable / defer-to-runtime-and-allow-unsafe-conversions RAD-style work.
With an additional middle-ground setting where it's still lenient but emits
console warnings to review potentially troublesome sections.

Someone should create a whole new scripting language just for that! Any
takers?

~~~
fho
IMHO Haskell is not a bad "scripting language", whatever that means. My
current project has lots of nice, composable blocks that get compiled in a
library project and I use stacks scripting feature to just glue them together.
Works for me.

~~~
SomeCallMeTim
Personally, I write games a lot, and I write apps with rich UI behaviors. Both
have a lot of inherent statefulness and imperative behaviors that are, in my
opinion, modeled better using a a language that at least supports imperative
structures. Both also benefit a lot from OO principles.

I also use functional concepts, and my code also ends up with lots of nice,
composable blocks, but being in a language that _forces_ functional concepts
where they don't fit is a recipe for unneeded complexity and unintuitive code.

Functional isn't a silver bullet. There Is No Silver Bullet.

~~~
fho
Naa ... without wanting to get into a religious war here: Haskell actually
provides an imperative "mode" (aka "do-notation"). But I agree about the
silver bullet thing ... I am/was a Java developer by trade and have written my
fair share of Python and C/C++ code. Haskell just clicked with me after
getting over the initial hurdles and is a good fit for the work I do (which is
processing about 400kEvents per second from a custom sensor).

------
chch
For a short moment, I hoped that this was about a revival of one of my
favorite non-Turing-computable esoteric programming languages, but I guess
that's of pretty low probability!

Unfortunately the original spec is long gone, but [1] at least mentions the
gist:

[1] [https://esolangs.org/wiki/Gravity](https://esolangs.org/wiki/Gravity)

------
weberc2
How does the feature set differ from [Wren][0]? Also, the syntax reminds me a
lot of Go.

[0]: [https://github.com/munificent/wren](https://github.com/munificent/wren)

------
marcoms
What's the argument for required brackets around if (conditions) and switch
(conditions)? To me they seem redundant.

\--

As a side point, I hope switch statements are less like C and more like Rust
(Rust happens to have better looking syntax, not just because its Rust):

    
    
        match <identifier> {
            <val> => {
                //
            }
        
            ..
        }
    

C-style always creates confusion on how to indent blocks following case
statements

~~~
david-given
Having tried this in the past with personal programming languages, I always
found I needed the parentheses to disambiguate control flow statements. You
end up with stuff like:

    
    
      if foo*bar baz()
    

...being parseable as either of these:

    
    
      if (foo) { *bar } baz()
      if (foo*bar) { baz() }
    

That example can be solved with enough lookahead but I think I found cases
where it couldn't be (although I can't bring them to mind). Terminator tokens
are another way to solve it, so you get Ada-style:

    
    
      if foo*bar then baz() endif
    

...or Go-style:

    
    
      if foo*bar { baz() }

~~~
erikpukinskis
If you stop putting multiple expressions per line it disambiguates too:

    
    
        if foo
          *bar
        baz()
    
        if foo*bar
          baz()

~~~
klibertp
That's only if newlines are meaningful in the grammar. In C and related
languages they are not, and where they are they tend to be a pain (the dreaded
semicolon insertion...)

And even if you make newlines meaningful you only trade one pain for another,
namely, you now need some kind of line continuation construct and lots of
special cases where newlines are allowed...

In short: it's not that simple.

~~~
erikpukinskis
Can't you just treat newlines like any other delimiter? Granted many tools
assume newlines, but you could just not use those tools, or replace newlines
with a placeholder so you can parse programs as a single line.

------
bpicolo
Says it supports Functional programming, but I don't really see functional
features. Seems premature?

I see what the goals of Gravity are, but are there any reasons I want to use
it?

Side note: not a huge fan of implicit self, i.e. class methods automatically
referring to "y" as the instance variable "y". I realize c# and Java do it,
but worrying about name elision at all is something I'm not a fan of. From an
ergonomics perspective, it makes editor autocomplete features slightly worse,
as a prefixed "this" or what have you can give it additional context vs
"anything in scope"

~~~
Tloewald
It supports closures and higher order functions. The sample code doesn't show
any of it.

It basically looks a lot like a subset of Swift designed to allow someone
familiar with Swift to get going faster with Creo. Creo looks interesting
mainly as a better integrated development experience than XCode provides.

~~~
catnaroek
Closures and higher-order _procedures_ do not a functional language make. It
has to be convenient to implement procedures that compute actual mathematical
functions.

Assume there exists a (pure) function `f` and a list `xs`. Does the following
expression always return `true`, or, at least, never return `false`?

    
    
        map(f, xs) == map(f, xs)

~~~
tomp
By this criterium Ocaml isn't functional either. Hell, even Haskell's not!

~~~
catnaroek
By this criterion, both Haskell and ML are functional. If you attempt to
compare values whose type doesn't support decidable equality testing, you get
an error, either at compile time (Haskell, Standard ML) or at runtime (OCaml,
arguably a design defect). And, if `f` is a pure function whose codomain
supports decidable equality testing, then `map f xs = map f xs` (or double
equals using Haskell syntax) is always true.

~~~
tomp
> And, if `f` is a pure function whose codomain supports decidable equality
> testing, then `map f xs = map f xs` (or double equals using Haskell syntax)
> is always true.

This statement is true in any language. So it's useless as a criterium for
determining which language is "functional" and which isn't.

Edit: except, of course, Haskell - `xs` could be infinite, in which case the
expression wouldn't be true (but bottom instead).

~~~
catnaroek
See for yourself:

    
    
        lolcathost% js17
        js> function twice(x) { return 2*x; }
        js> var xs = [1,2,3];
        js> var ys = xs.map(twice);
        js> var zs = xs.map(twice);
        js> ys == zs
        false
        js> 
    

Of course, the fundamental problem (in both Haskell and dynamic object-
oriented languages) is _types_ :

(0) Haskell doesn't have a type of lists. It has a type of potentially
infinite streams.

(1) Dynamic object-oriented languages don't have a type of lists. They have a
(dynamic) type of objects with physical identity, whose state (mutable or
otherwise) can be interpreted as a list.

ML is free of these problems. It has a bona fide type of lists. Of course, you
can also define a bona fide type of streams if you want to. Or a type of
dynamic objects with identity. And those will be different types.

~~~
ballenf
'==' or '===' is not an equality operator when used on objects (including
arrays) in Javascript. It's a reference equality operator: are the two
variables _referencing_ the same object?

There is no builtin object content equality binary operator in Javascript, at
least as of ES5.

~~~
catnaroek
Equality for objects means reference equality. That's precisely the problem
with object-oriented languages: you can't manipulate the values that you
really want, you have to manipulate objects whose _state_ is hopefully the
value you want.

------
JCDenton2052
What problem does it solve that is not solved already? What does it do better
than it is done today?

~~~
dbattaglia
Why does it have to do either of these?

~~~
carterehsmith
There is like 5,000 programming languages around.

If you "just" create another one, without any novel contribution to the
"languages" domain, you are basically just creating noise.

Nobody will use your language and nobody will write about it.

So.. .what is the point?

~~~
whistlerbrk
learning, but you're right about adoption of course

------
Entangled
Wouldn't this be better served with defaults?

    
    
        // constructor
        func init (a, b, c) {
            if (!a) a = 0;
            if (!b) b = 0;
            if (!c) c = 0;
            x = a; y = b; z = c;
        }
    

Like

    
    
        func init (a=0, b=0, c=0) {
            x = a; y = b; z = c;
        }

~~~
pmontra
Yes, but I guess it's only an example to demonstrate one liners and anything
would do. I prefer not to have to surround conditions with () and terminate
statements with semicolons. Plenty of languages demonstrated that it's ok.
However I don't know how that impacts the complexity of the compiler. I used
to know how to write one and reason about it but I spent my last 25 years
doing other things.

Nice touch to be able to do

    
    
        func + (v) { ... }

------
d--b
Has anyone tried this CreoLab thing? Any comment?

Here's the main use case:
[http://creolabs.com/gravity](http://creolabs.com/gravity)

~~~
chncdcksn
May be off topic, but did Apple remove their restriction on using a VM in an
app put on the App Store? Or was that restriction only for JITs and not
interpreters?

~~~
lobster_johnson
That was about JIT, i.e. generating native code.

~~~
Vendan
Also about interpreters, at least on iOS side, and they have relaxed that
slightly, though interpreters are still banned from running downloaded code

------
geofft
This looks like a language designed for use with a commercial product /
development environment ([http://creolabs.com/](http://creolabs.com/)).

I'm curious how well that works - I know that _used_ to be fairly common in
the '80s and '90s, but it feels like that hasn't been happening much of late.
The only very similar examples I can think of are Swift and Xamarin; Swift had
the advantage of a large customer base (everyone writing iOS apps), and
Xamarin was based on an existing, well-established language (C#). And all the
older big examples that come to mind, VB, Delphi, Objective-C, etc., were
variants of an existing language (Basic, Pascal, C, respectively), not a brand
new language.

Creo folks, are you finding that customers / potential customers are excited
about picking up the new language? I'd love to live in a world where there's
more work on programming languages (clearly, none of our existing languages
are optimal) but I'm not super optimistic.

------
seibelj
Cross-platform embeddable VM language written in C for iOS and Android?
Strange, I've been doing this for years using Lua...

~~~
salimmadjd
I really like what the company is doing with their other products, mainly
their design tool. It looks interesting.

But I have the same question as yours. Why not just leverage Lua. I wish they
made it clear what they're gaining. Maybe the end bundle size is smaller than
Lua?

~~~
vvanders
Lua is already incredibly compact, I agree in that I don't really see what
this is solving that isn't already covered by Lua.

~~~
redahs
Concurrency is always hard and fibers could be interesting, but looking at
src/runtime/gravity_vm.c It appears to be single threaded with max 1 fiber
running simultaneously per VM.

I think there is still a niche for something like a Lua/Erlang hybrid where
there is a real possibility that the VM will run high level code units on
multiple cores.

The other thing missing from Lua and LuaJIT which would be nice in future VMs
would be support for SIMD vector optimizations.

~~~
vvanders
Lua already has coroutines. I think if you're looking to peg multiple cores or
SIMD then your going to want to drop down to another language anyway.

~~~
redahs
I do use C, but my point is that it is feasible to incorporate both of those
features in an embedded VM, by using Erlang style actors for concurrency, and
by providing builtin vector types that use SIMD instructions where available.
If future language designers were to do so, they would be able to better
differentiate their language from Lua, which does not provide these features.

------
pkd
I think the main value of this project is hidden under the "internals" link of
the site. It discusses the construction of the language. Although it is
incomplete as of now - hopefully the pages get filled up.

[https://marcobambini.github.io/gravity/internals/](https://marcobambini.github.io/gravity/internals/)

------
kibwen
_> Swift-like syntax_

But the example doesn't show any Swift-like syntax... except for `func`. Other
than that, this is a dead ringer for Javascript.

------
andrewmcwatters
I'm totally biased since I love Lua and C, but this language looks great.
Really loving what it's putting down.

Edit: What's downvote worthy of this comment?

~~~
chc
Since you asked: This comment is pretty insubstantial. There's no comment on
what's good or interesting about this language, just "really loving what it's
putting down," which is pretty inscrutable as praise goes.

------
jlebrech
I've been looking for an embeddable language other than Lua to use in an
ncurses app.

------
gct
How's performance compared to eg: Python?

------
anilgulecha
// a represents a range with values 1,2,3 var a = 1...3;

// b represents a range with values 1,2 var b = 1..<3;

Ah! I wish they had gone for 1..3 and 1>..3 and 1..<3 and 1>..<3 to make it
easy to understand. The above would map to [1,2,3], [2,3], [1,2] and [2]
respectively.

Range operator quirks with ... and .. have to today be memorized and waste
developer seconds that add up to man-years.

~~~
ChristianGeek
Makes perfect sense to me...three characters define the range. Should be
1...3, 1>..3, 1..<3, and 1>.<3

------
aninteger
It looks nice but... How do you call into existing C libraries? I didn't see
an example of that.

~~~
emsy
[https://marcobambini.github.io/gravity/api.html](https://marcobambini.github.io/gravity/api.html)

Unfortunately, the reverse isn't covered yet (calling Gravity functions from
C).

------
amai
I like [https://nim-lang.org](https://nim-lang.org) more.

------
scott_karana
Any details about the runtime (or lack thereof)?

------
traviswingo
For those being negative about "yet another programming language," try
creating a lang sometime...it's a fantastic exercise and, in the very least,
will make you a much better programmer.

~~~
cwyers
This isn't some hobby project. This is a commercial offering, submitted to HN
by the corporate account of the company that created it. I don't see why
anyone should hold it to hobby project standards.

~~~
hnbroseph
> This is a commercial offering

looks like gravity an mit-licensed open source offering.

~~~
watty
I think he meant that it was created by a company for commercial reasons. Not
that it contains a commercial or non-commercial license.

------
eternalban
Well, they have an excellent 404 page:
[http://creolabs.com/404.html](http://creolabs.com/404.html)

------
pavfarb
"built-in JSON serializer/deserializer" near "closures" and "coroutines (via
fibers)" feels a bit.. odd. Sign of the times, I understand, but still.

Apart from this boring grumbling, the project is very interesting. Waiting for
internals
([https://marcobambini.github.io/gravity/internals/index.html](https://marcobambini.github.io/gravity/internals/index.html))
to arrive.

~~~
adrianratnapala
I think languages should have built in help for serialisation, though not tied
to a particular format. This is to get around the tension between automating
the process (avoiding boiler-plate) versus "gating" to validate and transform
data as it enters/leaves the domain model.

All serialisation frameworks I've seen map internal record types (structs,
objects) to an external schema, and write directly to record fields --
breaking down that "gate". What I would like is to map those schema to
something like a constructor/factory parameter list instead. (Python keyword
arguments come close, but the lack of typing means there is still no schema).

Serialisation libraries should confine themselves to converting between
(typed) key-value pairs and wire formats. Then there should be syntactic sugar
to help the transition between that plain-old data and the real domain model.

------
hubert123
It looks good, but no word on performance numbers or debugger or IDE.

------
snackai
Great, just what we needed, another programming language.

~~~
macintux
Pretty sure we had all the programming languages we needed by the late 80s.
Nonetheless, we need new perspectives on languages more than we need snark.

