Go- Why Does My For Loop Throw "Unexpected Semi-colon or New-line"? - go

I'm writing a dice rolling function. In order to add the result of each die, I added to an output variable using a for loop. However, I'm getting an error thrown when I attempt to build;
syntax error: unexpected semicolon or newline, expecting {
This was thrown on the line initializing the for loop.
Here is my code:
for i := 0; i < [0]si; i++ {
output := output + mt.Intn([1]si)
}
si is simply an int array holding 2 values, and mt is the name I gave to math/rand when I imported it.

Your loop has several problems:
The use of square brackets is odd. Outside of type definitions, these go after slice/array names, e.g. x[i] would give you the ith element of the slice x.
There is no reference to i inside the loop body, and thus each iteration of the loop will do the same thing.
You should probably write output = output + ... without the colon. Otherwise, a new variable output is declared during each iteration of the loop, and forgotten immediately after so that the loop has no effect.
The compiler error is probably caused by the first of these problems.

You access an array with varname[idx] in Go, just like in most other languages. It's only when declaring a new array of type si that you use the [size]si prefix syntax. You're getting the error because your code is syntactically invalid. You're trying to compare i to an array of 0 si s.

Related

Is there a bug in handling slices with references in Go?

I'm trying to build a new list of structs that contains references to items that exist in another slice. It's easier to understand if you see it, so I've prepared a snippet that you can run.
I have a list (dummylist) of two points (Cartesian coordinates) that I want to parse to build a new list (mylist) with items having some features (in the example, X > 80). I've defined two points: {X:90.0, Y:50.0} and {X:20.0 , Y:30.0}. I expect that mylist will contain {X:90.0, Y:50.0}, instead at the end there is {X:20.0 , Y:30.0}. With some print here and there I can verify that the algorithm is working fine (it enters in the "if" condition in the right case), but, at the end, "mylist" contains the wrong element.
package main
import(
"fmt"
)
func main() {
type point struct {
X float64
Y float64
}
type pointsList []point
type pointContainer struct {
Point *point
}
type pointContainerList []pointContainer
// Prepare a slice with two elements
dummylist := new(pointsList)
*dummylist = append(*dummylist, point{X:90.0, Y:50.0})
*dummylist = append(*dummylist, point{X:20.0 , Y:30.0})
// My empty list
mylist := new(pointContainerList)
fmt.Println(fmt.Sprintf("---- At the beginning, mylist contains %d points", len(*mylist)))
// Filter the initial list to take only elements
for _, pt := range *dummylist {
fmt.Println("\n---- Evaluating point ", pt)
if pt.X > 80 {
fmt.Println("Appending", pt)
*mylist = append(*mylist, pointContainer{Point: &pt})
fmt.Println("Inserted point:", (*mylist)[0].Point, "len = ", len(*mylist))
}
}
// mylist should contain {X:90.0, Y:50.0}, instead...
fmt.Println(fmt.Sprintf("\n---- At the end, mylist contains %d points", len(*mylist)))
fmt.Println("Content of mylist:", (*mylist)[0].Point)
}
Here you can run the code:
https://play.golang.org/p/AvrC3JJBLdT
Some helpful consideration:
I've seen through multiple tests that, at the end, mylist contains the last parsed item in the loop. I think there is a problem with references. It's like if the inserted item in the list (in the first iteration) is dependent on the "pt" of other iterations. Instead, if I use indexes (for i, pt := range *dummylist and (*dummylist)[i]), everything works fine.
Before talking about bugs in Golang... am I missing something?
Yes, you're missing something. On this line:
*mylist = append(*mylist, pointContainer{Point: &pt})
you're putting the address of the loop variable &pt into your structure. As the loop continues, the value of pt changes. (Or to put it another way, &pt will be the same pointer for each iteration of the loop).
From the go language specification:
...
The iteration values are assigned to the respective iteration
variables as in an assignment statement.
The iteration variables may be declared by the "range" clause using a
form of short variable declaration (:=). In this case their types are
set to the types of the respective iteration values and their scope is
the block of the "for" statement; they are re-used in each iteration.
If the iteration variables are declared outside the "for" statement,
after execution their values will be those of the last iteration.
One solution would be to create a new value, but I'm not sure what you're gaining from so many pointers: []point would probably be more effective (and less error-prone) than a pointer to a slice of structs of pointers to points.

How to catch the "slice bounds out of range" error and write a handle for it

I read other questions about the "slice bounds of range" here in the stackoverflow, but none of them using the same context from this.
Then, none of the answers helped me.
In my use case, the "golang's syntax" of substring using [] doesn't return an error variable. It launches a runtime error using the "panic" instruction.
My goal is to avoid to reach on the "panic" instruction.
I need to treat this error and provide messages that describe with more details the context around the moment where this error had occurred.
Obs:
The content of the string variable which one I need to get the substring value is totally dynamic and the indexes that I have been using to get the substring value is equally calculated dynamically.
You need to do bounds checking on your indexes:
if j >= 0 && j <= len(str) {
y = str[:j]
}

While loop throwing error at the start of while

I want to take the user's input of a positive integer where 1 < a < 10^6 and run a loop on it and then store it in a matrix which gets printed to the screen. However, my code is throwing a syntax error pointing to the letter "e" in while. Does anyone know why this error is appearing?
A = (while (a!=1)
If(rem(a,2)=0
floor(a^(1/2));
Else
floor(a^(3/2));
endwhile)
disp(A);
You're having several different problems in your code:
a while loop doesn't return anything, so you can't assign it to A
syntax is case sensitive, so it's if and else, not If and Else
you're missing a closing brace after the if clause
you're missing an endif
you're assigning to rem, use == to compare for equality

XQuery: Select a node in the context of a varaible

In order to learn XQuery I tried to run the following XQuery command in BaseX
let $x := doc("test.xq")//h2/following-sibling return $x::h2
I supposed it should be equivalent to
let $x := doc("test.xq")//h2/following-sibling::h2 return $x
But it gives the following error and doesn't work while the second command works
Error:
Stopped at D:/Program Files/BaseX/data/test.xq, 1/66:
[XPST0003] Unexpected end of query: '::h2'.
In general, how can I select some nodes (h2) in the context provided by a variable ($x := doc("test.xq")//h2/following-sibling)
That's not how variables work I'm afraid. It looks like you're trying to treat the variable declaration as a kind of "macro" and expecting its textual definition to be substituted in when the variable is referenced, but in fact XQuery variables are more like local variables in C or Java - the definition expression is evaluated to give a value or sequence and when you refer to the variable you get that value back.
So both the definition and referencing expressions need to be valid expressions in their own right. If you wanted to store the list of all following sibling elements in the variable and then later filter for just the h2 elements you'd need something like
let $x := doc("test.xq")//h2/following-sibling::* return $x[self::h2]
You can't separate the expression at that part, see following-sibling::h2 as one unit. You can do the following instead :
let $x := doc("test.xq")//h2 return $x/following-sibling::h2

Why there is no post in for range ? Golang

I would like to increment a variable after each range loop. However it seems it's not possible using the standard ( for init; condition; post { } ) for syntax therefore I'm wondering why . Here is what I'm trying to do
for item := range itemsList; page++ {
}
It seems the only way to do this is
for item := range itemsList{
page++
}
which doesn't look as nice as the first one.
The for statement specification does mention that a Range Clause stands alone.
ForStmt = "for" [ Condition | ForClause | RangeClause ] Block .
As opposed to a Post Statement, which is part of:
ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] .
That means a post statement is only valid in the context of an initialization and a condition, in order to potentially make that condition change (since it is executed after each execution of the block, and only if the block was executed).
There is no such need (making a condition stops a loop) in a Range clause, where the fact that the loop has been done over all the elements of a range (of an array, slice, string, map, or channel permitting receive operations) is enough for the loop to stops.
A range expression is evaluated once before beginning the loop (or at least its length is). There is no need to change anything after each execution of the block.
So trying to add a post statement to a range loop would generate a compilation error like:
expected '{', found ';'

Resources