gkz / LiveScript

LiveScript is a language which compiles to JavaScript. It has a straightforward mapping to JavaScript and allows you to write expressive code devoid of repetitive boilerplate. While LiveScript adds many features to assist in functional style programming, it also has many improvements for object oriented and imperative programming.
http://livescript.net
MIT License
2.32k stars 156 forks source link

returning array unexpected output #512

Open duralog opened 10 years ago

duralog commented 10 years ago

wrote this (using 2 spaces indentation):

lala = 3
show_val = (val) ->
  * E1 \ul c: \list,
      E2 \li null, "key:", key
      E3 \li null, "val:", val
  * "lala"

got this:

var show_val;
show_val = function(val){
  E1('ul', {
    c: 'list'
  }, E2('li', null, "key:", key), E3('li', null, "val:", val));
  return "lala";
};

the same thing, with tab indentation produces this:

var show_val;
show_val = function(val){
  [
    E1('ul', {
      c: 'list'
    }, E2('li', null, "key:", key)), E3('li', null, "val:", val)
  ];
  return "lala";
};

expected this:

var show_val;
show_val = function(val){
  return [
    E1('ul', {
      c: 'list'
    }, E2('li', null, "key:", key), E3('li', null, "val:", val)),
   "lala"
  ];
};

you will notice there are various bugs here.

  1. the differences between spaces and tabs. the spaces version correctly puts the ending paren to E1 after E3, but does not return correctly
  2. with tabs, the paren closing E1 is incorrectly placed after E2.
  3. with space indentation, an array is not produced.

so, I got smart and tried this:

show_val = (val) ->
  return
    * E \ul c: \list,
        E \li null, "key:", key
        E \li null, "val:", val
    * "lala"

it produces this (spaces & tabs):

var show_val;
show_val = function(val){
  return [
    [
      E('ul', {
        c: 'list'
      }, E('li', null, "key:", key)), E('li', null, "val:", val)
    ], "lala"
  ];
};

which is also wrong. it's adding that extra array in there, and the parens are also wrong too. it appears that the DEDENT is processed wrong on * array notation. using [] will produce the correct output though, but I did spend a bit of time debugging this... however LS is worth it, as it has for sure saved me that time now many times over. great work guys!

Delapouite commented 10 years ago

Yes I've also bean bitten by this star notation in the past and now unfortunately tend to avoid using it.

kay-is commented 10 years ago

I had the same problem, when using LiveScript with Mirthril. You only need the first star.

show_val = (val) ->
  * E1 \ul c: \list,
      E2 \li null, "key:", key
      E3 \li null, "val:", val
    "lala"

produced:

var show_val;
show_val = function(val){
  return [
    E1('ul', {
      c: 'list'
    }),
    E2('li', null, "key:", key),
    E3('li', null, "val:", val),
   "lala"
  ];
};

My Mithril example which has a deeper nesting:

view:->
  m 'html',
  * m 'body',
    * m 'input', onchange:(m.with-attr 'value', it.description), value:it.description!
      m 'button', onclick:it.add, 'Add'
      m 'table',
      for task in it.list
        m 'tr',
        * m 'td',
          * m 'input[type=checkbox]', onclick:(m.with-attr 'checked', task.done), checked:task.done!
          m 'td', style:text-decoration:if task.done! then 'line-through' else 'none', task.description!

produces:

view: function(it){
  var task;
  return m('html', m('body', [
    m('input', {
      onchange: m.withAttr('value', it.description),
      value: it.description()
    }), m('button', {
      onclick: it.add
    }, 'Add'), m('table', (function(){
      var i$, ref$, len$, results$ = [];
      for (i$ = 0, len$ = (ref$ = it.list).length; i$ < len$; ++i$) {
        task = ref$[i$];
        results$.push(m('tr', [
          m('td', m('input[type=checkbox]', {
            onclick: m.withAttr('checked', task.done),
            checked: task.done()
          })), m('td', {
            style: {
              textDecoration: task.done() ? 'line-through' : 'none'
            }
          }, task.description())
        ]));
      }
      return results$;
    }()))
  ]));
}