Cannot modify a value in a Soy template

1.4k Views Asked by At
{let $first: 10 /} // this is a single line soy comment
  {if $first > 5 }
  {$first}<br/>
  {let $first:$first-1 /}
  {/if}
{$first}

I tried this, and it prints: 10 10

Ideally, it should print: 10 9 ..

Can you please identify what's wrong in my code?

1

There are 1 best solutions below

0
On BEST ANSWER

First of all, you cannot really overwrite the value of $first. The documentation states local variables defined by let are not modifiable. This is because whenever you alias a value with let, a new variable is created in the compiled output. Moreover, the scoping rules of soy expressions aren't the same as in Javascript (but you could think of {let} having similar semantics to ECMAScript 6's let statement, that is, non-hoisted, block-scoped).

In your code:

{let $first: 10 /}           /* 1 */
{if $first > 5}
  {$first}<br/>
  {let $first¹: $first-1 /}  /* 2 */
                             /* 3 */
{/if}
{$first}                     /* 4 */

what's happening is:

  • In (1), $first is an alias for the value 10. A variable is introduced to hold this value.

  • In (2):

    Right hand: $first takes its value from (1), because it is defined in a parent block.

    Left hand: $first¹ is being aliased to the value resulting from $first - 1 = 10 - 1 = 9. Because the definition of $first can't be overwritten, a new variable is introduced, different from (1). There are two things to note:

    a. The value for $first¹ is 9, but it's never read in this snippet.

    b. $first¹ only "lives" within the block it was defined, that is, inside {if...}. In fact, if you were to insert {$first} in (3), it would output 9.

  • In (4), the value of $first¹, being out of the scope introduced by the {if} block, can no longer be read, so $first from (1) is the only one visible, yielding 10. It makes use of the same variable as (1) in the compiled output.