Variable declaration reset: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
(→‎{{header|J}}: Clarify summary statement)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(20 intermediate revisions by 12 users not shown)
Line 12:
=={{header|ALGOL 68}}==
In Algol 68, things that aren't explicitely initialised are notionally initialised to SKIP - an indeterminate value, so there should be no output from the program. Each iteration of the loop will get a new curr and prev, with prev initialised to SKIP. The following is equivalent to the Phix program...
<langsyntaxhighlight lang="algol68">BEGIN
[]INT s = ( 1, 2, 2, 3, 4, 4, 5 );
FOR i FROM LWB s TO UPB s DO
Line 21:
prev := curr
OD
END</langsyntaxhighlight>
...however, one of the non-standard features of Algol 68G is that uninitialised variables cause a runtime error instead of silently being set to SKIP.
{{out}} with [[ALGOL_68_Genie|Algol 68G]]:
Line 30:
...whereas, with [[Rutgers_ALGOL_68|Rutgers Algol 68]]:<br>
No output.
=={{header|AWK}}==
<syntaxhighlight lang="awk">
# syntax: GAWK -f VARIABLE_DECLARATION_RESET.AWK
BEGIN {
n = split("1,2,2,3,4,4,5",arr,",")
for (i=1; i<=n; i++) {
curr = arr[i]
if (i > 1 && prev == curr) {
printf("%s\n",i)
}
prev = curr
}
exit(0)
}
</syntaxhighlight>
{{out}}
<pre>
3
6
</pre>
 
=={{header|C}}==
Line 35 ⟶ 55:
 
The following compiles using either C89/90 (-std=c90 -ansi -pedantic) or C99 syntax using gcc 9.4.0.
<langsyntaxhighlight lang="c">#include <stdio.h>
 
int main() {
Line 61 ⟶ 81:
 
return 0;
}</langsyntaxhighlight>
<small>(Note: Obviously the <code>for (int i=0, prev</code> needs the outer i and the inner prev removed, and the same "int" added to the second loop, for it to compile cleanly though it only does so under C99 (or later) as for loop initial declarations are not allowed in C89/90.)</small>
{{out}}
Line 69 ⟶ 89:
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">#include <array>
#include <iostream>
 
int main()
{
constexpr std::array s {1,2,2,3,4,4,5};
 
if(!s.empty())
{
int previousValue = s[0];
 
for(size_t i = 1; i < s.size(); ++i)
{
// in C++, variables in block scope are reset at each iteration
const int currentValue = s[i];
 
if(i > 0 && previousValue == currentValue)
{
std::cout << i << "\n";
}
 
previousValue = currentValue;
}
}
}
 
</syntaxhighlight>
{{out}}
<pre>
2
5
</pre>
 
=={{header|F_Sharp|F#}}==
Functional programming doesn't really do variables!!! There is no particular judgement of right or wrong here, just a plain-speaking statement that using variables is awful.
<syntaxhighlight lang="fsharp">
// Variable declaration reset. Nigel Galloway: June 21st 2022
let s=[1;2;2;3;4;4;5]
// First let me write this in real F#, which rather avoids the whole issue
printfn "Real F#"
s|>List.pairwise|>List.iteri(fun i (n,g)->if n=g then printfn "%d" (i+1))
// Now let me take the opportunity to write some awful F# by translating the C++
printfn "C++ like awful F#"
let mutable previousValue = -1
for i in 0..s.Length-1 do
let currentValue=s.[i]
if previousValue = currentValue then printfn "%d" i
previousValue <- currentValue
</syntaxhighlight>
{{out}}
<pre>
Real F#
2
5
C++ like awful F#
2
5
</pre>
=={{header|Factor}}==
Normally you would not use lexical scoping for something like this in Factor. But since it is possible, here we go. Note that:
Line 76 ⟶ 155:
 
{{works with|Factor|0.99 2022-04-03}}
<langsyntaxhighlight lang="factor">USING: kernel math prettyprint sequences ;
 
[let
Line 86 ⟶ 165:
curr prev!
] each
]</langsyntaxhighlight>
{{out}}
[none]
Line 94 ⟶ 173:
 
{{works with|Factor|0.99 2022-04-03}}
<langsyntaxhighlight lang="factor">USING: kernel math prettyprint sequences ;
 
[let
Line 104 ⟶ 183:
curr prev!
] each
]</langsyntaxhighlight>
{{out}}
<pre>
Line 112 ⟶ 191:
Now compare to how you would normally solve this in Factor, where issues of variables and scope are irrelevant:
{{works with|Factor|0.99 2022-04-03}}
<langsyntaxhighlight lang="factor">USING: grouping math.vectors prettyprint sequences.extras ;
 
{ 1 2 2 3 4 4 5 } 2 <clumps> [ all-eq? ] arg-where 1 v+n .</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">Dim As Integer s(1 To 7) => {1,2,2,3,4,4,5}
For i As Integer = 1 To Ubound(s)
Dim As Integer curr = s(i), prev
Line 123 ⟶ 202:
prev = curr
Next i
Sleep</langsyntaxhighlight>
{{out}}
<pre>
Line 136 ⟶ 215:
=={{header|Go}}==
Note firstly that unassigned variables are impossible in Go. If a variable is created (using the 'var' keyword) without giving it an explicit value, then it is assigned the default value for its type which in the case of numbers is zero. Fortunately, this doesn't clash with values in the slice in the following program.
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 164 ⟶ 243:
prev = curr
}
}</langsyntaxhighlight>
 
{{out}}
Line 178 ⟶ 257:
First off, the idiomatic J approach to finding indices of numbers which match their predecessors would be:
 
<langsyntaxhighlight Jlang="j"> 1+I.(}:=}.) 1 2 2 3 4 4 5
2 5</langsyntaxhighlight>
 
In other words, compare adjacent numbers (which results in a list of results one element shorter than the argument), find the indices of the matches (which would be the indices of the pairs which match) and add one (to get the indices in the original list of the second value of each of the pairs).
Line 189 ⟶ 268:
Anyways, here's a rough approximation of what the task is asking for:
 
<langsyntaxhighlight Jlang="j">same2=: {{
i=. 0
r=. ,EMPTY
Line 203 ⟶ 282:
end.
r
}}</langsyntaxhighlight>
 
This gives us:
 
<langsyntaxhighlight Jlang="j"> same2 1,2,2,3,4,4,5
2 5</langsyntaxhighlight>
 
But, since we were unable to declare 'prev' before it was assigned, we have no way of moving that declaration of 'prev' outside of the loop. We could add a declaration of 'prev' outside of the loop,
 
<langsyntaxhighlight Jlang="j">same3=: {{
i=. 0
r=. ,EMPTY
Line 227 ⟶ 306:
end.
r
}}</langsyntaxhighlight>
 
But it would not alter the generated result.
 
Also... J's control words (like '<tt>while.</tt>') do not create new variable scopes. However, givenGiven J's semanticsscoping rules, itsif behaviorJ inintroduced thenew contextvariable ofscopes thisfor taskcontrol words, that would beprevent unchangedupdates ifinside thethose whileblocks loopfrom introducedbeing avisible outside those blocks (unless we also added new variablescoping rules for that case -- a major engine upgrade -- or used non-local variables, such as J's "locales" which are probably out of scope for this task...). Where J's block scope isolation is desirable, we can use nested functions (J's verbs, adverbs or conjunctions).
 
But J's design -- which does not allow variables to be declared which are not assigned -- makes most variable declaration problems trivial. This is arguably a good thing.
 
=={{header|Java}}==
Note firstly that variables declared in methods must be assigned a value before they can be used in Java and so here we give '(g)prev' an initial value of 0 which won't clash with the values in the array.
<langsyntaxhighlight lang="java">public class VariableDeclarationReset {
public static void main(String[] args) {
int[] s = {1, 2, 2, 3, 4, 4, 5};
Line 259 ⟶ 340:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 268 ⟶ 349:
 
=={{header|JavaScript}}==
<langsyntaxhighlight lang="javascript"><!DOCTYPE html>
<html lang="en" >
<head>
Line 288 ⟶ 369:
</script>
</body>
</html></langsyntaxhighlight>
No output<br>
Any of 1) manually moving the declaration of prev to before the loop, or 2) using <code>for (let i=0, prev; i<7; i+=1)</code>, and in fact initialising prev there, to any value, works exactly the same, or 3) changing the third "let" to "var" (causes legacy hoisting and) gives:
Line 302 ⟶ 383:
 
As it happens, if the first argument of range/2 was changed to 0, then in this particular case the correct results would still be correct because at the first iteration, the test would be $array[0] == $array[-1], the point being that $array[-1] evaluates to the last element of the array. That is, the "bug" in the program would not be revealed by the test case.
<langsyntaxhighlight lang="jq">[1,2,2,3,4,4,5]
| . as $array
| range(1;length)
| select( $array[.] == $array[.-1])
</syntaxhighlight>
</lang>
 
=={{header|Julia}}==
In Julia, variables are declared by being defined. Because variables also must be defined before they are
referred to in compiled code, the code below yields an error that the variable `prev` is not defined:
<langsyntaxhighlight lang="julia">
s = [1, 2, 2, 3, 4, 4, 5]
Line 319 ⟶ 400:
prev = curr
end
</syntaxhighlight>
</lang>
If the variable `prev` is defined before the `for` statement, the code then runs. We also may
declare the variable `prev` as global to refer explicitly to the variable declared outside of the for block:
<langsyntaxhighlight lang="julia">
s = [1, 2, 2, 3, 4, 4, 5]
prev = -1
Line 332 ⟶ 413:
prev = curr
end
</langsyntaxhighlight> {{out}}
<pre>
3
6
</pre>
Parenthetical note: making a global variable to support a for loop has a bad code smell in Julia. A better
way to do such a comparison of adjacent values in an array is to alter the start of the loop variable:
<syntaxhighlight lang="julia">
s = [1, 2, 2, 3, 4, 4, 5]
 
for i in eachindex(s)[begin+1:end] # or 2:length(s)
s[i] == s[i - 1] && println(i)
end
</syntaxhighlight>
 
=={{header|K}}==
There is no such thing as a <i>straightforward longhand loop</i> in K. See also: https://nsl.com/
 
A natural expression for finding the indices of repeated elements (in [[ngn/k]]) might be:<syntaxhighlight lang=K>&=/'2':1 2 2 3 4 4 5
1 4</syntaxhighlight>
 
But of course, there's no variables here.
 
Longhand loops can be emulated, using lambdas (in which case local variables expire when the lambda exits), but this is not what many programmers would think of as a straightforward longhand loop.
 
=={{header|Nim}}==
In Nim, a loop create a new block. Variables declared in the loop body are created and initialized at each round: they do not retain the value from one round to the next.
 
Moreover, a variable needs to be declared before use, except variables in “for” loop which are implicitly declared in the loop block scope. If the variable has not been declared, the program fails to compile.
 
Is is not mandatory to initialize a variable. If there is no explicit initialization, the variable gets a default value which depends on its type (this is a binary zero).
 
Thus, the following program doesn’t compile, as, at compile time, “prev” is used before its declaration:
 
<syntaxhighlight lang="Nim">let s = [1, 2, 2, 3, 4, 4, 5]
for i in 0..s.high:
let curr = s[i]
if i > 0 and curr == prev:
echo i
var prev = curr
</syntaxhighlight>
 
The following program compiles but doesn’t output the right result as “prev” is reset at beginning of each round:
 
<syntaxhighlight lang="Nim">let s = [1, 2, 2, 3, 4, 4, 5]
for i in 0..s.high:
let curr = s[i]
var prev: int
if i > 0 and curr == prev:
echo i
prev = curr
</syntaxhighlight>
 
To get the right result, we need to declare “prev” outside the loop.
<syntaxhighlight lang="Nim">let s = [1, 2, 2, 3, 4, 4, 5]
var prev: int
for i in 0..s.high:
let curr = s[i]
if i > 0 and curr == prev:
echo i
prev = curr
</syntaxhighlight>
 
{{out}}
<pre>2
5
</pre>
 
=={{header|Perl}}==
By default, variables can be created on-the-fly, as with <code>$prev</code> here. Testing against <code>$curr</code> is not an error, even when it's value is undefined. This is perhaps not "best practices", but it does work just fine.
<syntaxhighlight lang="perl">@s = <1 2 2 3 4 4 5>;
for ($i = 0; $i < 7; $i++) {
$curr = $s[$i];
if ($i > 1 and $curr == $prev) { print "$i\n" }
$prev = $curr;
}</syntaxhighlight>
{{out}}
<pre>2
5</pre>
 
But better to do it this way, requiring <code>my</code> declarations imposing lexical scope (an instance of <code>$curr</code> is instantiated on every pass through loop) and employing a <code>state</code> variable (persistent within loop).
<syntaxhighlight lang="perl">use strict;
use warnings;
use feature 'state';
 
my @s = <1 2 2 3 4 4 5>;
for (my $i = 0; $i < 7; $i++) {
my $curr = $s[$i];
state $prev;
if ($i > 1 and $curr == $prev) { print "$i\n" }
$prev = $curr;
}</syntaxhighlight>
{{out}}
<pre>2
5</pre>
 
=={{header|Phix}}==
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">}</span>
Line 349 ⟶ 520:
<span style="color: #000000;">prev</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curr</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 362 ⟶ 533:
Although PL/M has block scope, all variables are static, so PREV retains its value between iterations of the loop.<br>
Note the extra DO which is necessary to introduce a new scope as declarations are not allowed in a DO loop.
<langsyntaxhighlight lang="pli">100H:
 
/* CP/M BDOS SYSTEM CALL */
Line 395 ⟶ 566:
END;
 
EOF</langsyntaxhighlight>
{{out}}
<pre>
Line 403 ⟶ 574:
 
=={{header|Python}}==
In Python, variables are not declared before use. If you assign to a non-existent variable, you create a new variable with that name. The language does not prohibit writing code to read a variable that may or may not exist. But if the code tries at runtime to read a variable that happens to not have been assigned to (or a variable that happens to have been <code>del</code>'ed), you get a <code>NameError</code> exception at runtime.
In Python, variables are supposed to be defined before they are used. The code does run, but note that a Python code checker such as pyflakes will flag such code with an error.
 
<lang python>
The following code is legal, but note that a Python code checker such as pyflakes will flag such code with an error.
<syntaxhighlight lang="python">
s = [1, 2, 2, 3, 4, 4, 5]
Line 412 ⟶ 585:
print(i)
prev = curr
</langsyntaxhighlight>{{out}}
<pre>
2
Line 421 ⟶ 594:
By default, Raku variables need a prefix sigil indicating the storage / interface, and a scope declarator to indicate the variables' accessibility. The vast majority of the time, variables are declared with a "my" scope declarator that constrains them to the present block and any enclosed sub blocks. When a 'my' variable is declared inside a loop (block), a new independent instance of the variable is instantiated every time through.
 
<syntaxhighlight lang="raku" perl6line>my @s = 1, 2, 2, 3, 4, 4, 5;
loop (my $i = 0; $i < 7; $i += 1) {
my $curr = @s[$i];
Line 429 ⟶ 602:
}
$prev = $curr;
}</langsyntaxhighlight>
{{out|Yields}}
<pre>Use of uninitialized value of type Any in numeric context
Line 444 ⟶ 617:
Lots of warnings but nothing else. If we suppress the warnings:
 
<syntaxhighlight lang="raku" perl6line>my @s = 1, 2, 2, 3, 4, 4, 5;
quietly loop (my $i = 0; $i < 7; $i += 1) {
my $curr = @s[$i];
Line 452 ⟶ 625:
}
$prev = $curr;
}</langsyntaxhighlight>
 
No output.
Line 459 ⟶ 632:
We can however, declare the variable with an "our" scope, which effectively makes it a package global. Use of 'our' scoping is discouraged except in a few very specific situations. It "works" (for some value of works), but pollutes the namespace. The 'our' variable will trample any other instance of a variable with that name anywhere in the program in any other scope.
 
<syntaxhighlight lang="raku" perl6line>my @s = 1, 2, 2, 3, 4, 4, 5;
loop (my $i = 0; $i < 7; $i += 1) {
my $curr = @s[$i];
Line 467 ⟶ 640:
}
$prev = $curr;
}</langsyntaxhighlight>
 
{{out|Yields}}
Line 475 ⟶ 648:
A better solution is to declare a state variable. A 'state' variable is essentially scoped similar to a 'my' variable (visible only inside the block), but is persistent across calls.
 
<syntaxhighlight lang="raku" perl6line>my @s = 1, 2, 2, 3, 4, 4, 5;
loop (my $i = 0; $i < 7; $i += 1) {
my $curr = @s[$i];
Line 483 ⟶ 656:
}
$prev = $curr;
}</langsyntaxhighlight>
 
{{out|Yields}}
Line 492 ⟶ 665:
 
No scope declarators at all. Every variable is a global. Bad idea. Do not do this casually.
<syntaxhighlight lang="raku" perl6line>no strict;
@s = 1, 2, 2, 3, 4, 4, 5;
loop ($i = 0; $i < 7; $i += 1) {
Line 500 ⟶ 673:
}
$prev = $curr;
}</langsyntaxhighlight>
 
{{out|Yields}}
Line 509 ⟶ 682:
* Blocks start at index 1 in Red.
* <code>all</code> short-circuits, so <code>prev</code> will be defined by the time <code>curr = prev</code> is checked.
<langsyntaxhighlight lang="rebol">Red[]
s: [1 2 2 3 4 4 5]
repeat i length? s [
Line 517 ⟶ 690:
]
prev: curr
]</langsyntaxhighlight>
{{out}}
<pre>
3
6
</pre>
 
=={{header|Seed7}}==
Variables must be declared in the locals section (or as globals) before execution begins, so this whole excercise is moot. There is only one way to write it and it's the way that works.
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const proc: main is func
local
const array integer: s is [] (1, 2, 2, 3, 4, 4, 5);
var integer: i is 0;
var integer: curr is 0;
var integer: prev is 0;
begin
for i range 1 to length(s) do
curr := s[i];
if i > 1 and curr = prev then
writeln(i);
end if;
prev := curr;
end for;
end func;</syntaxhighlight>
{{out}}
<pre>
Line 525 ⟶ 723:
 
=={{header|Visual Basic .NET}}==
<langsyntaxhighlight lang="vbnet">Option Strict On
Option Explicit On
 
Line 544 ⟶ 742:
End Sub
 
End Module</langsyntaxhighlight>
{{out}}
<pre>
2
5
</pre>
 
=={{header|V (Vlang)}}==
Note firstly that unassigned variables are impossible in Vlang. If a variable is created it must have an explicit value, then it is assigned the default value for its type which in the case of numbers is zero. Fortunately, this doesn't clash with values in the slice in the following program.
<syntaxhighlight lang="v (vlang)">fn main() {
s := [1, 2, 2, 3, 4, 4, 5]
// There is no output as 'prev' is created anew each time
// around the loop and set implicitly to zero.
for i := 0; i < s.len; i++ {
curr := s[i]
mut prev := 0
if i > 0 && curr == prev {
println(i)
}
prev = curr
}
// Now 'prev' is created only once and reassigned
// each time around the loop producing the desired output.
mut prev := 0
for i := 0; i < s.len; i++ {
curr := s[i]
if i > 0 && curr == prev {
println(i)
}
prev = curr
}
}</syntaxhighlight>
 
{{out}}
<pre>
Line 553 ⟶ 785:
=={{header|Wren}}==
Note firstly that unassigned variables are impossible in Wren. If a variable is created without giving it an explicit value, then it is assigned the special value 'null' which is the only instance of the Null class and therefore distinct from all other values in the language.
<langsyntaxhighlight ecmascriptlang="wren">var s = [1, 2, 2, 3, 4, 4, 5]
 
// There is no output as 'prev' is created anew each time
Line 571 ⟶ 803:
if (i > 0 && curr == prev) System.print(i)
prev = curr
}</langsyntaxhighlight>
 
{{out}}
9,476

edits