1. variable declaration reset

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.

new topic     » topic index » view message » categorize

2. Re: variable declaration reset

Euphoria needs the prev variable moved above the loop and initialized also.

Lonny

new topic     » goto parent     » topic index » view message » categorize

3. Re: variable declaration reset

petelomax said...

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.

new topic     » goto parent     » topic index » view message » categorize

4. Re: variable declaration reset

euphoric said...

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.

new topic     » goto parent     » topic index » view message » categorize

5. Re: variable declaration reset

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 that is a waste of energy
    • the variable is created exactly once in the loop
    • in a traditional interpreter (one-line-at-time design) it is not surprising that ''integer prev'' is actually duplicated for every loop iteration which causes a "reset"... very inefficient
    • 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

new topic     » goto parent     » topic index » view message » categorize

6. Re: variable declaration reset

_tom said...

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.

_tom said...

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.

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu