# Scope of $variable in Let statement in Calculated Field

**URL:** <https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155>\
**Category:** Questions\
**Tags:** scripting, variables\
**Created:** [October 19, 2022, 6:52pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155 "2022-10-19T18:52:19Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![xochi](https://avatars.discourse-cdn.com/v4/letter/x/0ea827/32.png) [@xochi](https://the.fmsoup.org/u/xochi)\
**Post date:** [October 19, 2022, 6:52pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/1 "2022-10-19T18:52:19Z")

</div>

I thought I had discovered a bug with JSON, but it turns out that I was wrong.

I have a script like this:

```auto
  Set Variable $N = ValueCount(...) // $N = 44
  [... do some calculations ...]
  Set Field Table::Foobar
  // Suddenly, $N = 2

```

What's going on is that this table has a calculated field:

```auto
Table::CalculatedField = Let(
[
  $N = Get(CalculationRepetitionNumber)
]; 

 "foobar repetition " & $N & " is " & GetRepetition(Table::Foobar; $N)
)

```

So, apparently the "$N" variable in the script, and the "$N" variable in the calculated field are interfering with each other; when I set the value of Table::Foobar, Table::CalculatedField updates, which sets $N to a different value, causing problems.

Has this always been the case? Clearly, based on my scripts and calculations, I was under the impression that in a calculation field, variables and $variables were scoped locally to the calculation and were thus the same.

If this isn't the case, then I'm really confused!

---

<div class="post-metadata">

**Author:** ![xochi](https://avatars.discourse-cdn.com/v4/letter/x/0ea827/32.png) [@xochi](https://the.fmsoup.org/u/xochi)\
**Post date:** [October 19, 2022, 7:04pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/2 "2022-10-19T19:04:02Z")

</div>

The [documentation](https://help.claris.com/en/pro-help/content/let.html?Highlight=let) is not crystal clear to me:

> The Let function sets the variables from left to right. You can use previously defined variables (for example, function variables defined earlier in the Let function or local and global variables that you defined with the [Set Variable script step](https://help.claris.com/en/pro-help/content/set-variable.html)) to define new variable values.
> 
> You can also nest one Let function within another. If you use a previously defined function variable within a nested Let function, the function variable has scope only within the nested function (as if you had defined a completely unique variable). See example [2](https://help.claris.com/en/pro-help/content/let.html?Highlight=let#example-nested-scope), below.

It sounds as if the first Let() function does not create a new scope, but if you have a nested Let() function that reuses the same $variable names, then these do get a new scope?

---

<div class="post-metadata">

**Author:** ![Malcolm](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/malcolm/32/196_2.png) [@Malcolm](https://the.fmsoup.org/u/Malcolm)\
**Post date:** [October 19, 2022, 7:09pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/3 "2022-10-19T19:09:44Z")

</div>

That sounds bad.

I suggest checking your assumptions in a clean file that has nothing but the table, with the fields needed for the script, and the script.

---

<div class="post-metadata">

**Author:** ![Torsten](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/torsten/32/1574_2.png) [@Torsten](https://the.fmsoup.org/u/Torsten)\
**Post date:** [October 19, 2022, 7:14pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/4 "2022-10-19T19:14:52Z")

</div>

You could try naming the custom function's variable differently. Preferably drop the '$' identifier. If this yields a different result, this hints at a scope issue.

---

<div class="post-metadata">

**Author:** ![xochi](https://avatars.discourse-cdn.com/v4/letter/x/0ea827/32.png) [@xochi](https://the.fmsoup.org/u/xochi)\
**Post date:** [October 20, 2022, 12:17am UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/5 "2022-10-20T00:17:09Z")

</div>

Further testing suggests it's a very simple issue - in a script, if something (such as a **Set Field** step) causes another calculated field to update, any $variables used in the calculated field's calculation will be in the same scope as $variables used in the script. It doesn't require repeating fields or JSON or any thing fancy.

- if you use regular variables (such as 'N' instead of $N) in the calculation field, it doesn't happen
- if the calcuation field is not stored, it doesn't happen (presumably because it doesn't update when you do the Set Field step?)
- this behavior happens both in FM18 and 19, so it doesn't appear to be new.

This seems like a very subtle and devious trap, because:

- when editing scripts, the **Set Variable** script step automatically adds $ to variable names -- if you enter 'N' you get '$N'
- because of this, it's natural to assume that $N variables are the same as non variables without the dollarsign, and both are local to the enclosing context
- if you then copy a calculation from your script to a calculated field, it's easy to just copy & paste, and then you are using $ variables in the field calculation
- becuase of how it works in scripts, I naturally assumed "$" variables are local to the field calculation. This tuns out to be wrong.

---

<div class="post-metadata">

**Author:** ![bdbd](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/bdbd/32/620_2.png) [@bdbd](https://the.fmsoup.org/u/bdbd)\
**Post date:** [October 20, 2022, 12:34am UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/6 "2022-10-20T00:34:42Z")

</div>

You should note that $var variables are scoped to scripts. You can define a $var variable in a let statement in a field calculation, however when a script runs with the same $var variable and the table is in context, both are one and the same.

---

<div class="post-metadata">

**Author:** ![Malcolm](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/malcolm/32/196_2.png) [@Malcolm](https://the.fmsoup.org/u/Malcolm)\
**Post date:** [October 20, 2022, 1:51am UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/7 "2022-10-20T01:51:02Z")

</div>

> [@xochi](#):
>
> when editing scripts, the **Set Variable** script step automatically adds $ to variable names -- if you enter 'N' you get '$N'

The set variable step always adds a $ character to the variable name. That's the recommended scope. You are able to add a second $ character to create a global variable. You cannot remove all the $ characters. When you do so, a $ character will be added to the variable name. This makes sense. A variable without a $ prefix can be created within calculations that use the LET and WHILE functions. Any variable that you set with the Set Variable script step must be local or global to survive beyond it's own definition and be used in the script.

Having said all of that, I've just experimented and found exactly the problem that you are describing. This seems like a nasty bug to me. Will you report it?

My test is attached

[VarLeaks.fmp12](https://the.fmsoup.org/uploads/short-url/duPNNxcH5CScbMSNdwaXWz4zmTf.fmp12) (292 KB)

---

<div class="post-metadata">

**Author:** ![xochi](https://avatars.discourse-cdn.com/v4/letter/x/0ea827/32.png) [@xochi](https://the.fmsoup.org/u/xochi)\
**Post date:** [October 20, 2022, 3:08am UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/8 "2022-10-20T03:08:33Z")

</div>

@Malcolm - thanks!

Here's my project file:

[variable\_scope.fmp12](https://the.fmsoup.org/uploads/short-url/jeEHJe5ICtcNbTRrSgAZbBC7pEH.fmp12) (368 KB)

> [@Malcolm](#):
>
> This seems like a nasty bug to me. Will you report it?

I'm still unsure about this - the behavior is really unexpected to me, but maybe everyone knows that's how it is supposed to work? I appreciate others saying they find it weird too...

---

<div class="post-metadata">

**Author:** ![Malcolm](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/malcolm/32/196_2.png) [@Malcolm](https://the.fmsoup.org/u/Malcolm)\
**Post date:** [October 20, 2022, 3:40am UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/9 "2022-10-20T03:40:32Z")

</div>

This is a bug that could have serious consequences. No-one wants to have values from field calculations bubbling up into their scripts.

It is an excellent reason to ensure that you limit the scope of your variables as tightly as possible. In your case, the variable $N can be more tightly scoped by removing the $ character, making it a calculation variable.

> [@About Claris Products Feedback and Bug reporting](https://the.fmsoup.org/t/about-claris-products-feedback-and-bug-reporting/37):
>
> Please report your feedback about Claris Products on Claris site so that your feedback and bug reports help the vendor improve the product. The soup does NOT report to Claris on your behalf. [Reporting product issues](https://community.claris.com/en/s/topic/0TO0H000008OQOGWA4/report-a-product-issue)

---

<div class="post-metadata">

**Author:** ![harvest](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/harvest/32/231_2.png) [@harvest](https://the.fmsoup.org/u/harvest)\
**Post date:** [October 20, 2022, 4:45am UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/10 "2022-10-20T04:45:53Z")

</div>

reminds me of this thread:

> [@Local variables defined in layout objects live long and travel widely](https://the.fmsoup.org/t/local-variables-defined-in-layout-objects-live-long-and-travel-widely/2870):
>
> [The FileMaker documentation says](https://help.claris.com/en/pro-help/content/using-variables.html?Highlight=variables): When you define a variable, you can specify its scope by adding a prefix before the variable name. Scope Prefix Example Availability function None variableName Only within the function where it is defined local $ $variableName Only within the script where it is defined (not available to sub-scripts); cleared when the script ends global $$ $variableName Anywhere within the file where it is defined; cleared when the file is closed For local (si…

---

<div class="post-metadata">

**Author:** ![Torsten](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/torsten/32/1574_2.png) [@Torsten](https://the.fmsoup.org/u/Torsten)\
**Post date:** [October 20, 2022, 6:33am UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/11 "2022-10-20T06:33:51Z")

</div>

FMScript handles scope not the same way other known languages like C, C++, C#, Swift, Java etc. do.  
The scope of a $-scoped variable is the executed script, that of a $$-scoped variable the executed file and variables declared in functions that have no $ or $$ scope designator have the function as scope. In the above-mentioned languages, functions do not know variables that have been declared in another function. The compiler guarantees that scope is respected and there is no interference between functions.  
FMScript does not enforce variable declaration and lets live $-scoped variables in functions. The responsibility for controlling scope between script and function lies entirely with the developer, the script engine does not throw a warning.  
Declaration of variables and strong scope are missing in FM since many years.  
Avoiding the use of script-scoped $variables in functions is a good workaround.

---

<div class="post-metadata">

**Author:** ![xochi](https://avatars.discourse-cdn.com/v4/letter/x/0ea827/32.png) [@xochi](https://the.fmsoup.org/u/xochi)\
**Post date:** [October 20, 2022, 1:46pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/12 "2022-10-20T13:46:54Z")

</div>

This can also happen when using the Data Viewer: [Overriding Variables using the Data Viewer](https://the.fmsoup.org/t/overriding-variables-using-the-data-viewer/2357)

And applies to Custom Functions as well.

hey @MonkeybreadSoftware - would it be possible to create a feature to audit our calc fields and scripts?

> Warning: Table::FIeld is a calculated field which uses $variable names, which could have unexpected side effects. Consider rewriting the calcuation using plain variables instead.

---

<div class="post-metadata">

**Author:** ![FileKraft](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/filekraft/32/1183_2.png) [@FileKraft](https://the.fmsoup.org/u/FileKraft)\
**Post date:** [October 22, 2022, 2:41pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/13 "2022-10-22T14:41:27Z")

</div>

if you see a custom function with a local variable assigned or embedded in a statement / expression within then run as fast as you can!

---

<div class="post-metadata">

**Author:** ![Torsten](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/torsten/32/1574_2.png) [@Torsten](https://the.fmsoup.org/u/Torsten)\
**Post date:** [October 22, 2022, 6:52pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/14 "2022-10-22T18:52:46Z")

</div>

Or wrestle the beast 🦖

---

<div class="post-metadata">

**Author:** ![DanShockley](https://avatars.discourse-cdn.com/v4/letter/d/9f8e36/32.png) [@DanShockley](https://the.fmsoup.org/u/DanShockley)\
**Post date:** [February 2, 2023, 3:33pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/15 "2023-02-02T15:33:41Z")

</div>

All this discussion of scope is perhaps confusing people. Here's a very simple way to describe what actually happens:  
When a $variable is defined, it is shared across EVERYTHING while it is defined.  
When a SCRIPT defines it, it goes away when that script finishes running.  
When something else defines it (Field calc, layout conditional formatting, button-bar label calc, etc, etc.), it is defined in what I've seen people call "script-zero" scope: In other words, EVERYTHING sees it, and it sticks around while that object-with-a-calculation is evaluating it.

So, moral of the story: If you do not NEED (and know why you need) a `$variable` in a Let or While, do not include the $ symbol - use truly calculation-local variable names.  
If you DO use $variables outside of an actual script, use them VERY carefully. Give them VERY UNIQUE names.

I've seen custom functions, which could be run in all kinds of contexts outside of scripts, use names like `$num` to do some kind of across-recursion-level processing of info. If you must use a custom function like that, rename its variables to `$_NAME_OF_CUSTOM_FUNCTION__whatever_they_named_it`. Better is to avoid those custom functions, if you can.

---

<div class="post-metadata">

**Author:** ![xochi](https://avatars.discourse-cdn.com/v4/letter/x/0ea827/32.png) [@xochi](https://the.fmsoup.org/u/xochi)\
**Post date:** [February 2, 2023, 6:38pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/16 "2023-02-02T18:38:31Z")

</div>

Thank you @DanShockley

Also, I wonder about this:

> [@Torsten](#):
>
> The scope of a $-scoped variable is the executed script, that of a $$-scoped variable the executed file and variables declared in functions that have no $ or $$ scope designator have the function as scope. I

To clarify, I almost never use $$ variables, but I assume these act like global fields, e.g. global to the file, but global _only on a per-session basis_ (e.g. User A's $$foobar variable will not affect user B's $$foobar varaible). I would assume this keeps $$variables isolated across Scripts that are running in PSOS mode?

---

<div class="post-metadata">

**Author:** ![Malcolm](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/malcolm/32/196_2.png) [@Malcolm](https://the.fmsoup.org/u/Malcolm)\
**Post date:** [February 2, 2023, 7:15pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/17 "2023-02-02T19:15:39Z")

</div>

> [@xochi](#):
>
> I would assume this keeps $$variables isolated across Scripts that are running in PSOS mode?

Correct. $$variables are unique to each user.

---

<div class="post-metadata">

**Author:** ![xochi](https://avatars.discourse-cdn.com/v4/letter/x/0ea827/32.png) [@xochi](https://the.fmsoup.org/u/xochi)\
**Post date:** [February 2, 2023, 7:20pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/18 "2023-02-02T19:20:04Z")

</div>

> [@Malcolm](#):
>
> Correct. $$variables are unique to each user.

What about if the same user is connected to the database twice? 🙂

---

<div class="post-metadata">

**Author:** ![Malcolm](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/malcolm/32/196_2.png) [@Malcolm](https://the.fmsoup.org/u/Malcolm)\
**Post date:** [February 2, 2023, 8:14pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/19 "2023-02-02T20:14:17Z")

</div>

🤔 Interesting

I assume user sessions are independent of each other. I know people using iPad and desktop at the same time.

---

<div class="post-metadata">

**Author:** ![bdbd](https://yyz2.discourse-cdn.com/flex030/user_avatar/the.fmsoup.org/bdbd/32/620_2.png) [@bdbd](https://the.fmsoup.org/u/bdbd)\
**Post date:** [February 2, 2023, 8:25pm UTC](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155/20 "2023-02-02T20:25:35Z")

</div>

$$variables are unique to a file, from the moment it is opened to the moment it is closed in a client. Client, here, means FileMaker Pro, FileMaker Go, FileMaker WebDirect or a server-side session invoked via PSOS or a scheduled server script.

[Next page](https://the.fmsoup.org/t/scope-of-variable-in-let-statement-in-calculated-field/3155.md?page=2)
