thefrontside / ember-let

Create variable bindings inside your handlebars templates
MIT License
52 stars 16 forks source link

Added ability to use inline #8

Closed taras closed 7 years ago

taras commented 7 years ago

Note: this feature requires Ember 2.0+

Fixes #7

rwjblue commented 7 years ago

This is pretty unlike the language concept of let. Since this is setting a bound property on the template context, some really weird/unexpected things happen.

{{let name post.author.name}}
{{name}}
{{#each post.comments as |comment|}}
  {{let name comment.author.name}}
  {{name}}
{{/each}}
{{name}}

All of these {{name}} usages will be the value of the last commenter. This is pretty WAT.

rwjblue commented 7 years ago

I also see no mention in the README that using {{let foo would clobber foo on whatever the template context is...

cowboyd commented 7 years ago

All of these {{name}} usages will be the value of the last commenter. This is pretty WAT.

@rwjblue Agree, so how to fix?

As it stands, it's basically straight up variable assignment which is sub-optimal, but the question is, how to make it mask (and then restore) the previous declaration in the underlying runtime.

Even if the semantics are not just-so, I'm still very curious about what the style entails. (I am not currently using the inline form)

rwjblue commented 7 years ago

@cowboyd - @mmun and I have been chatting about the best fix. I believe it is to use an AST transform to change:

{{name}} <- should be whatever {{name}} is on the template context
<div>
  {{name}} <- should be whatever {{name}} is on the template context
  {{let name (some-sexpr)}}
  {{#foo-bar}}
    {{name}} <- should be some-sexpr's value
  {{/foo-bar}}

  {{#foo-bar as |name|}}
    {{name}} <- should be the yielded value from foo-bar value
  {{/foo-bar}}

  {{name}} <- should be some-sexpr's value
</div>
{{name}} <- should be whatever {{name}} is on the template context

Into:

{{name}} <- should be whatever {{name}} is on the template context
<div>
  {{name}} <- should be whatever {{name}} is on the template context
  {{#let (some-sexpr) as |name|}}
    {{#foo-bar}}
      {{name}} <- should be some-sexpr's value
    {{/foo-bar}}

    {{#foo-bar as |name|}}
      {{name}} <- should be the yielded value from foo-bar value
    {{/foo-bar}}

    {{name}} <- should be some-sexpr's value
  {{/let}}
</div>
{{name}} <- should be whatever {{name}} is on the template context

With this solution, nothing is set on the template context. Follows much closer to JS's version of let (available for the duration of the block, but not before, etc).

cowboyd commented 7 years ago

Ok, so TIL AST transforms are a thing.

giphy

Thank you for that. This sounds like exactly what it should be: sugar for the block form. Which would also give us a clean path for implementing let*

mmun commented 7 years ago

Yes, I've already implemented the transform. Just cooking up a PR now...

https://jsbin.com/yebitem/edit?html,js,output

taras commented 7 years ago

Awesome. Thank you @mmun!

On Sun, Aug 28, 2016 at 8:41 AM, Martin Muñoz notifications@github.com wrote:

Yes, I've already implemented the transform. Just cooking up a PR now...

https://jsbin.com/nuwebe/edit?html,js,output

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/thefrontside/ember-let/pull/8#issuecomment-242953463, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEjv6ERQyU9-7chRGS7ZB60ELRB617eks5qkPxbgaJpZM4Jso56 .

mmun commented 7 years ago

Also I'd suggest making the inline form be {{let foo=bar}} so that the parser can ensure that the name "foo" is a valid identifier more easily (and the user is more likely to make the connection themselves). But I'll keep that in a separate PR.

cowboyd commented 7 years ago

Also I'd suggest making the inline form be {{let foo=bar}}

Yeah, I like that. The "positionality" of binding expressions was one of the really frustrating things to me about learning to work with let in lisp. It always (and sometimes still does) make my eyes go screwy, so if we can avoid it, I'm all for it.

taras commented 7 years ago

Yeah, this is more obvious.

On Sun, Aug 28, 2016 at 9:05 AM, Charles Lowell notifications@github.com wrote:

Also I'd suggest making the inline form be {{let foo=bar}}

Yeah, I like that. The "positionality" of binding expressions was one of the really frustrating things to me about learning to work with let in lisp. It always (and sometimes still does) make my eyes go screwy, so if we can avoid it, I'm all for it.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/thefrontside/ember-let/pull/8#issuecomment-242954162, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEjvwV_GMcjfq0dfMw25gimNzViVDLDks5qkQIFgaJpZM4Jso56 .