Discussion:
ENDLOACAL & CALL ... fails to expand a nested local varialbe
(too old to reply)
Anton Shepelev
2024-05-15 16:36:34 UTC
Permalink
Hello, all.

According to

<https://ss64.com/nt/endlocal.html>

ENDLOCAL can be used with `& CALL SET' in order to pass
local variables outside, because the script is executed
line-by-line and the expantion performed before the local
scope is exited. I cannot, however, take advantage of this
feature with nested expanstion. The following script:

@ECHO OFF
SETLOCAL
SET VAL=1
SET REF=VAL
ENDLOCAL & CALL ECHO REF points to: [%%%REF%%%]

Prints:

REF points to: []

whereas I expected it to print:

REF points to: [1]

I can get the desired behavior only by expanding REF
beforehand:

@ECHO OFF
SETLOCAL
SET VAL=1
SET REF=VAL
CALL SET UNREF=%%%REF%%%
ENDLOCAL & CALL ECHO REF points to: [%UNREF%]

Why can't REF be expanded on the last line as in the first
example?
--
() ascii ribbon campaign -- against html e-mail
/\ www.asciiribbon.org -- against proprietary attachments
R.Wieser
2024-05-15 17:21:25 UTC
Permalink
Anton,
Post by Anton Shepelev
According to
<https://ss64.com/nt/endlocal.html>
ENDLOCAL can be used with `& CALL SET'
I think you have misread something there. The only "CALL"s on that webpage
are to a script and an internal function. No mentioning of "CALL SET".
Post by Anton Shepelev
SET REF=VAL
ENDLOCAL & CALL ECHO REF points to: [%%%REF%%%]
REF points to: []
REF points to: [1]
Remove the CALL and try again.
Post by Anton Shepelev
I can get the desired behavior only by expanding REF
...
Post by Anton Shepelev
CALL SET UNREF=%%%REF%%%
ENDLOCAL & CALL ECHO REF points to: [%UNREF%]
Why can't REF be expanded on the last line as in the first
example?
You're not expanding. You're playing around with collapsing multiple "%"
symbols (which happens due to the reinterpreting caused by the two CALLs in
there)


Question:
Have you tried to run the "sales.cmd" script yet ? What doesn't it do that
you need ?

Regards,
Rudy Wieser
Anton Shepelev
2024-05-15 22:34:53 UTC
Permalink
Post by R.Wieser
Post by Anton Shepelev
According to
<https://ss64.com/nt/endlocal.html>
ENDLOCAL can be used with `& CALL SET'
I think you have misread something there.
No, but maybe I misunderstood.
Post by R.Wieser
The only "CALL"s on that webpage are to a script and an
internal function. No mentioning of "CALL SET".
Yes, but it has the following example of passing local
variables up to the caller:

SETLOCAL
Set "_item=Ice Cream Maker"
Set _price=450
ENDLOCAL & SET _return1=%_item%& SET _return2=%_price%

It works because the last line is interpreted as a whole, so
that first all %% are expanded and only then is the local
scope exited. This sequence causes the local variables to
be still visible at expansion time, although they occur
/after/ ENDLOCAL. I tried `CALL SET' instead of just `SET'
to do the same thing but with complete expansion, and it did
not work.
Post by R.Wieser
Post by Anton Shepelev
@ECHO OFF
SETLOCAL
SET VAL=1
SET REF=VAL
ENDLOCAL & CALL ECHO REF points to: [%%%REF%%%]
REF points to: []
REF points to: [1]
Remove the CALL and try again.
It will then perform only a single expanstion and print:

REF points to: [%VAL%]

which is not what I need.
Post by R.Wieser
Post by Anton Shepelev
CALL SET UNREF=%%%REF%%%
ENDLOCAL & CALL ECHO REF points to: [%UNREF%]
Why can't REF be expanded on the last line as in the first
example?
You're not expanding. You're playing around with
collapsing multiple "%" symbols (which happens due to the
reinterpreting caused by the two CALLs in there)
How come? As I understand it, the % characters surrounding
a variable name comprise the expansion operator, thereofore
CALL SET UNREF=%%%REF%%% works in two stages:

1. CMD expands the REF variable by replacing its %name%
with its value and collapses double %. The resuling
text becomes: %VAL%

2. CALL then expands the variable VAL, yielding 1.

Oooops, the second CALL in the last example is redundant,
because UNREF must be expanded but once. The following
works just as well:

@ECHO OFF
SETLOCAL
SET VAL=1
SET REF=VAL
CALL SET UNREF=%%%REF%%%
ENDLOCAL & ECHO REF points to: [%UNREF%]
Post by R.Wieser
Have you tried to run the "sales.cmd" script yet? What
doesn't it do that you need ?
Yes, I have. Its CALL & SET ... line performs a single
expantion whereas I need a double one, unless I keep the
workaround with the intermediate UNREF variable.

What I need now is not a solution to any problem, but an
explanation why my original example does not work as I
expect it to.
--
() ascii ribbon campaign -- against html e-mail
/\ www.asciiribbon.org -- against proprietary attachments
Anton Shepelev
2024-05-15 22:47:45 UTC
Permalink
Post by Anton Shepelev
What I need now is not a solution to any problem, but an
explanation why my original example does not work as I
expect it to.
Looks like the following interpretation sequence explains
it:

0. ENDLOCAL & CALL ECHO REF points to: [%%%REF%%%]
1. Expand variables in the entire line:
ENDLOCAL & CALL ECHO REF points to: [%VAL%]
2. Execute ENDLOCAL (losing VAL)
3. Execute CALL, expanding %VAL% into an empty string:
ECHO REF points to: []
--
() ascii ribbon campaign -- against html e-mail
/\ www.asciiribbon.org -- against proprietary attachments
Herbert Kleebauer
2024-05-15 18:06:58 UTC
Permalink
Post by Anton Shepelev
ENDLOCAL can be used with `& CALL SET' in order to pass
local variables outside, because the script is executed
line-by-line and the expantion performed before the local
scope is exited. I cannot, however, take advantage of this
@ECHO OFF
SETLOCAL
SET VAL=1
SET REF=VAL
ENDLOCAL & CALL ECHO REF points to: [%%%REF%%%]
REF points to: []
Why can't REF be expanded on the last line as in the first
example?
Because the "call echo" is used to perform a delayed expansion.
After the "call" is evaluated, the line becomes:

ENDLOCAL & ECHO REF points to: [%VAL%]

But after ENDLOCAL is executed, VAL is no longer defined.
If you define VAL outside the SETLOCAL, you get this value:


SET VAL=2
SETLOCAL
SET VAL=1
SET REF=VAL
ENDLOCAL & CALL ECHO REF points to: [%%%REF%%%]
Anton Shepelev
2024-05-15 22:44:30 UTC
Permalink
Post by Herbert Kleebauer
Post by Anton Shepelev
@ECHO OFF
SETLOCAL
SET VAL=1
SET REF=VAL
ENDLOCAL & CALL ECHO REF points to: [%%%REF%%%]
Why can't REF be expanded on the last line as in the
first example?
Because the "call echo" is used to perform a delayed
expansion. After the "call" is evaluated, the line
ENDLOCAL & ECHO REF points to: [%VAL%]
I think the acutual sequece is a tad different. First,
percent expantion turns the original line into:

ENDLOCAL & CALL ECHO REF points to: [%VAL%]

Then ENDLOCAL is executed and the local value of VAL is
lost. And finally, %VAL% is evaluated as an empty string.
Post by Herbert Kleebauer
But after ENDLOCAL is executed, VAL is no longer defined.
If you define VAL outside the SETLOCAL, you get this
Yes, I have observed this in my experiments. Thanks you.
--
() ascii ribbon campaign -- against html e-mail
/\ www.asciiribbon.org -- against proprietary attachments
Loading...