107

How do I define an array of anonymous objects in CoffeeScript? Is this possible at all, using the YAML syntax?

I know that having an array of named objects is quite easy:

items:[
   item1:
      name1:value1
   item2:
      name:value2
]

However, it would be a bit trickier, if those two objects had no names

9 Answers 9

305

Simple -- place a comma by itself in a column lower than that in which you define your objects.

a = [
     nameA1: valueA1
     nameA2: valueA2
     nameA3: valueA3
  ,
     nameB1: valueB1
     nameB2: valueB2
     nameB3: valueB3
]

Will become:

var a;

a = [
  {
    nameA1: valueA1,
    nameA2: valueA2,
    nameA3: valueA3
  }, {
    nameB1: valueB1,
    nameB2: valueB2,
    nameB3: valueB3
  }
];
Sign up to request clarification or add additional context in comments.

7 Comments

because its a weird lookin solution and the commas are easily missed
This is dangerous!! Sometimes only gives you an array with the last item ! See my example below..
@DeanRadcliffe It will return the last item in the array if you don't place the comma properly, yes, but isn't CoffeeScript built on the premise of convention over syntactical sugar?
I would indent the opening [ to the left of the next line, it's confusing enough as is..
I think coffeescript, instead of being a simplification and improvement over vanilla generates a lot more unnecessary complications. Would love to use just plain .js with rails integration without the need for coffee.
|
41

You can also add a coma between each object: 

items:[
    item1:
        name1:value1
  ,
    item2:
        name:value2
]

Comments

27

you can't:

this is some tricks:

items:[
    (name:"value1")
    (name:"value2")
]

another

items:[
    true && name:"value1"
    true && name:"value2"
]

this is the best:

items:[
    {name:"value1"}
    {name:"value2"}
]

3 Comments

Isn't that so ugly :( Coffeescript is really nice for it's indent based coding but for large object literals it's not much better than standard JSON as you have to balance up all the brackets and you end up with nasty trailing bracket soup. There was a ticket to resolve this and use YAML syntax but apparently there is parsing ambiguity in coffeescript to solve this which is unfortunate.
Instead of "true &&" you could of course use the equivalent "yes and" or "no or". "yes and" even kind of makes sense here.
Check out my answer -- this is perfectly doable without any tricks or braces.
14

I think the comma solution is better, but I figured I'd add this for completeness:

a = [
  {
    nameA1: valueA1
    nameA2: valueA2
    nameA3: valueA3
  }
  {
    nameB1: valueB1
    nameB2: valueB2
    nameB3: valueB3
  }
]

1 Comment

I think this is much better than the comma solution, where you have to be careful with comma placement.
3

You can define variable while defining array, so an ugly answer would be:

a = 
  items: [
    item1 = 
      name: 'value1'
    item2 = 
      name: 'value2'
  ]

It would work, but you may get warnings about "defined, but not used variables (item1, item2)". Better way would be to use underscore, variable used to omit not used variables:

a = 
  items: [
    _ = 
      name: 'value1'
    _ = 
      name: 'value2'
  ]

console.log JSON.stringify(a) will produce this:

  {
    "items":[
      {
        "name":"value1"
      },{
        "name":"value2"
      }
    ]
  }

Comments

1

I'm very happy to report after a bit of fiddling that I could get this to compile just right:

items: [
  nameA: subA
  nameB: subB
,
  nameX: subX
  nameY: subY
]

It results it just what you'd expect: a list of two anonymous objects.

Comments

0

I ran into a related problem and found this solution. If you want an array of many single k/v objects without braces, just indent some of them. Seems to do the trick.

data = [                                     
  "2013-09-25T16:46:52.636Z":3,              
    "2013-09-25T16:47:52.636Z":6,            
      "2013-09-25T16:48:52.636Z":2,          
        "2013-09-25T16:49:52.636Z":7,        
  "2013-09-25T16:50:52.636Z":5,              
    "2013-09-25T16:51:52.636Z":2,            
      "2013-09-25T16:52:52.636Z":1,          
        "2013-09-25T16:53:52.636Z":3,        
  "2013-09-25T16:54:52.636Z":8,              
    "2013-09-25T16:55:52.636Z":9,            
      "2013-09-25T16:56:52.636Z":2,          
        "2013-09-25T16:57:52.636Z":5,        
          "2013-09-25T16:58:52.636Z":7       
]                                            

Produces:

coffee> data
[ { '2013-09-25T16:46:52.636Z': 3 },
  { '2013-09-25T16:47:52.636Z': 6 },
  { '2013-09-25T16:48:52.636Z': 2 },
  { '2013-09-25T16:49:52.636Z': 7 },
  { '2013-09-25T16:50:52.636Z': 5 },
  { '2013-09-25T16:51:52.636Z': 2 },
  { '2013-09-25T16:52:52.636Z': 1 },
  { '2013-09-25T16:53:52.636Z': 3 },
  { '2013-09-25T16:54:52.636Z': 8 },
  { '2013-09-25T16:55:52.636Z': 9 },
  { '2013-09-25T16:56:52.636Z': 2 },
  { '2013-09-25T16:57:52.636Z': 5 },
  { '2013-09-25T16:58:52.636Z': 7 } ]

It's counter-intuitive to me; you'd think that this would make sub-objects but I think the comma at the end of the line tells it to stop making properties on that object.

3 Comments

While this works, I suspect it is a side effect of how the lines are parsed. Since successive lines don't have the same indentation, it can't put them in the same object. Apparently, instead of raising a syntax error, it starts a new object. It's a feature that probably shouldn't be counted on - unless you can find it documented.
@hpaulj well if you've got a better way to do this I'm all ears
Since Python is my 'first language', I'm not afraid to use a few extra brackets and braces. Even if Coffeescript does not need them, I find them to be helpful. Your second block is more readable.
0

Not an answer to the OP's question, but just in case you're here for the same reason I was... If you're low on Mountain Dew and use '=' instead of ':', then Coffeescript will turn your array of objects into a flat array without a compile error:

data = [
    one='one'
    two='two'
  ,
    one='1'
    two='2'
]

Produces

['one', 'two', '1', '2']

Insert more Mountain Dew and replace the '=' with ':'.

1 Comment

wtf does mountain dew have to do with this?
0

Why not:

list = []
list.push
  prop1: val
  prop2: val
list.push
  prop1: val
  prop2: val

It's still a huge improvement to me over js, very easy to read, minimal and pretty safe to write.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.