Is it possible to use a previously defined value in subsequent definitions of a `Block`?
The values of the variables in a Block
are set at definition time, when data
has no value:
Clear["data","len"]
TracePrint[
Block[
{
data=Range[5],
len=Length[data]
},
{len,data}
],
_Length
]
Length[data]
{0, {1, 2, 3, 4, 5}}
The difference between using Plus
and Length
is that when data
has no value data + 1
just evaluates to data + 1
while Length[data]
evaluates to 0. So, the sum
variable still has data
in it, and it's value can change when data
acquires a value.
One possibility to achieve your goal is to use SetDelayed
instead of Set
in your Block
:
Block[
{
data = Range[5],
len := Length[data]
},
{len,data}
]
{5, {1, 2, 3, 4, 5}}
Another, more robust possibility is to use the currently undocumented varargs
With
syntax:
With[
{data = Range[5]},
{len = Length[data]},
{len, data}
]
{5, {1, 2, 3, 4, 5}}
Support for this syntax is not going away, and I believe the syntax should soon become documented.
It is possible to use Block
with normal assignment, but you have to wait until data
is available. (See the answer of @CarlWoll for the use of delayed assignment.)
Block[{data = Range@5, len},
len = Length@data;
{len, data}
]
However in this particular example, it is unclear why Module
would not be preferable. Imo, Block
should only be used when dynamic scoping is really needed, which is seldom.