Coder Social home page Coder Social logo

coffeescript's People

Contributors

alangpierce avatar alubbe avatar breckinloggins avatar cehoffman avatar codelahoma avatar connec avatar danielgtaylor avatar edemaine avatar epidemian avatar geoffreybooth avatar geraldalewis avatar hden avatar helixbass avatar jashkenas avatar jeremybanks avatar lydell avatar matehat avatar michaelficarra avatar mklement0 avatar satyr avatar sgentle avatar sstephenson avatar stanangeloff avatar thejh avatar trevorburnham avatar vendethiel avatar xixixao avatar ysmood avatar zdenko avatar zmthy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coffeescript's Issues

CoffeeScript in Rails

Would it be possible to call CoffeeScript compiling calls within a rails app itself and for the written CS code to be converted to JS on the server call? So instead of compiling a separate script, why not just write it natively in the rhtml <%= %> tags, or in the controller or in the helper? seems like a better use of CoffeeScript, especially for teaching or using Prototype or script.aculo.us

default arguments for functions?

It would be nice if we could have default arguments for functions like:

mymeth: a="abc", b="def" => a + b
or perhaps
mymeth: a: "abc", b: "def" => a + b

which would get translated to something like:
mymeth = function(a,b) {
a || (a = "abc")
b || (b = "def")
return a + b
}

what do you think?

Newlines inside expressions

So, Ruby has a nice behavior that ignores newlines that you obviously only inserted for formatting. I propose that this feature eventually be implemented in coffee-script, but considered low priority.

In the mean time, a newline escape character would be nice.

using the "in" operator

coffee script throws an error on:
alert("true") if 0 in ['adsf']

will we be able to use the in operator?

Also, if I have blank lines at the beginning of my file, coffee script throws an error.

Is there a coffeescript mailing list?

possible to add object comprehensions ?

I.e. something like

values: v for k,v in {a:1, b:2, c:3}

which gets converted to something like :

var __a = [], __b, __c, __d = {a:1, b:2, c:3};
for(var __b in __d) {
  __c = __d[__b];
  __a.push(__c);
}
values = __a;

How to deal with multiline code in loops

How should I covert something like the following?

for(var i in list) {
  .. multiple 
  .. lines of code
}

The only way I could figure with the array comprehensions was to pull out the multilines into a function, like so:

fn: i =>
    .. multiple 
    .. lines of code
  .

fn(i) for i in list.

ternary operator?

Are there plans to allow the use of the ternary operator in coffee-script?
I'm converting some code that uses it a lot.
Also, will "===" be allowed in the future? right now i convert them to "==" which coffee script converts back to "===".

SWITCH to COND

May I humbly suggest : http://dbj.org/dbj/?p=119
I kind-of-a- used/borrowed lisp (cond .... ). So:

switch day
       when "Tuesday"   then eat_breakfast()
       when "Wednesday" then go_to_the_park()
when "Saturday"
   if day is bingo_day
      go_to_bingo()
      go_dancing()
when "Sunday"    then go_to_church()
  else go_to_work()

Would 'compile' to :

      cond( day, "Tuesday", eat_breakfast, "Wednesday", go_to_park,
                "Saturday", function () {
                           if ( day === bingo_day ) go_to_bingo() ;
                           else go_dancing() ;
                  },
                 "Sunday", go_to_church,
                 go_to_work // default
               )() ; // execute the function returned

cond() is a very simple function and using it would result in cleaner and shorter JS code. I think.

--DBJ

Narwhal speed

having troubles with CS in interactive mode due Narwhal not finding coffee-script.js I used JSDB.org and it is much faster on small script (sorting an array)

time jsdb test.js

real 0m0.017s | user 0m0.010s | sys 0m0.006s

vs

time narwhal test.js

real 0m1.371s | user 0m1.098s | sys 0m0.150s

is there any plans in having other JS compilers added for interactive mode ?

Named Functions

For debugging purposes, it would be better if CoffeeScript generated only named functions, ie:

square: x => x * x.

Compiles into:

var square = function square(x) { return x * x; };

Questions:

Are there any namespace problems with this, if function names in different scopes collide? If so, what are the consequences (debuggers getting confused, perhaps)? Is it safe to take the final portion of the id as the function name when defining a function on a nested object?

String Interpolation

Ruby style interpolation would be awesome. E.g.

a: "dog"
b: ['f','o','x']
p = "The #{b.join} jumps over the #{a}"

compiles to:

var a, b, p;
a = "dog";
b = ['f','o','x']
p = "The "+(b.join)+" jumps over the "+(a);

or

var a, b, p;
a = "dog";
b = ['f','o','x']
p = ["The ",b.join," jumps over the ",a].join("");

Should be fairly easy to implement (guessing here)

lack of ternary operator

I've just been trying out converting some JS into coffee and the one thing that seemed a bit silly was converting the ternary operator stuff into some more verbose.

e.g instead of

x = qn ? do_a : do_b

x: if qn then do_a else do_b.

feels like we're going backwards there !

Real Iterator Semantics (please)

I know it is extending the run-time semantics of the language, but I think having real iterators instead of just arrays for comprehensions would be great.

CoffeeScript in CoffeeScript

I do not think that writing a compiler in JS is the right way to go. rather, it would be nice if the compiler would be implemented in Coffee-Script itself.

This way you will have a more "relaxed" environment to maintain the compiler and at the same time will be as portable as the generated JS code.

On the down side the compilation stage would not be the most straight-forward considering the stackoverflow-based file I/O in JS ;)

default catch return null with try

It would be nice to have a default catch:

x: try nonexistent * missing
try { x= nonexistent * missing } catch(e) { x = null } # or undefined ?

nicely mirrors the .try(:xxx) in Rails.

set variable for this

Many Javascript functions set this to self in their bodies. This enables the parent object to be referenced by inner functions, even when their scope is a different 'this'. JS example:

$("#xx").click(function() {
  var self = this;
  $(this).find(".y").blur(function() {
     // self != this
  })
})

A suggestion was made to automatically set a variable (__this_12345) to this, so that it could be referenced from inner functions.

There weren't many suggestions for syntax here, other than tying it in with the 'this' shortcut (see other ticket), which might be workable, but I'm not sure. It might be safer just to use another keyword (is self safe?)

Significant Whitespace

So, this is more intended for discussing the potential implications of implementing significant whitespace.

You said on reddit:

If you want to help with significant whitespace, that would be great. The basics are working over on the whitespace branch with a lexer similar to the one you describe, with INDENT, OUTDENT, and "\n" tokens. The tricky case is the one I mentioned above:

elements.each(el =>
  el.click(event =>
    el.show() if e.active))

The two outer functions need to be closed before the closing parentheses and big OUTDENT occurs. I'm a bit at a loss for how to implement this in the grammar.

If you produced two outdent tokens, that would work. The way to do this is deceptively simple.

Currently, I assume your lexer has some idea of a current indentation level, and if this increases, then an INDENT is produced, if it decreases, an OUTDENT is produced, and otherwise a standard \n is produced.

The way to adapt it is to instead stop caring about indentation and start caring about alignment. This is how haskell does it to great success. Most of my examples in code will not be in ruby but a haskell-like, so hopefully you know haskell.

The way to implement it in your lexer is to have a stack of indentations. Looking at this example:

a
  b
  c
     d
         e
     f
g

This should be grouped like this:

a(b c(d(e)f))g

So, let's follow through with my stack indentation idea and see where that goes.

First we have a, it is at zero indentation level, so we lex that as usual. Next, we have an INDENT of two spaces, so we push 2 to the stack, then emit the indent token as per usual:

2:[] -- stack 
a INDENT

Then, we lex b. c isn't a INDENT or OUTDENT so the stack is unchanged and c is lexed as per usual.

2:[]
a INDENT b NEWLINE c

Then we have an indentation of 3 spaces, so we push 3 to the stack, and emit an indent token as per usual.

3:2:[] -- stack
a INDENT b NEWLINE c INDENT

Then, we have d, which we lex as per normal, then an indent of 4 spaces, so we emit an indent and add to the stack.

4:3:2:[] -- stack
a INDENT b NEWLINE c INDENT d INDENT

Finally, we lex e, and then we have the fun stuff. We first have an outdent of 4 spaces. If this outdent was anything less than 4, we'd throw an error. As it is, it is equal to 4, so that's fine. We subtract 4 from the top of the stack, and get zero.

 0:3:2:[] -- stack
a INDENT b NEWLINE c INDENT d INDENT e 

Then, we pop the zero off the stack, and emit an OUTDENT token. We also lex f as per usual.

3:2:[] --stack
a INDENT b NEWLINE c INDENT d INDENT e OUTDENT f

Finally we hit the major hurdle you were facing. We have an outdent of 5 spaces. So, we generalise the above algorithm and subtract 5 spaces from the whole stack, starting at the left:

0:0:[] -- stack
a INDENT b NEWLINE c INDENT d INDENT e OUTDENT f

Then, for each zero at the top of the stack, we emit an OUTDENT
[] -- stack
a INDENT b NEWLINE c INDENT d INDENT e OUTDENT f OUTDENT OUTDENT

Then, we lex g

a INDENT b NEWLINE c INDENT d INDENT e OUTDENT f OUTDENT OUTDENT g

Note, if i replace INDENT with ( and OUTDENT with ) and NEWLINE with a space, then you get:

 a(b c(d(e)f))g

Which is the exact grouping we wanted.

This way, you get exactly 1 OUTDENT token for every INDENT token. Hope this helps.

inline comments

Currently the following produces an error
x: 1 # hello

Presumably that's not a feature ?

falsyness of zero, empty string, null and undefined.

Javascript has rather too many falsey values (IMHO), namely: null, 0, false, "", undefined compared with Ruby's nil, false

This is an odd behavior since it means that !0 == true and !"" == true, resulting in some odd bugs, if you're not careful.

CoffeeScript actually makes matters slightly trickier since it no longer coerces null and undefined together, with ==

Now I don't know if anything can actually be done, but I thought I'd throw it out there - see if anyone has any clever ideas on the matter

multiline chainable methods

in coffescript isn't possible make multiline methods chainable alla jquery:

example

$(".team")
.find("player")
.css("color","#000000")

give this error:
syntax error for '.', unexpected property_access

Unary Minus

If I write:

(3 -4)

This gives a syntax error. The unary minus should be handled in the parser not the lexer.

Support for Ruby-style symbols

one: :fish
two: :fish
red: :fish
blue: :fish

There's only one instance of :fish.

Although, as we see here, the Ruby syntax doesn't mesh very well with the CoffeeScript :-assignment syntax. There are other symbols that could be used, but : is nice because it's not too "wide-looking".

closures in coffee-script?

How would this be done in coffee-script:

tester = (function() {
var a=10;
console.log("in outer");
return function(b,c) { console.log(a + b + c) ; }
})();

something like? :
tester: =>
a=10
console.log("in outer")
anon: a, b => console.log(a + b + c)
()

shortcut syntax for this. and prototype.

Suggestion, as this. and prototype. are typed alot in JS, it would be useful to have a shortcut.
E.g.

@var  compiles to this.var
Animal@move compiles to Animal.prototype.move

Other suggestions were to use .. or ::. @ has some parity with Ruby.

OMeta JS 2.0

#1)
Started a JavaScript version of the compiler using OMeta JS 2.0:
http://www.tinlizzie.org/ometa-js/#Coffee

Currently sub-classing the Javascript Compiler, so it can execute CoffeeScript aliases or JavaScript, but may need to redo it as a complete compiler in order to do CoffeeScript Statements.
Not sure how much time I'll have to work on this, so anyone else is welcome to to take it over.

#2)
Suggest that Objects should be either CoffeeScript format OR standard JSON format to make it easier to read JSON directly without parsing to CoffeeScript or visa versa.

With the newlines it looks good, but I think
ages: {max: 10, ida: 9, tim: 11 }
is slightly more legible than
ages: { max: 10 ida: 9 tim: 11 }

#3)
In your Docs [ http://jashkenas.github.com/coffee-script/#array_comprehensions ]
Suggest you change the example from:

Eat lunch.

lunch: food.eat() for food in ['toast', 'cheese', 'wine'].

to something like:

Eat lunch.

lunch: eat(food) for food in ['toast', 'cheese', 'wine'].
eat: edible => log("yum: " + edible).
log: msg => if (window && window.console) console.log(msg) else alert(msg).

This works better than having to define eat in String.prototype.eat
Otherwise you end up eating Strings instead of Food! ;-)

adding ? and ! to methods

It's incredibly useful in Ruby to be able to end methods with ? and ! We could rewrite the variable names to include these as text. E.g.

exists?: x => typeof x != 'undefined' && x != null
merge!: x, y => x = x.merge(y)

compiles to

exists__question = function(x) { return typeof(x) !== 'undefined' && x !== null }
merge__exclamation =  function(x, y) { return x = x.merge(y) }

I realize that there's a clash with the existence operator here -- but it would be really useful and we could come up with another operator for existence e.g. if ?obj or if obj??

Convert Ranges to Array as expressions?

Would it be useful to allow ranges as expressions that are inline converted into arrays ?
E.g. alongs these lines.

t: [0..6]
var t = []
for(var __a = 0;__a<=6; __a++) {
  t[__a] = __a
}

require, dependency management, load paths and all that jazz

Currently there isn't any way for several CoffeeScript files to interact with each other, since everything is done in a closure. That's a good thing, but would make it difficult to build large applications.

What if we add a load path and require statement to coffeescript, which would automatically compile the required files into the JavaScript code?

 require("animal.coffee")
 require("jquery.js")

This could (later) be combined with a package manager (Rubygems sounds like a good bet), so we can have proper external dependencies compiled right into our JavaScript code.

We might risk replicating some narwhal/node.js functionality though.

Thoughts?

Multi-line functions as arguments

I just started playing with CoffeScript, really great work guys, it's a work of art! There probably already is a nice idiomatic solution for this and I jsut don't know it, I just thought I'd ask (a mailing list would be awesome!):

When passing functions as arguments, it looks really good with single line functions:

items.map(item => item.value().)

But when doing the same with muliple line functions, it looks not so great:

items.each(item =>
  item.focus()
  item.remove.
)

Those extra parens really noise up the code in a bad way. This is where Ruby's block syntax really shines, maybe there could be something similar added, such as:

items.each -> item
  item.focus()
  item.remove.

Or with arguments:

 items.inject(4) -> sum, item
   sum + item.value().

Which would be quivalent to:

 items.inject(4, (sum, item => sum + item.value().))

What do you think?

Comprehensions can't handle arguments objects.

A little help would be good on this one. Our array/object comprehensions can't handle argument objects being passed. The for..in loop doesn't see any properties on them, and doesn't run. Is there any way around this, other than generating two code paths for comprehensions (one for arrays/arguments and one for objects)? See the following JS:

for (key in [1, 2, 3]) console.log(key)
=> 0
=> 1
=> 2
=> undefined

(function(){ for (key in arguments) console.log(key) })(1, 2, 3)
=> undefined

Slice literal assignment

The following code

a[5..8] = [1,2,3]

Compiles to

(function(){
  a.slice(5, 8 + 1) = [1, 2, 3];
})();

I suggest it should compile to:

(function(){
    a.splice.apply(a,[1,3].concat([1,2,3]));
    return a;
})();          

The main problem with this approach is simply that the return value of that expression is what is removed not the new array, which would fit better with assignment semantics, hence the return statement.

Argument Enhancements (Defaults and Splats)

Think about adding argument defaults to CoffeeScript function definitions. Something along the lines of:

start_reading: book, page: 1 => ...

Ideally, the arguments with default values could occur anywhere in the list.

Also, splats to siphon up the rest of the arguments:

demolition: *condominiums => wreck(condo) for condo in condominiums..

Neither of these should be too hard to implement -- both can be accomplished by inserting an expression that does the work at the top of the Code body.

Object comprehensions: "for key, value" would feel more natural

I think the order of the key/value pair should be reversed in the object comprehension syntax. Key then value is the standard order in most languages (that I know of), and it reflects the way objects are defined.

years_old: {max: 10, ida: 9, tim: 11}

ages: child + " is " + age for child, age in years_old

Or is it a bug in the documentation?

Bug with assigning function and calling it immediately.

This should assign the function to square and then call it with 4 as an argument, but when everything is said and done square is assigned the result of the function call.

cs> (square: x => x * x.)(4)
16
cs> square
16

Here is the equivalent (correct) js:

js> (square = function (x) { return x * x })(4)
16
js> square
function (x) {
    return x * x;
}

It doesn't seem like you are using the issue tracker right now, but I wasn't sure how else to notify you.

I'm not sure what the javascript that is getting compiled looks like, but I think it would be cool to have a function in the REPL like Common Lisp's "macroexpand" and "macroexpand-1" to see the JS code that was being generated.

Thanks a bunch,

Nick

Optional curlies around objects as method parameters

I really like Ruby's way of making the curlies optional when passing a hash as the last argument to a function:

 monkey "blah", { :foo => 2, :bar => 3 }  # with curlies
 monkey "blah", :foo => 2, :bar => 3      # without curlies

It makes it look like named arguments. Is it possible to do the same in CoffeeScript?

monkey("blah", { foo: 2, bar:3 })        # with curlies
monkey("blah", foo: 2, bar:3)            # without curlies

Currently, this compiles to:

monkey("blah", {
  foo: 2,
  bar: 3
});
// with curlies
monkey("blah", foo = 2, bar = 3);
// without curlies

So the second example is valid Coffee, and compiles into an assignment. My suggestion is to make the second one compile to the same code as the first one.

Seems to me like this would be pretty hard on the parser and potentially introduce some confusion, so I'm not sure this is worth it at all, what do you think?

scope of temporary variable

Currently

lunch: eat(food) for food in ['toast', 'cheese', 'wine']

is converted to:

  var __a, __b, __c, __d, food, lunch;
  lunch = (function() {
    __a = ['toast', 'cheese', 'wine'];
    __c = [];
    for (__b in __a) {
      if (__a.hasOwnProperty(__b)) {
        food = __a[__b];
        __d = eat(food);
        __c.push(__d);
      }
    }
    return __c;
  })();

shouldn't it be:

  var food, lunch;
  lunch = (function() {
    var __a, __b, __c, __d;
    __a = ['toast', 'cheese', 'wine'];
    __c = [];
    for (__b in __a) {
      if (__a.hasOwnProperty(__b)) {
        food = __a[__b];
        __d = eat(food);
        __c.push(__d);
      }
    }
    return __c;
  })();

comments creating syntax errors

x: =>
# error
  for i in [0..6]
    1

line 3: syntax error, unexpected indent.

Perhaps it would be clever to strip out all the comments before parsing the file ?

Expression Ranges

Ranges should allow more complex expressions without parentheses:

[1...3+4] 

gives a syntax error, I don't think it should.

Two list comps problems

So, I decided to try porting an old project of mine from JS to Coffee.

  1. I still needed a for loop in a few cases, and had to reimplement it. Perhaps if we had some way to make more interesting range comprehensions with steps or something, hm...
iterate: st, en, step =>
   step = 1if step is undefined
   block =>
     i = st
     while i < en
       block(i)
       st += step

But, the main issue was, if i used two list comprehensions at once, it failed with a massive stacktrace:

doStuff(x,y) for x in [0...num_sprites_x] for y in [0...num_sprites_y]

chainable methods with function multiinline as arguments

i have see that isn't possible having chainable methods with function multiinline as arguments.

$("a").each(
=> $(this).css()
$(this).css()
$(this).css()
).
map(=> $(this).attr("href") ).
end()

this is compiled in this

(function(){
$("a").each(function() {
return $(this).css();
}, $(this).css(), $(this).css()).map(function() {
return $(this).attr("href");
}).end();
})();

and if i use the point for close the function in this mode:

$("a").each(
=> $(this).css()
$(this).css()
$(this).css()
.
).
map(=> $(this).attr("href") ).
end()

i have this error:

ine 5: syntax error for '.'

Postfix Block Expression

So, I'd really like something along the lines of ruby, that let you pass an additional argument to a function as a block specified after the function call, i.e:

myFunc(1,2) x =>
   alert(x).

This would be semantically equivalent to either:

myFunc(1,2,x=>alert(x).)

or:
myFunc(1,2)(x=>alert(x).)

Return value from function breaks constructor

Problem: if the return value from a function is an array or an object, the creation of new objects will be incorrect. E.g.

A: x,y => this.array = [x,y]
a: new A(1,2) 
# a is [1,2], not a class of A

This is not a problem for classic JS as it can choose not to return anything. However CS has implicit return values.

Some Solutions:

  1. Put null or this at the bottom of constructors.
  2. Use a special keyword to denote constructors (e.g. class or constructor or ==>).
  3. override the new operator in some way:
    function A(x,y) { return this.array = [x,y] } 
    a = new (function() { A.apply(this, Array.prototype.slice.call(arguments,0)) } )(1,2)
    

Notes
1 was noted to be ugly or error prone
2 was felt to be ok, although it seemed silly to have an a keyword to just turn off implicit returns in functions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.