1. variable declaration reset
- Posted by petelomax Apr 15, 2022
- 793 views
This just surprised me:
sequence s = {1,2,2,3,4,4,5} for i=1 to length(s) do integer curr = s[i], prev if i>1 and curr=prev then ?{i,s[i]} end if prev = curr end for
On desktop/Phix you get {3,2} and {6,4}, but under pwa/p2js you get precisely nuttin.
JavaScript actually resets prev at the start of every iteration, whereas desktop/Phix leaves it be.
One fix is to simply move the declaration of prev outside of|above the loop, and then they match.
Another way to fix it is to replace "let" in the JavaScript with "var", which triggers legacy hoisting...
[However a blanket use of "var" would fail badly in say "if cond then atom a ... else atom a" cases]
I'm intrigued to know how (various versions of) Euphoria handle this,
and whether to do the same on desktop/Phix and risk breaking legacy code,
or not do that, but somehow (and that's the question) issue a warning/error.
I've also created a rosettacode task to see what that yields.
2. Re: variable declaration reset
- Posted by Lnettnay Apr 15, 2022
- 773 views
Euphoria needs the prev variable moved above the loop and initialized also.
Lonny
3. Re: variable declaration reset
- Posted by euphoric (admin) Apr 16, 2022
- 725 views
This just surprised me:
sequence s = {1,2,2,3,4,4,5} for i=1 to length(s) do integer curr = s[i], prev if i>1 and curr=prev then ?{i,s[i]} end if prev = curr end for
JavaScript actually resets prev at the start of every iteration...
That's the behavior I expect, no matter what language I'm using. A variable defined is a variable reset.
4. Re: variable declaration reset
- Posted by petelomax Apr 17, 2022
- 700 views
That's the behavior I expect, no matter what language I'm using. A variable defined is a variable reset.
You could argue it that way, however the point of block scope is to only declare a variable where it is needed, and clearly prev is only needed within the loop and we don't want any code outside the loop to be able to see it. However if you reset it on every iteration then it is absolutely impossible to declare a local prev within the loop for the use I had in mind. The closest you could get would be
if true then integer prev for ... end for end if
which is potentially an awful lot of manual re-indentation just to introduce a new variable and limit it to the desired scope.
In fact, now I think of it, I can almost imagine a more complicated bit of code where you want two prev, and genuinely want them as separate entities, and want their values preserved even while code execution leaves and re-enters their scope many times. Maybe if you had two such lists and wanted to advance the one with the lowest curr first?
Mind you, there is a valid counter argument in that variables should really be reset to unassigned at the end of/when execution leaves their scope, not that Phix currently does that.
5. Re: variable declaration reset
- Posted by _tom (admin) Apr 17, 2022
- 692 views
Phix is working as expected.
JavaScript is working in a plausible, internally consistent, ?
Consider the creation of a variable, which is a two step process.
- instantiate a type and give it a name integer prev
- prior to this, any code that used the name ''prev'' crashes Phix
- just after this moment: ? object(prev) is False.
- assign a value prev := s[i]
- after this moment: ? object(prev) is True.
- since it is a loop, prev is now in-scope before the declaration, next time the loop is performed ... this makes sense, but maybe not obviously
- observations
- prev is out-scope after ''end for''
- it makes no sense (in a compiled program) for ''integer prev'' to be duplicated ''i'' number of times
- the variable is created exactly once in the loop
- it makes no sense (in a compiled program) for ''integer prev'' to be duplicated ''i'' number of times
- in a traditional interpreter (one-line-at-time design) it is not surprising that ''integer prev'' is actually duplicated for every loop iteration
- in a traditional interpreter (one-line-at-time design) it is not surprising that ''integer prev'' is actually duplicated for every loop iteration
- I would expect ''integer prev'' to be ignored in a loop after the first encounter
- once the loop goes past ''one iteration'', then prev is in-scope from the top of the loop ? object(prev) just before the declaration returns True
sidebar
This seems to be more idiomatic for OE/Phix:
for i=2 to length(s) do if s[i-1] == s[i] then ? { s[i-1], s[i] } end if ---- optional integer curr,prev {curr,prev} := { s[i-1], s[i] } end for
question
It would be interesting if a statement existed that would "undo" an assignment and "reset" a variable to an assigned state so ? object(prev) does return False
be well
_tom
6. Re: variable declaration reset
- Posted by petelomax Apr 18, 2022
- 631 views
to be duplicated ''i'' number of times that is a waste of energy
is actually duplicated for every loop iteration which causes a "reset"... very inefficient
To be pedantic, I doubt that any language actually duplicates variables, and I'd consider a forced/implicit reset more "somewhat shy of spectacularly helpful" than "inefficient".
One thing I hadn't considered is that in some languages (Julia, Python) variables are defined by being assigned, and some (Java) effectively force assignment, so you simply cannot define an "unassigned empty slot" as it were.
It would be interesting if a statement existed that would "undo" an assignment and "reset" a variable to an assigned state so ? object(prev) does return False
Sort of, not p2js compatible, and note that as-is this would play merry havoc with refcounts for non-integer variables:
sequence s = {1,2,2,3,4,4,5} for i=1 to length(s) do integer curr = s[i], prev -- reset prev to "unassigned": #ilASM{ [32] mov eax,h4 mov [prev],eax [64] mov rax,h4 mov [prev],rax } if i>1 and curr=prev then ?{i,s[i]} end if prev = curr end for
Maybe delete(prev) could be made to do that sort of thing(/emit that sort of code) properly, including any needed refcount cleanup.
Anyway,
I think I may have just found a potential solution (for p2js):
-- Phix code for i=1 to 7 do integer prev ... end for
<==>
// JavaScript code for (let i=1, prev; i<=7; i+=1) { ... }Yet to give it a proper spin, but that would give prev the correct scope and behaviour, however it would only work for "for", and such unassigned vars would need to be bunched up at the start, so I might have to go back to the drawing board...
Of course, I've been using pwa/p2js aggressively for about a year and only hit this now, so any neat way to sidestep or trigger some kind of compilation error would not be dismissed.