And I can't seem to understand this kind of variable declaration:
_, prs := m["example"]
What exactly is "_," doing and why have they declared a variable like this instead of
prs := m["example"]
(I found it as part of Go by Example: Maps)
It avoids having to declare all the variables for the returns values.
It is called the blank identifier.
As in:
_, y, _ := coord(p) // coord() returns three values; only interested in y coordinate
That way, you don't have to declare a variable you won't use: Go would not allow it. Instead, use '_' to ignore said variable.
(the other '_' use case is for import)
Since it discards the return value, it is helpful when you want to check only one of the returned values, as in "How to test key existence in a map?" shown in "Effective Go, map":
_, present := timeZone[tz]
To test for presence in the map without worrying about the actual value, you can use the blank identifier, a simple underscore (_).
The blank identifier can be assigned or declared with any value of any type, with the value discarded harmlessly.
For testing presence in a map, use the blank identifier in place of the usual variable for the value.
As Jsor adds in the comments:
"generally accepted standard" is to call the membership test variables "ok" (same for checking if a channel read was valid or not)
That allows you to combine it with test:
if _, err := os.Stat(path); os.IsNotExist(err) {
fmt.Printf("%s does not exist\n", path)
}
You would find it also in loop:
If you only need the second item in the range (the value), use the blank identifier, an underscore, to discard the first:
sum := 0
for _, value := range array {
sum += value
}
The Go compiler won't allow you to create variables that you never use.
for i, value := range x {
total += value
}
The above code will return an error message "i declared and not used".
Since we don't use i inside of our loop we need to change it to this:
for _, value := range x {
total += value
}
The blank identifier may be used whenever syntax requires a variable name but program logic does not, for instance to discard an unwanted loop index when we require only the element value.
Excerpt From:
The Go Programming Language (Addison-Wesley Professional Computing Series)
Brian W. Kernighan
This material may be protected by copyright.
_ is the blank identifier. Meaning the value it should be assigned is discarded.
Here it is the value of example key that is discarded. The second line of code would discard the presence boolean and store the value in prs.
So to only check the presence in the map, you can discard the value. This can be used to use a map as a set.
The great use case for the unused variable is the situation when you only need a partial output. In the example below we only need to print the value (state population).
package main
import (
"fmt"
)
func main() {
statePopulations := map[string]int{
"California": 39250017,
"Texas": 27862596,
"Florida": 20612439,
}
for _, v := range statePopulations {
fmt.Println(v)
}
}
It is called the blank identifier and it helps in cases where you wish to discard the value that is going to be returned and not reference it
Some places where we use it:
A function returns a value and you don't intend to use it in the
future
You want to iterate and need an i value that you will not be
using
Basically, _, known as the blank identifier. In GO we can't have variables that are not being used.
As an instance when you iterating through an array if you are using value := range you don't want a i value for iterating. But if you omit the i value it will return an error. But if you declare i and didn't use it, it will also return an error.
Therefore, that is the place where we have to use _,.
Also it is used when you don't want a function's return value in the future.
An unused variable is not allowed in Golang
If you were coming from other programming languages this might feel bit difficult to get used to this. But this results in more cleaner code. So by using a _ we are saying we know there is a variable there but we don't want to use it and telling the compiler that does not complain me about it. :)
_(underscore) in Golang is known as the Blank Identifier. Identifiers are the user-defined name of the program components used for the identification purpose. Golang has a special feature to define and use the unused variable using Blank Identifier. Unused variables are those variables that are defined by the user throughout the program but he/she never makes use of these variables.
Go compiler throws an error whenever it encounters a variable declared but not used. Now we can simply use the blank identifier and not declare any variable at all.
// Golang program to show the compiler
// throws an error if a variable is
// declared but not used
package main
import "fmt"
// Main function
func main() {
// calling the function
// function returns two values which are
// assigned to mul and div identifier
mul, div := mul_div(105, 7)
// only using the mul variable
// compiler will give an error
fmt.Println("105 x 7 = ", mul)
}
// function returning two
// values of integer type
func mul_div(n1 int, n2 int) (int, int) {
// returning the values
return n1 * n2, n1 / n2
}
Output
./prog.go:15:7: div declared and not used
Let’s make use of the Blank identifier to correct the above program. In place of div identifier just use the _ (underscore). It allows the compiler to ignore declared and not used error for that particular variable.
// Golang program to the use of Blank identifier
package main
import "fmt"
// Main function
func main() {
// calling the function
// function returns two values which are
// assigned to mul and blank identifier
mul, _ := mul_div(105, 7)
// only using the mul variable
fmt.Println("105 x 7 = ", mul)
}
// function returning two
// values of integer type
func mul_div(n1 int, n2 int) (int, int) {
// returning the values
return n1 * n2, n1 / n2
}
Output
105 x 7 = 735
Related
I try to understand this line:
query : SelectionSet Response RootQuery
I understand this is a "Type Annotations" syntax, but I don't find documentation example or explanation about multiple "word" separated by whitespace.
I see these examples:
answer : Int
factorial : Int -> Int
distance : { x : Float, y : Float } -> Float
add : number -> number -> number (ref)
I found anywhere query: Int Int Int syntax, neither in Elm Syntax nor in Beginning Elm nor in Elm FAQ.
Do SelectionSet, Response, RootQuery are
functions arguments?
multi value function results?
Best regards,
Stéphane
Same question on Elm Discourse
A response in How do I read the type of a SelectionSet?
SelectionSet is a type with two type variables. Here's the definition:
type SelectionSet decodesTo scope
= SelectionSet (List RawField) (Decoder decodesTo)
In a type declaration like this, any lowercase name after the type is a type variable, which can be filled in by any type (except for a few special constrained type variables, number, appendable, comparable, and compappend). A simpler example would be Maybe, where you can have a Maybe Int or a Maybe String. Similarly, Dict takes two type variables (for the key and value) so you can have Dict String String or Dict Int MyCustomType (the key type of a Dict does need to be comparable).
So, in your scenario, Response corresponds to decodesTo and RootQuery corresponds to scope. The SelectionSet has a Decoder that decodes to a Response value, and it also carries around this scope type variable, which isn't used directly in the data that it holds. It's used as a piece of information at the type level, so that you (and the library) know that calling map (which has the type (a -> b) -> SelectionSet a scope -> SelectionSet b scope) will preserve that scope value; that is, it prevents mixing scopes.
The above is mostly general function syntax for functional languages such as Haskell, Elm, etc.
For example:
add : Int -> Int -> Int
add x y = x + y
The first line says that is function of two integer arguments with an integer return value. The second line implements the specification given in the first. One calls this function as follows:
> add 2 3
5
Note this example:
> inc = add 1
> inc 2
3
Here add 1 is a "partially applied function." It has type Int -> Int. In many languages, add 1 would not make sense. But since functions are first-class things in Elm, add 1 makes sense: it is a function. Partial application is also called "currying."
I'm new to Lua and trying to understand the concept of OOP in Lua. To do so, I've tried creating an object and creating methods and "private variables". My issue is when I try to use "setters" or "getters", it's indicating that my tables are returning NIL which means I'm either having a scoping issue or something else I can't figure out.
The kicker is I'm using an example from an online Lua coding tutorial, and when I run the tutorial it works flawlessly. However, when I run mine, I get NIL or nothing outputs whenever I try to "get" or return a value from one of the member functions.
I'm using a couple of different environments:
ZeroBrain
Sublime Text
Lua for Windows
Do you know why my code is not returning populated tables?
newPlayer = function(n, h, a, r)
player = {}
n = n or ""
h = h or 100
a = a or 100
r = r or 0
function player:getPlayerName()
return n
end
function player:getPlayerHealth()
return h
end
function player:getPlayerArmor()
return a
end
function player:getPlayerRank()
return r
end
function player:setPlayerName(arg)
n = arg
end
function player:setPlayerHealth(arg)
h = arg
end
function player:setPlayerArmor(arg)
a = arg
end
function player:setPlayerRank(arg)
r = arg
end
function player:connect(arg)
print(string.format(" %s joined" , arg))
end
return player
end
player1 = newPlayer("John", 100, 100, 1000)
player1.getPlayerName()
Your code does not contain "populated tables" to return.
Your newPlayer function does create a table, and it does return it. It creates a number of functions within that table. But that's all newPlayer does: creates a table and puts some functions in it.
The data accessed by those functions is not part of the table. n, h, a, and r (BTW, please use better variable names) are all local variables. Your inner functions will access the specific stack containing those variables, but the variables themselves will not be magically associated with the table.
Your principle problem is almost certainly with the setters. And it comes from a combination of this:
function player:setPlayerName(arg)
with this:
player1.getPlayerName()
When you create a function using a : character between a table name and the function's name, you are using syntactic sugar for a function which implicitly takes as its first argument a value called self. As the name suggests, this is supposed to represent the object which this function is being called upon. So your function creation code is equivalent to:
function player.setPlayerName(self, arg)
Since you create all of your functions with :, all of your functions take at least one parameter.
The : syntax can also be used when calling such functions. If you did player1:getPlayerName(), this would cause the table you accessed to find the getPlayerName function to be used as the first argument in the function call. So that line would be equivalent to player1.getPlayerName(player1).
Obviously, these two syntaxes are mirrors of one another: functions created with : take a parameter that is expected to refer to the table it is being called on, and functions called with : will be given the table which was accessed to get that function.
But... your code didn't stick to the symmetry. You created the functions with :, but you call them with .
Now, you get functions are able to get away with this because... well, none of your values are actually part of the table. So your get functions just return the local value that they adopted from their creating context.
The set functions pose a problem. See, they take a parameter. But because the function was declared with :, they really take two parameters, the first being the implicit self.
Now, : syntax is just syntactic sugar; it's just a convenient way to do what you could have done yourself. So it is in theory OK to call a function with . even if you created it with :. But if you do so, you must pass the table as the first parameter. Though your code doesn't show it, I strongly suspect you didn't do that.
If you called player1.setPlayerName("foo"), what will happen is that the implicit self parameter will get the value "foo", and the arg parameter will be nil. And you will assign that nil value to the n local variable. So subsequent calls to player1.getPlayerName() will return nil.
Basically, what's going on here is that you're combining two different ways of creating objects in Lua. You stored your private data in a way that external code cannot access (ie: local upvalues), but that data is now no longer part of the table itself. Which means that, although you dutifully create those functions with : syntax to indicate that they take a self table, they never actually use that table. And because they never use the table, it's a lot harder to figure out what's going wrong.
Basically, the key here is to be symmetrical. If you create a function with :, then you should either call it with : or make sure to pass it the object table as the first parameter.
Broadly speaking, the standard way to create private members is by convention, not by forbidding it. That is, you agree not to mess with any members of a table other than those with certain names. Python convention is to pretend that names starting with _ don't exist, and Lua programs sometimes use that.
Upvalues are an interesting solution for private variables, but they do come with problems. If you want to invent a member variable, you have to do it in a centralized place rather than wherever you might need one. Even if the variable is optional, you have to create a named local at the top of the function.
TLDR of Nicol's answer, see my answer to another question:
function player:setPlayerArmor(arg)
a = arg
end
The : syntax is syntactic sugar. It creates an implicit 'self' argument when declared, and when used. If you declare it one way and use it another, the arguments won't be what you're expecting. Say your player has 100 health. Look at this result:
player1.setPlayerHealth(55, 66)
print(player1.getPlayerHealth())
-- will display '66', not '55' because `:` declares implicit 'self' argument
This displays 66 because the setPlayerHealth function has an implicit 'self' parameter because it was declared with :. If you instead called it
with the ::
player1:setPlayerHealth(55, 66)
print(player1:getPlayerHealth())
-- will display '55' because `:` passes player1 as self
function player:setHealth1(arg)
-- implicit 'self' argument refers to player1 when called on player1
end
-- is the same as
function player.setHealth2(self, arg)
-- with `.` notation, you need to add the 'self' argument explicitly
end
player1.setHealth1(31) -- self argument will be 31 and arg will be nil
player1.setHealth2(32) -- self argument will be 32 and arg will be nil
player1:setHealth1(33) -- self argument will be player1 and arg will be 33
player1:setHealth2(34) -- self argument will be player1 and arg will be 34
I can write a lambda expression outside of parenthesis, but I cannot put it there by name. I have tried many ways:
val plus3: (Int,Int,Int)->Int = {a,b,c->a+b+c}
println(apply3(1,2,3){a,b,c->a+b+c}) // OK
println(apply3(1,2,3){plus3}) // Type mismatch. Required: Int, Found: (Int,Int,Int)->Int
println(apply3(1,2,3){(plus3)}) // Type mismatch. Required: Int, Found: (Int,Int,Int)->Int
println(apply3(1,2,3)plus3) // unresolved reference
println(apply3(1,2,3){plus3()}) // value captured in a closure
println(apply3(1,2,3){(plus3)()}) // value captured in a closure
What is the syntax to put a name there (outside of parenthesis)?
I don't know why, but in the documentation there is not a word on the theme. It says we could put lambda there, but not a word about a variable or constant that denotes that lambda.
I don't know why, but in the documentation there is not a word on the theme.
Yes, there is:
In Kotlin, there is a convention that if the last parameter to a function is a function, and you're passing a lambda expression as the corresponding argument, you can specify it outside of parentheses
plus3 is an identifier and not a lambda expression, so you can't specify it outside of parentheses.
The type of plus3 is (Int,Int,Int->Int). The same as of {a,b,c->a+b+c}. Look again at the messages that I am getting from Kotlin compiler.
You mean the error messages when you pass { plus3 }? By Kotlin rules { plus3 } is a lambda which ignores its argument (if any) and returns plus3. So the rule applies, and apply3(1,2,3){plus3} means the same as apply3(1,2,3,{plus3}).
It sees plus3 as Int.
Exactly the opposite: it expects to see an Int as the return value of the lambda and sees plus3 which is (Int,Int,Int) -> Int.
So, the problem here is not of the high philosophical nature, but seems pure syntactic.
That was exactly my point: the rule is purely syntactic, it's applied before the compiler knows anything about type or value of plus3, and so it doesn't know or care whether this value happens to be a lambda.
The rule could instead say
In Kotlin, there is a convention that if the last parameter to a function has a function type, you can specify it outside of parentheses
in which case apply3(1,2,3) plus3 would work. But it doesn't.
Placing a lambda expression outside of a function call's parentheses is the same as placing it inside the parentheses like this:
println(apply3(1, 2, 3, { a, b, c -> a + b + c }))
From here, we can simply assign the lambda to a val (as you have done) which results in:
val plus3: (Int, Int, Int) -> Int = { a, b, c -> a + b + c }
println(apply3(1, 2, 3, plus3))
According to the Go reference there are two ways of declaring a variable
Variable_declarations (in the format of var count = 0 or var count int)
and
Short_variable_declarations (in the format of count := 0)
I found it's very confusing to decide which one to use.
The differences I know (till now) are that:
I can only using a count := 0 format when in the scope of a function.
count := 0 can be redeclared in a multi-variable short declaration.
But they do behave the same as far as I know. And in the reference it also says:
It (the count:=0way) is shorthand for a regular variable declaration with initializer expressions but no types
My confusions are:
If one is just the shorthand way of the other, why do they behave differently?
In what concern does the author of Go make two ways of declaring a variable (why are they not merged into one way)? Just to confuse us?
Is there any other aspect that I should keep my eyes open on when using them, in case I fall into a pit?
The Variable declarations make it clear that variables are declared. The var keyword is required, it is short and expresses what is done (at the file level everything excluding comments has to start with a keyword, e.g. package, import, const, type, var, func). Like any other block, variable declarations can be grouped like this:
var (
count int
sum float64
)
You can't do that with Short variable declarations. Also you can use Variable declarations without specifying the initial value in which case each variable will have the zero value of its type. The Short variable declaration does not allow this, you have to specify the initial value.
One of Go's guiding design principle was to make the syntax clean. Many statements require or it is handy that they allow declaring local variables which will be only available in the body of the statement such as for, if, switch etc. To make the syntax cleaner and shorter, Short variable declaration is justified in these cases and it is unambigous what they do.
for idx, value := range array {
// Do something with index and value
}
if num := runtime.NumCPU(); num > 1 {
fmt.Println("Multicore CPU, cores:", num)
}
Another difference: Redeclaration
Quoting from the Language specification:
Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.
This one is also handy. Suppose you want to do proper error handling, you can reuse an err variable because most likely you only need it to check if there were any errors during the last function call:
var name = "myfile.txt"
fi, err := os.Stat(name) // fi and err both first declared
if err != nil {
log.Fatal(err)
}
fmt.Println(name, fi.Size(), "bytes")
data, err := ioutil.ReadFile(name) // data is new but err already exists
// so just a new value is assigned to err
if err != nil {
log.Fatal(err)
}
// Do something with data
What's happening here?
package main
import "fmt"
func main() {
myArray :=[...]int{12,14,26} ;
fmt.Println(myArray)
myArray :=[...]int{11,12,14} //error pointing on this line
fmt.Println(myArray) ;
}
It throws an error that says
no new variables on left side of :=
What I was doing was re-assigning values to an already declared variable.
Remove the colon : from the second statement as you are assigning a new value to existing variable.
myArray = [...]int{11,12,14}
colon : is used when you perform the short declaration and assignment for the first time as you are doing in your first statement i.e. myArray :=[...]int{12,14,26}.
There are two types of assignment operators in go := and =. They are semantically equivalent (with respect to assignment) but the first one is also a "short variable declaration" ( http://golang.org/ref/spec#Short_variable_declarations ) which means that in the left we need to have at least a new variable declaration for it to be correct.
You can change the second to a simple assignment statement := -> = or you can use a new variable if that's ok with your algorithm.
As a side note, redeclaration can only appear in a multi-variable short declaration
Quoting from the Language specification:
Unlike regular variable declarations, a short variable declaration may
redeclare variables provided they were originally declared earlier in
the same block with the same type, and at least one of the non-blank
variables is new. As a consequence, redeclaration can only appear in a
multi-variable short declaration. Redeclaration does not introduce a
new variable; it just assigns a new value to the original.
package main
import "fmt"
func main() {
a, b := 1, 2
c, b := 3, 4
fmt.Println(a, b, c)
}
Here is a very good example about redeclaration of variables in golang:
https://stackoverflow.com/a/27919847/4418897
myArray :=[...]int{12,14,26}
As stated by the previous commenters, := is a type of short-hand and/or the short-form of variable declaration.
So in the statment above you are doing two things.
You are declaring your variable to be myArray.
You are assigning an array of integers to the myArray variable.
The second part of your code fails, because what you are doing here:
myArray :=[...]int{11,12,14} //error pointing on this line
Is RE-declaring the existing variable myArray, which already contains integer values.
This works:
myArray = [...]int{11,12,14} // NO error will be produced by this line
Because, it is assigning the integer array to the existing ( pre-declared / initialized ) variable.