GNU make manual describes usage of computed names as follows:
VAR1 := 5
VARX := VAR1
$(info $((VARX)))
Output: 5
How to use computed name with multiple values inside?
VAR1 := 5
VAR2 := 7
VARY := VAR1 VAR2
$(info ???(VARY))
So that output would be 5 7?
Does NMake have similar functionality?
For GNU-make:
$(foreach item,$(VARY),$($(item)))
Related
This snippet works as expected play.golang.org/p/VuCl-OKMav
i := 10
next := 11
prev, i := i, next
However this nearly identical snippet gives non-name f.Bar on left side of := play.golang.org/p/J8NNWPugQG
type Foo struct {
Bar int
}
f := Foo{10}
next := 11
prev, f.Bar := f.Bar, next
What's special about the struct that stops type inference? Is this a bug?
It's an open issue.
Issue 6842: spec: Assigning to fields with short declaration notation
It's not really a type inference issue, it's just that the left-hand-side of := must be a list of identifiers, and f.Bar is not an identifier, so it can't be declared — not even with :='s slightly-more-permissive rules for what it can declare. See "Short variable declarations" in The Go Programming Language Specification.
From the spec's Short variable declarations section:
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.
So if you declare the variable inside another type (struct Foo in the example), it is disqualified by "provided they were originally declared earlier in the same block".
So the answer is to just set the pre-declared variable equal not using the := syntax to the value:
...
var prev int
prev, f.Bar = f.Bar, next
...
it is just that you already assigned f to Foo
f := Foo{100}
in this case f.Bar is 100
so to reassign it just remove the column
var prev string
f := Foo{10}
next := 11
prev, f.Bar = f.Bar, next
this will work
I'm considering writing a template to Go code generator and wonder:
If I have many string constants and/or variables with the same value would they be stored in an executable file multiple times or compiler will make an optimisation and store just 1 instance per duplicate and refer it wherever needed?
E.g.
File1.go
========
s1 := "some_string_1"
s2 := "some_string_2"
FileN.go
========
a1 := "some_string_1"
a1 := "some_string_2"
Would it affect file size if I have multiple files with the same constants or compiler is smart enough to make optimization?
Imagine that in many templates I have somthing like:
Template 1
==========
{% for a in list1 %}<td>{{a}}</td>{% endfor %}
Tempalte 2
==========
{% for b in list2 %}<td>{{b.c}}</td><td>{{b.d}}</td>{% endfor %}
that would be translated to something like:
for i, a := range list {
write("<td>")
write(a)
write("</td>")
}
for i, b := range list2 {
write("<td>")
write(b.c)
write("</td></td>")
write(b.d)
write("</td>")
}
Obviously the <td> & </td> would be repeated many times in code. So would it make any sense to create a global array of strings and takes values from it? Something like:
myStrings := [...]string{
"<td>",
"</td>"
}
for i, a := range list {
write(myStrings[0])
write(a)
write(myStrings[1])
}
The language spec says nothing regarding the internal storage of string constants or literals. Based on this discussion I would assume there is currently no interning in the language; https://github.com/golang/go/issues/5160 though that is a bit dated now.
That same search turned up this project which you may find helpful; https://gist.github.com/karlseguin/6570372
In Python, I can declare a variable as d ='/some/dir/%s' and later replace %s with any value as
>>> d = '/some/dir/%s'
>>> d % "hello"
'/some/dir/hello'
Is it possible to do the same in Go? If so, how?
Yes, fmt.Sprintf does that:
d := "/some/dir/%s"
fmt.Sprintf(d, "hello") // Returns "/some/dir/hello"
This snippet works as expected play.golang.org/p/VuCl-OKMav
i := 10
next := 11
prev, i := i, next
However this nearly identical snippet gives non-name f.Bar on left side of := play.golang.org/p/J8NNWPugQG
type Foo struct {
Bar int
}
f := Foo{10}
next := 11
prev, f.Bar := f.Bar, next
What's special about the struct that stops type inference? Is this a bug?
It's an open issue.
Issue 6842: spec: Assigning to fields with short declaration notation
It's not really a type inference issue, it's just that the left-hand-side of := must be a list of identifiers, and f.Bar is not an identifier, so it can't be declared — not even with :='s slightly-more-permissive rules for what it can declare. See "Short variable declarations" in The Go Programming Language Specification.
From the spec's Short variable declarations section:
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.
So if you declare the variable inside another type (struct Foo in the example), it is disqualified by "provided they were originally declared earlier in the same block".
So the answer is to just set the pre-declared variable equal not using the := syntax to the value:
...
var prev int
prev, f.Bar = f.Bar, next
...
it is just that you already assigned f to Foo
f := Foo{100}
in this case f.Bar is 100
so to reassign it just remove the column
var prev string
f := Foo{10}
next := 11
prev, f.Bar = f.Bar, next
this will work
Using gmake v3.80, how can I create a rule that ORs together two things. I'm starting with this code:
ifeq "$(BUILD_ARCH)" "lnx86_22"
TEST_ARCH := i86
endif
ifeq "$(BUILD_ARCH)" "linux_24_i86"
TEST_ARCH := i86
endif
And would like to combine the two ifeq(s) into a single if that ORs the two conditions together, perhaps something like this?
ifeq "$(BUILD_ARCH)" "lnx86_22" OR "$(BUILD_ARCH)" "linux_24_i86"
TEST_ARCH := i86
endif
What is the actual syntax that would allow me to do this?
You can use $(filter ...) for that. Like this:
ifneq (,$(filter $(BUILD_ARCH),lnx86_22 linux_24_i86))
TEST_ARCH := i86
endif
Another option would be to use constructed variable names:
lnx86_22_ARCH := i86
linux_24_i86_ARCH := i86
...
TEST_ARCH := $($(BUILD_ARCH)_ARCH)
ifeq (,$(TEST_ARCH))
$(error Failed, unknown arch $(BUILD_ARCH))
Failed, unknown arch $(BUILD_ARCH)
endif
If you are able to upgrade to newer versions of GNU make there are other options available.