
GorillaScript - jarek-foksa
http://ckknight.github.io/gorillascript/
======
egonschiele
Wow, some of these features sound really cool!

As a small complaint: After seeing about a dozen compile-to-JS languages, I
don't care about the full list of features anymore. Please add a big note at
the top saying how this is _different_ from other compile to JS languages. Why
save all the good stuff (typing, promises, currying) for the last half of this
massive page?

~~~
atroche
I came here to say this.

~~~
X4
I second that, just WOW. Someone wasn't satisfied with removing semicolons and
curly braces and fixed the ENTIRE language instead. WOW!!

------
mr_luc
Holy cow. It's built on macros, and macro-friendly! And I can use it with the
node.js ecosystem!

As a guy who built his own npm-installable macros.coffee, [0][1][2] I am torn.

I love macros enough that I felt I _needed_ to have them in JS-family
languages, which have few metaprogramming options outside of tricks on 'this',
which is why, when I saw that CoffeeScript had clean syntax and a relatively
clean AST, I made it my "learning node/npm" project to add them.

On the other hand, my project is simple because it depends on a fragile hack:
running a deep-copy on a chunk of AST for 'quote'. It's a fragile hack that
jashenkas could break with a single well-placed closure, and as I promised on
my project page, "If you want to ... build a substantially more 'heavy-duty'
implementation, I'll probably end up using yours." This isn't an
implementation in CoffeeScript, but it's better -- it's actually built into
the language (as macros work best as a core language component; once you have
'em, it's easiest to write your language with them).

I'll have to try out GorillaScript and see what it actually feels like to
write code in the language, allowing for the fact that its syntax may not be
as pretty as coffeescript yet. But I wouldn't be surprised to find myself
using GorillaScript this time next year.

Macros++.

\-----

0) github.com/mrluc/macros.coffee

1)
[http://mrluc.github.io/macros.coffee/docs/macros.html](http://mrluc.github.io/macros.coffee/docs/macros.html)

2)
[https://npmjs.org/package/macros.coffee](https://npmjs.org/package/macros.coffee)

~~~
cameronkknight
Interesting work. Once I refactored GorillaScript to be pretty much fully
macro-driven, it made everything super-nice to deal with. Every single syntax
construct in GorillaScript is a macro, even `if` and all that stuff.

------
cameronkknight
If anyone would like to look at the slides for a presentation I did on
GorillaScript, here you go: [http://ckknight.github.io/gorillascript-
presentation/](http://ckknight.github.io/gorillascript-presentation/)

In it, I discuss some of the design decisions. Sadly, there wasn't any video,
so I don't actually go in-depth in the slides themselves.

~~~
goldfeld
This looks like CoffeeScript had a baby with Rust, and I'm seriously tempted
to switch from the former for my latest project. It has all features for which
I am still considering adding specialist libraries to CS (promises, macros,
and a bunch of ES6 stuff.) Insanely great work! The latter parts of the slides
where one slide == one feature helped me have a feel for the language better
than the text docs.

------
bliker
I would prefer some compiled JavaScript ECMAScript 6 that and could be
compiled into compatible JS. So I can use all the goodness like classes and
iterators. Without having to deal with polyfills.

Please somebody...

~~~
aeosynth
[https://github.com/google/traceur-
compiler](https://github.com/google/traceur-compiler)

Requires a runtime, though.

~~~
bliker
It can be precompiled but it has not been optimized to do so:
[https://github.com/google/traceur-
compiler/issues/307](https://github.com/google/traceur-compiler/issues/307) It
seems the project is not very active.

~~~
aeosynth
It requires a runtime even after compiling:
[https://github.com/google/traceur-
compiler/wiki/CompillingOf...](https://github.com/google/traceur-
compiler/wiki/CompillingOffline)

> The code generated by Traceur depends on a small runtime library containing
> Javascript code for things like creating classes, handling spread arguments,
> etc. To use code compiled from Traceur, you'll need to include that too.

~~~
rattray
That doesn't sound so bad if it works well, though, right? Kind of like
including jQuery so you get cross-browser code.

------
bsaul
Massive work.congratulation for achieving this.

My main concerne is with optionnal typing ( which is my only real concern with
javascript at the moment ) : it says that types are checked at runtime.

Does this mean i still have to run unit tests that goes into all my code
before i can be sure i don't have a type error ?

~~~
cameronkknight
Yes, you would, at least in the current state of things. I do plan on adding
some compile-time checking (without getting in the way), but it's not there
yet.

------
mistercow
While this is an interesting effort, I can't help but be squeamish about the
sheer volume of JS that gets emitted (due to type checking) for what seem like
small amounts of input.

~~~
tel
Wait, the type checking isn't static?

~~~
cameronkknight
Currently, no. I do plan on adding warnings (not errors) on a statically-
calculated type issue. One thing is that I don't plan on it erroring if you
call a function with a value whose type might be an "any" type or a "union"
where it expects a specific type. If there's some overlap, it would allow, to
make things easier and give the programmer the benefit of the doubt.

Thus, the following would compile without warning:

    
    
        let double(x as Number) x * 2
        let repeat(x as String) x & x
        let fun(x as Number|String)
          if is-number! x
            double x
          else
            repeat x
        let fail(x as Boolean)
          // this should fail at compile-time
          double x
    

I could write the compiler to be a lot smarter and have it track types through
conditional branches (which would be very hard, but possible), or allow it in
those cases where it is possible that the types overlap.

I also might add a "cast", i.e. a runtime type check. I'm not sure what the
best syntax for it would be, but it would act like the following:

    
    
        CAST(x, Number) // validate that x is a Number or throw a TypeError
        CAST(x, Number|String) // validate that x is either a number or a string, otherwise throw TypeError
        CAST(x, Number, 0) // validate that x is a Number, otherwise evaluate to 0.
    

Of course, in the cases where `x` could not fit the type requested, then that
could error at compile-time.

I would love some feedback on this, especially from the perspective of "what
would I use to help me develop", not "I need my program to be 100% statically
type-safe without having to do any testing".

~~~
tel
The feeling of it reminds me a bit of Erlang's success typing, but I don't
know enough to say much more.

------
gregwebs
Wow, I wish this is what coffeescript was. This has most of the niceties of
coffeescript and adds immutability, types, and macros.

I will end up sticking with TypeScript though for anything at work since the
type system has more capabilities right now and it is just Javascript with
types so it is very simple to use for those with Javascript experience.

~~~
omaranto
What do you mean when say that you wish CoffeeScript was this? I mean
GorillaScript exists, so if you prefer it to CoffeeScript then use it rather
than CoffeeScript.

~~~
masukomi
The difference is that CoffeeScript has a massive amount of mindshare,
integrations, and tooling. GorillaScript may be better than CoffeeScript but
that doesn't mean that it's even remotely close in terms of day-to-day
usability. Because CoffeeScript got there first (and was decent) it's got a
huge head start on ANY other competitor.

~~~
wiremine
Yes, but that's like saying Perl got there first before Python or Ruby.
GorillaScript, CoffeeScript, TypeScript, etc. all basically use Javascript as
a platform, and there should be room for all of them in the long run. (Or, at
least room to let the market sort out which ones they like the best).

BTW, this got me thinking: are the Javascript envine vendors (V8, etc.) doing
anything to make it easier to write languages like GorillaScript or
CoffeeScript? Or is it all up to the language designers?

~~~
cameronkknight
They have made serious effort with developer tooling, especially with Source
Maps.

------
nnq
With such a kitchen-sink list of features, I can't believe he left out _named
parameters_ (seriously) and refinements (sarcastically).

Though this is definitely the best compile-to-JS language and I'd choose to
use it if I'll ever feel safe enough using anything else than plain
Javascript.

~~~
cameronkknight
For named parameters, this is the best one can do in JavaScript without
constructing a fully static type analyzer:

let use-named({ name, age }) ->

use-named(name: "ckknight", age: 25)

For refinements, what are you referring to?

~~~
nnq
Ah, destructuring is so sweet!

You're right, it's no real need for it and it's unfeasible because you need to
either (a) fully static type analyze everything or (b) what anonymous just
explained... and they're both out of the question.

The refinements thing was a joke, in the spirit of what else can one add: it's
a controlled form of monkeypatching / classboxing about which a lot of fuss
was made in the Ruby community after Matz decided to add it to the language
([http://timelessrepo.com/refinements-in-
ruby](http://timelessrepo.com/refinements-in-ruby)), mainly because it's very
hard to implement without creating more problems, even if you have your own
interpreter to hack on (short answer: don't bother looking about it and even
if you're smart enough to figure out a way to add it to a compile-to-JS
language, don't waste your effort on it - they're not an anti-feature and they
could make sense in languages that allow monkeypatching, like JS and Ruby, but
they're too much work for too little benefit and too much possibility for bad
use and unneeded complexity).

~~~
cameronkknight
Actually, here's a better example, if you want defaults.

Also nice is that it doesn't have to create a full defaults object at runtime,
and each binding would only be evaluated if individually needed:

    
    
        let func-with-named-params({
          id as String // TypeError if not a String
          metadata // don't care about type, defaults to void
          seed as Number = get-random-seed() // requires a Number, only calls function if not provided.
        }) ->
    

You can do all sorts of things with object destructuring.

Yeah, Refinements seem like a similar thing to extension classes in .NET where
methods defined somewhere else affect a class but only if included, without
polluting the globals.

The only possible way I could see supporting something like this is with a
different method call operator, so something like:

NOTE: The following is theoretical code. It does not work in GorillaScript
0.9.x, but might be implemented if there is enough positive feedback for it.

    
    
        refinement String
          def repeat(count as Number)
            if count < 1
              ""
            else if count < 2
              this
            else if count bitand 0b1 // if it's odd
              this->repeat(count - 1) & this
            else
              (this & this)->repeat(count bitrshift 1)
        
        // and used as such:
        "Hello "->repeat(5) == "Hello Hello Hello Hello Hello "
        // would turn into this code:
        String_$_repeat("Hello ", 5)
        
        let unknown(x)
          // This would throw a compile-time error, as x's type
          // would be unknown. It would have to be a single
          // named type that has a refinement defined, either at
          // the top of the file or with an import.
          x->repeat(5)
    

Also, refinements could have macros on them, so one could do

    
    
        "Hello"->for-code-point point, index
          // This is a body in a macro defined as "for-code-point" on a String refinement.
          do-something(point)
    

So, this would be a nice way to have refinements, but have the terrible
downside of requiring the type to be statically known.

You could also define a refinement on a union type or even an object type,
such as the following:

    
    
        refinement Array|{ length: Number }
          // define a getter, why not?
          def get median()
            this[this.length \ 0]
          
          macro loop
            syntax item as Identifier, index as (",", index as Identifier)?, body as Body
              index ?= @tmp \i
              AST
                let mutable $index = 0
                while $index < @length, $index += 1 // it knows that `@length` is a Number, no need to type checking
                  let $item = this[$index]
                  $body
    
          def each(callback)
            // look, we're using the macro we just defined!
            this->loop value, index
              callback value, index
    

The refinement namespace would not conflict with the normal invocation
namespace, so you could have `"Hello".same()` and have it be exactly as
expected, but `"Hello"->same()` not, because it would turn into
`String_$_same("Hello")` (or something like it).

To clarify before, the following would work:

    
    
        refinement Number
          // automatically knows it returns a Number
          def log(base as Number = Math.E)
            Math.log(this) / Math.log(base)
        
        let alpha = 1e100->log(10) // knows that 1e100 is a Number, obviously, and since ->log returns a Number, alpha is automatically known to be a Number.
        let bravo = alpha->log(10) // knows alpha is a Number, etc.
        let charlie = Math.pow(2, 10)->log(2) // since we know Math.pow returns a Number, we're good.
        let delta as Number = some-library.some-unknown-method()
        let echo = delta->log() // we specifically declared delta as a Number, so we can use ->log
        
        let foxtrot = [1, 2, 3]->median // Array subtypes from { length: Number }
        let golf = "hotel"->median // Hey, so does String!
        let india = arguments->median // And so does Arguments
        let juliet = { length: 4, 2: \kilo } // And so does this custom type
        let lima as { length: Number } = some-outside-source()
        let mike = lima->median
        // assuming I come up with a "cast" operator, i.e. type-
        // check with error or default value
        // this would allow a String, Array, etc., would check
        // at runtime (but not in production, with
        // DISABLE_TYPE_CHECKING set to true)
        let november = (some-outside-source() as { length: Number })->median
        // require that the result is an array, otherwise
        // evaluate to []. The default could be an expensive
        // operation that is only executed when necessary.
        let oscar = (some-outside-source() as Array = [])->median
    
        // unknown is of the "any" type, representing all
        // possible values, including null and void.
        let unknown = some-library.some-other-method()
        // Since unknown isn't at least { length: Number }, we
        // don't know that ->median should map to our refinement
        // { length: Number }->median and thus cannot be used
        // without casting.
        let wrong = unknown->median
    

I dunno, something to think about. Would people want to have this feature?

------
dlsym
1 & 2 == "12" \- Now THAT I call unexpected behavior. :-/

Interesting language though.

~~~
pogden
In what way is that unexpected, given then & is string concatenation?

~~~
onli
& is normally (= in C) a bitwise operator, not a string concatenation.
Especially looking strange for me when it makes a string out of two numbers.

~~~
cameronkknight
I never claimed for GorillaScript to be a C-like language, because at its
core, stripped of syntax, JavaScript is not a C-like language.

It more resembles LISP with its macros and closures with nice syntax built
around those concepts.

I tried to make all the operators match their closest arithmetic, mathematical
equivalents. Thus using `^` for exponent and `+` for addition. Since
JavaScript does not support bitwise operators cleanly, needing to cast to
int32 and generally being disued, I felt they could be better aliased with
`bit`, freeing up those operators. Since string concatenation needed some
operator as a building block for string interpolation, the freed-up `&` was a
ripe candidate for it.

That all said, string interpolation is the typical use case for creating
strings, so feel free to just use that if possible. Anything more than that
and you might need a templating engine.

~~~
X4
What do you think about not using any operator (but space+"") for
concatenation and using a syntax like this:

    
    
        var 1   = 5+5 // I would expect: Error 0-9 cannot be used as a variable
        var foo = "Hello " "Bob!" "\nAre you there?"
        var bar = "Hello " 1
    
        console.info(1) // throw error and refer to var 1
    
        console.info(foo)
        "Hello Bob!
        Are you there?"
    
        console.info(bar)
        "Hello 1"

~~~
cameronkknight
Juxtaposition as an operator is already used by function invocation, e.g.

    
    
        f "Hello"
    

If f were a string, how would I know I wanted to concat it instead of calling?

~~~
X4
By not making () optional. Honestly I get why people hate curly braces, but
parenthesis are important, removing them makes a new language hard to
understand, making it optional makes the language (horrible or) simply weird
and non-deterministic.

There is ZERO technological or efficiency related benefit in making ()
optional, it just makes your grammar parser more complex and slows down
compile/interpretation time.

If I would have time and no specs given, then I would write a compiler for
Sanskrit. It's one of the oldest languages and as accurate as AI Agent
languages. Really accurate. Just google for "Sanskrit Artificial Intelligence"
and you will find very interesting publications. Here's something by NASA:
[http://www.vedicsciences.net/articles/sanskrit-
nasa.html](http://www.vedicsciences.net/articles/sanskrit-nasa.html)

Btw. I've written a simple language+vm in C already using bison,flex etc. Our
Prof and other students made a custom CPU that runs on a custom OS made for
this language called Ninja. A friend of mine extended it by Object Orientation
later.

------
imslavko
I have no claim to be an experienced developer or so, just asking for
opinions: doesn't this huge number of complex features implemented in modern
programming language give you a feeling of something being wrong? And why?

~~~
X4
No it doesn't. It gives you freedom to do things naturally, but you will only
understand how to solve a problem naturally, when you've understood
"programming in general" or "Computer Science", without specifics to a
programming language.

To take fear away, you can easily create very very complex stuff with a single
language feature. Think about QBASIC, one would think that you cannot do
anything except some command-line programs with it. See the complete opposite:
[http://www.pcworld.com/article/2033318/black-annex-is-the-
be...](http://www.pcworld.com/article/2033318/black-annex-is-the-best-qbasic-
game-youve-ever-seen.html)

------
Zecc
>> x and= y - Same as if x then x := y

I'm having trouble imagining when you'd need to do this. But oh well..

>> There is also a short syntax for single-word strings that also convert
dashed-names to camelCase just as normal identifiers do.

I'd like to see an example of this. I don't think I quite understand what it's
meant to do.

>> Binding access

I would have preferred: f@obj (arg1, arg2, arg3) for function application
over: f@ (obj, arg1, arg2, arg3)

Other that that, I can certainly appreciate the huge amount of work involved
in creating this and I wish them success.

~~~
cameronkknight
and= isn't all that useful, I agree, but it would be odd to leave out given
that there's or=, ?=, ownsor=, etc.

\alpha-bravo-charlie == "alphaBravoCharlie"

Well, since GorillaScript doesn't require parentheses for invocation, you'd
need to have some delimiter between the context and the arguments or have to
wrap one of them. Why not simply just use "," as the delimiter and then you
can treat it as if doing .call/.apply?

~~~
Zecc
> Well, since GorillaScript doesn't require parentheses for invocation, you'd
> need to have some delimiter between the context and the arguments or have to
> wrap one of them.

Well, I was trying to think why you'd even need a delimiter. I thought the
absence of the comma between the context and the first argument would
disambiguate:

    
    
      f@x (a, b, c)

would be written as:

    
    
      f@x a, b, c  // Comma between a and b
    

While:

    
    
      f@(x a) (b, c)
    

would be:

    
    
      f@x a b, c  // No comma between a and b
    
    
    

Then again, a call like:

    
    
      f@ a b c d, e
    

would be ambiguous, so on second thought I think you've made the right
decision.

Heck, even the non-ambiguous cases seem easier to mentally parse with the
comma there.

So I retract from what I said. I should have thought this through before
posting.

Edit: I see you've also added the example of dashed-names to camelCase
conversion to the page. Thanks, that helps. Edit2: formatting.

------
__david__
So overall this is an interesting take on Javascript. I like that much of it
gets precompiled away (constants, etc). I'm not so fond of "&" being string
concatenation. I like Perl6's "_" better, it reads well. Also:

> || - or, can no longer be used with and unless one group is in parentheses

Seriously? Do you require the "+" and " _" operators to have parentheses
around them? Why do people think order of operations is hard with "and" and
"or"? I _really* don't get it (and _always_ turn off compiler warnings about
that when working with C).

Also, "ownskey" is a bit of a mouthful. Why not ".?" ("?." would be "get key
if object isn't null")?

~~~
cameronkknight
Most of the time, string concatenation is unnecessary with interpolation:
"$alpha $bravo" means alpha & " " & bravo.

The reason `and` and `or` are best in parenthesized groups is that it creates
confusion in the precedences otherwise. asking someone what `alpha and bravo
or charlie` means can be confusing if there's no obvious grouping (like a
standard mathematical operator's) giving `and` more precedence than `or` or
the other way around.

You actually can use `!.` as an "owns access", as used in `alpha!.bravo`,
which means `if alpha ownskey \bravo then alpha.bravo`.

And yes, `?.` means an "existential access", as used in `alpha?.bravo`, turns
into `if alpha? then alpha.bravo`.

You can also mix these with `?!.` and it works as expected. :)

~~~
__david__
The thing about "and" and "or" is that there _is_ obvious grouping--it stems
from boolean logic where there is an order of operations ('or' is like '+' and
'and' is like '\\*'). There's really no excuse to pander to people that can't
or won't memorize the order of operations for boolean logic.

BTW, I don't like coming across super critical, but this is a pet peeve of
mine. This particular issue really gets under my skin (I always pass
-Wnoparenthases to gcc). Overall I am very impressed with Gorillascript. I
love the macros, the functional programming stuff and the basic terseness of
it all.

------
grn
Looks very interesting! The features that caught my attention are:

    
    
        * immutable values
        * cascades
        * try/catch/else/finally
        * promises
        * async
        * optional typing
        * curreid functions
        * generics

------
girvo
This seems to fix every small issue and even a few large ones that I had
problems with in JS! It seems like it will be super easy to integrate with my
current "build tools" for the few dynamic languages I run (built into Komodo
as macros and plugins).

Heck, I could probably write the build tools plugins in Komodo WITH
GorillaScript. Of course, not quite the same as a brand new self-hosted
compiler, but I'd like to think that it's circular-referency is adequate to be
in the vein of functional programming tradition :)

I was never excited about Coffeescript. This is JavaScript: The Good Parts And
Even The Best Brand New Parts

~~~
cameronkknight
I'm very happy you're excited about it. The best thing you could do for me now
is to use GorillaScript to make something. Anything. Something big, something
small, something with fancy features or minimal ones. I want you to think
along the way "how could my life be easier?" "Better typing? Terser syntax?
More verbose syntax? Easier async support? Some other fanciful feature?"

Then, file issues on the GitHub tracker with your ideas to make GorillaScript
better for you. Or join us on IRC at irc.freenode.net at #gorillascript. I
(ckknight, author of GorillaScript) try to be there as often as I can, but I
do have a life outside of IRC, for now...

------
nubela
Why would I use this over coffeescript/underscorejs?

~~~
JuDue
Yes I'd like to know too. As the top post mentions, the documentation really
needs to hightlight the benefits over established popular libraries.

------
MichaelAza
This seems like the Python of compile-to-JS languages in much the same way
CofeeScript is the Ruby. Not a big fan of Python but I can see this becoming
popular with Python WebDevs.

I kinda hope this doesn't become a trend though, every web development
enviroment spawning its own compile-to-JS language. I feel that there are too
many such languages already.

~~~
nnq
I think it's closer to "the Scala of compile-t-JS languages" :) ...last time I
checked Python didn't have macros and syntax for currying, function
composition, piping etc. and its TIMTOWTDI philosophy seems closer to Ruby.

Honestly, the macros section scared me out, especially the "there are _five_
types of macro syntaxes" (...this is as far away from the pythonic way of
doing things as one can get) but this seems the most promising compile-to-Js
language I've seen.

~~~
cameronkknight
Macros can be scary. The need for five different syntaxes is because in a non-
homoiconic language, positioning and syntax matter, so having an infix
operator would be defined differently from a call-like macro. They all act
fundamentally the same, it's just how you define the syntax of how they are
used that is the difference.

------
mhb
When using this for development, what is the workflow? I write something in
GorillaScript, compile it and run it in the browser. Is there anything like
(GS) source level debugging so that I don't need to figure out the
correspondence between the GS source and the JS in order to, for example, set
a breakpoint?

~~~
bliker
That is where _source maps_ come into place. Not sure about support for GS
though.

~~~
cameronkknight
GorillaScript has full support for Source Maps, as any good compile-to-JS
language should.

------
aerolite
While this is actually really awesome, I think a lot of the nastiness of JS
can be dealt with by using a good JSHint plugin for your text editor (that
highlights errors/etc as they happen). Hoisting, function scope, ==, var,
using variables without defining them, etc - it'll catch many things.

~~~
cameronkknight
If I ever write JavaScript, then I definitely use JSHint. It doesn't help with
some things such as immutable local bindings, type checking, not having to
worry about hoisting, or any of the nice syntax features you get with
GorillaScript, which is why I see the benefit.

------
noelwelsh
Looks interesting.

The section on "Optional Typing" is too brief. Type inference is mentioned,
but there are no details on how the type system functions and what a failure
of type checking means. It seems one can't name types, which is odd and will
lead to a great deal of repetition.

~~~
cameronkknight
Types are allowed to be any of the primitive types (e.g. Boolean, Number,
etc.), null, undefined, any custom "class", a specifically-typed array (e.g.
[Number] for an array of numbers), or a specifically-typed object (e.g. {x:
Number, y: String}). I do plan on being able to alias the typed object as an
"interface", just haven't gotten around to that.

A failure of type checking generally means you get an early runtime error,
though I plan on reworking things to catch more at compile-time (while still
not being a pain).

~~~
tel
How do types work with objects and classes? Can you subtype?

~~~
cameronkknight
Yeah, class Child extends Parent

------
anonymous
Dashed-identifiers is probably my favourite feature. I've personally defined
the <leader>f chord to emit an underscore in vim just to save myself the
trouble of reaching all the way for a shift and a dash.

------
mwcampbell
I'm curious about why ckknight started this project instead of contributing to
Dart. I see that the syntax is more Pythonic than C-ish. What else
distinguishes this language from Dart?

~~~
cameronkknight
Dart reinvents a full type system for itself, with its own environment and
paradigms, and if you want to cross-compile to JavaScript instead of running
in a dart VM, you have to ship a huge swath of code with it to get it working.

GorillaScript works with the JavaScript type system instead of against it, at
least as well as it can, including supporting nice future additions like Map,
Set, and WeakMap.

GorillaScript tries to work within the JavaScript landscape as best it can so
that there is as little of a disconnect between GorillaScript and JavaScript
as possible.

------
Aqwis
Too bad it doesn't have list comprehensions. That's something I sorely miss
when writing most mainstream languages apart from Python. (I know CoffeeScript
has them.)

~~~
cameronkknight
Actually it does have list comprehensions. You just use a for loop (or any
loop) as an expression and it evaluates to an array.

------
alifaziz
There is also Embedded GorillaScript for templating
[http://ckknight.github.io/egs/](http://ckknight.github.io/egs/)

------
buster
Now this one really looks like a nice language!

------
mythz
Whoa, this actually looks really good. terse, robust and safety first, whilst
still packed with some high-level features.

~~~
modarts
Kinda like C# ;)

~~~
cameronkknight
Yes, I take a lot of inspiration (with some leeway for personal taste) from
Delphi and C#, so I have great respect for Anders Hejlsberg - who I'm now
competing with since TypeScript.

------
twiceaday
There is a small typo in "The outer this can also be captured _be_ appending".

~~~
roryokane
Filed a pull request fixing this:
[https://github.com/ckknight/gorillascript/pull/101](https://github.com/ckknight/gorillascript/pull/101)

------
nilved
Is this the same ckknight who made PitBull, Parrot etc?

~~~
cameronkknight
Yeah, I stepped away from the Lua world to work on JavaScript-related stuff.

~~~
mmgutz
The same guy who used to hang out on boo irc? Wonder if that's where the macro
ideas came from.

~~~
cameronkknight
Yeah, I hung out there. Also contributed a bit. No, most of my macro ideas
come from Scheme.

------
marcfawzi
"bitand" for bitwise & is weird

~~~
cameronkknight
Bitwise operators for JavaScript are unused except in special cases, as
JavaScript really doesn't handle bitwise as one might expect. Everything is
cast to either int32 (or uint32 in the case of >>>) and then recast back into
a Number (8-bit IEEE-754 floating point). Due to their relative lack of use,
freeing up the symbols to represent something else seemed prudent.

~~~
yoklov
I've seen them get quite a bit of use in graphical code, which is, well,
actually fairly common in JS.

Code that uses bitwise operations looks fairly ugly as is. Hav e you
considered enabling them with a prefix or suffix? E.G. ^$ instead of bitxor,
or >>$ instead of bitrshift...

~~~
cameronkknight
That could be possible, you could even do it today, if you wanted:

    
    
        macro operator binary ^$
          ASTE $left bitxor $right
    

There are also operators for `and`, `or`, `xor` which act logically. `not`
which does a boolean invert. So there are `bitand`, `bitor`, `bitxor`,
`bitnot` which fit well as working bitwise instead of logically.

I suppose the outliers are `bitlshift`, `bitrshift`, `biturshift`, but it does
somewhat make sense to keep the `bit` prefix because it casts to int32 and
because its operations are inherently bitwise.

