In Go, when assigning multiple values to an array, braces {....} is used. What is this braces? Is it anonymous struct?
package main
import "fmt"
func main() {
var string_array [4]string = [4]string {"X", "Y", "Z", "W"}
var int_array [5]int = [5]int {1,2,3}
fmt.Println(string_array)
fmt.Println(int_array)
}
{"X", "Y", "Z", "W"} is the same as below and Go runtime is doing an implicit conversion?
type anonymous struct {
_0 string
_1 string
_2 string
_3 string
}
var anon anonymous = anonymous{"X", "Y", "Z", "W"}
Why not using ["X", "Y", "Z", "W"] if it is an array?
multiple assignment from array or slice
Go array initialization
Where in the Golang specification is this syntax explained?
It's documented in the Go language specification under "Composite literals" (emphasis mine):
Composite literals construct values for structs, arrays, slices, and maps and create a new value each time they are evaluated. They consist of the type of the literal followed by a brace-bound list of elements. Each element may optionally be preceded by a corresponding key.
Where "brace-bound" refers to the values being delimited with { and } as per your posted code.
From the grammar spec:
CompositeLit = LiteralType LiteralValue .
LiteralType = StructType | ArrayType | "[" "..." "]" ElementType |
SliceType | MapType | TypeName .
LiteralValue = "{" [ ElementList [ "," ] ] "}" . <-- This production-rule, right here
ElementList = KeyedElement { "," KeyedElement } .
KeyedElement = [ Key ":" ] Element .
Key = FieldName | Expression | LiteralValue .
FieldName = identifier .
Element = Expression | LiteralValue .
Related
In the Protocol Buffers Version 3 Language Specification
The EBNF syntax for an option is
option = "option" optionName "=" constant ";"
optionName = ( ident | "(" fullIdent ")" ) { "." ident }
constant = fullIdent | ( [ "-" | "+" ] intLit ) | ( [ "-" | "+" ] floatLit ) | strLit | boolLit
ident = letter { letter | decimalDigit | "_" }
fullIdent = ident { "." ident }
strLit = ( "'" { charValue } "'" ) | ( '"' { charValue } '"' )
charValue = hexEscape | octEscape | charEscape | /[^\0\n\\]/
hexEscape = '\' ( "x" | "X" ) hexDigit hexDigit
octEscape = '\' octalDigit octalDigit octalDigit
charEscape = '\' ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | '\' | "'" | '"' )
Or in plain English, an option may be assigned a dotted.notation.identifier, an integer, a float, a boolean, or a single- or double-quoted string, which MUST NOT have "raw" newline characters.
And yet, I'm encountering .proto files in various projects such as grpc-gateway and googleapis, where the rhs of the assignment is not quoted and spans multiple lines. For example in googleapis/google/api/http.proto there is this service definition in a comment block:
// service Messaging {
// rpc UpdateMessage(Message) returns (Message) {
// option (google.api.http) = {
// patch: "/v1/messages/{message_id}"
// body: "*"
// };
// }
// }
In other files, the use of semicolons (and occasionally commas) as separators seems somewhat arbitrary, and I have also seen keys repeated, which in JSON or JavaScript would result in loss of data due to overwriting.
Are there any canonical extensions to the language specification, or are people just Microsofting? (Yes, that's a verb now.)
I posted a similar question on the Protocol Buffers Google Group, and received a private message from a fellow at Google stating the following
This syntax is correct and valid for setting fields on a proto option field which is itself a field referencing a message type. This form is based on the TextFormat spec which I'm unclear if its super well documented, but here's an implementation of it: https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.text_format
When I have time, I will try to unpack what I learn from analyzing TextFormat.
update
I received an answer on the Groups forum
I think for better or worse, "what protoc implements" takes precedence over whatever the spec says. The spec came later and as far as I know we have not put a lot of effort into ensuring that it comprehensively matches the format that protoc expects. I believe the syntax you are looking at is missing from the .proto file format spec but is mentioned here as the "aggregate syntax."
The link above is to a section titled Custom Options in the Language Guide (proto2) page. If you scroll all the way to the end of that section, there is the following snippet that mentions TextFormat:
message FooOptions {
optional int32 opt1 = 1;
optional string opt2 = 2;
}
extend google.protobuf.FieldOptions {
optional FooOptions foo_options = 1234;
}
// usage:
message Bar {
optional int32 a = 1 [(foo_options).opt1 = 123, (foo_options).opt2 = "baz"];
// alternative aggregate syntax (uses TextFormat):
optional int32 b = 2 [(foo_options) = { opt1: 123 opt2: "baz" }];
}
The Official documentation about map type says:
map<key_type, value_type> map_field = N;
...where the key_type can be any integral or string type (so, any
scalar type except for floating point types and bytes). The value_type
can be any type.
I want to define a map<string, repeated string> field, but it seems illegal on my libprotoc 3.0.0, which complains Expected ">". So I wonder if there is any way to put repeated string into map.
A Possible workaround could be:
message ListOfString {
repeated string value = 1;
}
// Then define:
map<string, ListOfString> mapToRepeatedString = 1;
But ListOfString here looks redundant.
I had the same need, and got the same error. I do not believe this is possible. Here is the relevant BNF definitions from the language specification.
https://developers.google.com/protocol-buffers/docs/reference/proto3-spec
messageType = [ "." ] { ident "." } messageName
mapField = "map" "<" keyType "," type ">" mapName "=" fieldNumber [ "["fieldOptions "]" ] ";"
type = "double" | "float" | "int32" | "int64" | "uint32" | "uint64"
| "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64"
| "bool" | "string" | "bytes" | messageType | enumType
messageName = ident
ident = letter { letter | decimalDigit | "_" }
field = [ "repeated" ] type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
"repeated" keyword only appears in the field definition. The map definition requires a "type", which does not include the repeated keyword.
That means there are a few options.
You could create a wrapper around the repeated value as you indicated.
There is the older way people defined define maps, which is more burdensome but is equivalent. This is the backwards compatible example from the language guide.
https://developers.google.com/protocol-buffers/docs/proto3#maps
message MapFieldEntry {
key_type key = 1;
repeated value_type value = 2;
}
repeated MapFieldEntry map_field = N;
You would need to convert the data to a map yourself, but this should be fairly trivial in most languages. In Java:
List<MapFieldEntry> map_field = // Existing list from protobuf.
Map<key_type, List<value_type>> = map_field.stream()
.collect(Collectors.toMap(kv -> kv.key, kv -> kv.value));
Use google.protobuf.ListValue
https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#listvalue
This is an untyped list collection from their well known types.
I think it should be as follows.
message ListOfString {
repeated string what_ever_name = 1;
}
// Then define:
map<string, ListOfString> what_ever_name = 1;
Remember what_ever_name should be same in both places.
The Official documentation about map type says:
map<key_type, value_type> map_field = N;
...where the key_type can be any integral or string type (so, any
scalar type except for floating point types and bytes). The value_type
can be any type.
I want to define a map<string, repeated string> field, but it seems illegal on my libprotoc 3.0.0, which complains Expected ">". So I wonder if there is any way to put repeated string into map.
A Possible workaround could be:
message ListOfString {
repeated string value = 1;
}
// Then define:
map<string, ListOfString> mapToRepeatedString = 1;
But ListOfString here looks redundant.
I had the same need, and got the same error. I do not believe this is possible. Here is the relevant BNF definitions from the language specification.
https://developers.google.com/protocol-buffers/docs/reference/proto3-spec
messageType = [ "." ] { ident "." } messageName
mapField = "map" "<" keyType "," type ">" mapName "=" fieldNumber [ "["fieldOptions "]" ] ";"
type = "double" | "float" | "int32" | "int64" | "uint32" | "uint64"
| "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64"
| "bool" | "string" | "bytes" | messageType | enumType
messageName = ident
ident = letter { letter | decimalDigit | "_" }
field = [ "repeated" ] type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
"repeated" keyword only appears in the field definition. The map definition requires a "type", which does not include the repeated keyword.
That means there are a few options.
You could create a wrapper around the repeated value as you indicated.
There is the older way people defined define maps, which is more burdensome but is equivalent. This is the backwards compatible example from the language guide.
https://developers.google.com/protocol-buffers/docs/proto3#maps
message MapFieldEntry {
key_type key = 1;
repeated value_type value = 2;
}
repeated MapFieldEntry map_field = N;
You would need to convert the data to a map yourself, but this should be fairly trivial in most languages. In Java:
List<MapFieldEntry> map_field = // Existing list from protobuf.
Map<key_type, List<value_type>> = map_field.stream()
.collect(Collectors.toMap(kv -> kv.key, kv -> kv.value));
Use google.protobuf.ListValue
https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#listvalue
This is an untyped list collection from their well known types.
I think it should be as follows.
message ListOfString {
repeated string what_ever_name = 1;
}
// Then define:
map<string, ListOfString> what_ever_name = 1;
Remember what_ever_name should be same in both places.
For example if I have a string {a, b, c}. I need to print out on the console all the permutations without repeating letters from 1 letter to 3 letters like this:
a b c ab ac abc acb ba bc bac bca ca cb cab cba
How can I write this using recursion?
If you need all the permutations of the chars into a String you can use a recursive function.
Here's the code in Swift.
func visit(unused:[Character], used: [Character] = [Character]()) -> [String] {
var result = [String(used)]
for (index, char) in unused.enumerate() {
var unused = unused
unused.removeAtIndex(index)
var used = used
used.append(char)
result = result + visit(unused, used: used)
}
return result
}
As you can see the function receives 2 params:
unused: represents the list of chars not yet used
used: the chars used to build possible element of the ouput. This parameter is optional so if it's not passed to the function, an empty array is used (this is useful for the first invocation).
Test
let word = "abc"
let chars = [Character](word.characters)
print(visit(chars))
["", "a", "ab", "abc", "ac", "acb", "b", "ba", "bac", "bc", "bca", "c", "ca", "cab", "cb", "cba"]
Omitting the empty String
This results also contains the empty String but you can easily omit this value just update the function as shown below.
func visit(unused:[Character], used: [Character] = [Character]()) -> [String] {
var result = [String]()
if !used.isEmpty {
result.append(String(used))
}
for (index, char) in unused.enumerate() {
var unused = unused
unused.removeAtIndex(index)
var used = used
used.append(char)
result = result + visit(unused, used: used)
}
return result
}
I've written this question out many times, and have finally realized that my biggest problem is that I don't know how I want to represent this data, and that's making it really hard to reason about the rest of the code.
The way the data is represented in Python:
class LSP():
C_MASK_MAP={
"A":"Ch A",
"B":"Ch B",
"C":"Ch C",
"D":"Ch D",
"T":"Tmpr",
"Y":"Batt",
"L":"Acc"
}
ADC_CHANS= (
"Ch A",
"Ch B",
"Ch C",
"Ch D",
"Tmpr",
"Batt"
)
ADC_MAJORS = (
"Ch A",
"Ch B",
"Ch C",
)
My imaginary Rust code (I realize the names will need updating but are the same here for clarity):
enum C_MASK_MAP {
Ch_A = 'A',
Ch_B = 'B',
Ch_C = 'C',
Ch_D = 'D',
Tmpr = 'T',
Batt = 'Y',
Acc = 'L'
}
//...
let ADC_CHANS = [
C_MASK_MAP::Ch_A,
C_MASK_MAP::Ch_B,
C_MASK_MAP::Ch_C,
C_MASK_MAP::Ch_D,
C_MASK_MAP::Tmpr,
C_MASK_MAP::Batt
];
ADC_MAJORS = [
C_MASK_MAP::Ch_A,
C_MASK_MAP::Ch_B,
C_MASK_MAP::Ch_C,
];
I've considered making C_MASK_MAP a HashMap<char, &'static str>, but then I ran into a huge mess trying not to make a million copies of the strs everywhere and dealing with lifetimes while avoiding making Strings, and the syntactic mess that is a reference to a static str (&&'static str or something).
I think there'd be a real benefit to being able to use an enum (or similar) because the values wouldn't be as big and are more easily interchanged C_MASK_MAP.get(key).expect("invalid key") vs just casting.
Your strings are sentinel values; this is a common pattern in Python, but is not how things should be done in Rust: enums are what such things should be: you’re encoding the legal values in the type system.
You could end up with something like this:
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Mask {
ChA = b'A',
ChB = b'B',
ChC = b'C',
ChD = b'D',
Tmpr = b'T',
Batt = b'Y',
Acc = b'L',
}
// e.g. Mask::ChA.into() == 'A'
impl Into<char> for Mask {
fn into(self) -> char {
self as u8 as char
}
}
impl Mask {
// e.g. Mask::from('A') == Ok(Mask::ChA)
pub fn from(c: char) -> Result<Mask, ()> {
match c {
'A' => Ok(Mask::ChA),
'B' => Ok(Mask::ChB),
'C' => Ok(Mask::ChC),
'D' => Ok(Mask::ChD),
'T' => Ok(Mask::Tmpr),
'Y' => Ok(Mask::Batt),
'L' => Ok(Mask::Acc),
_ => Err(()),
}
}
// e.g. Mask::ChA.is_chan() == true
pub fn is_chan(&self) -> bool {
match *self {
Mask::ChA | Mask::ChB | Mask::ChC | Mask::ChD | Mask::Tmpr | Mask::Batt => true,
Mask::Acc => false,
}
}
// e.g. Mask::ChD.is_major() == false
pub fn is_major(&self) -> bool {
match *self {
Mask::ChA | Mask::ChB | Mask::ChC => true,
Mask::ChD | Mask::Tmpr | Mask::Batt | Mask::Acc => false,
}
}
}
If you wanted you could implement std::str::FromStr for Mask as well, which would allow "A".parse() == Ok(Mask::ChA):
impl FromStr for Mask {
type Err = ();
fn from_str(s: &str) -> Result<Mask, ()> {
match s {
"A" => Ok(Mask::ChA),
"B" => Ok(Mask::ChB),
"C" => Ok(Mask::ChC),
"D" => Ok(Mask::ChD),
"T" => Ok(Mask::Tmpr),
"Y" => Ok(Mask::Batt),
"L" => Ok(Mask::Acc),
_ => Err(()),
}
}
}
I suspect that is_chan et al. may be more suitable than ADC_CHANS et al., but if you do actually need them, they work fine (you could do [Mask; 6] too, but if you need to add new elements it’d change the type which is an API compatibility break if public):
pub static ADC_CHANS: &'static [Mask] = &[
Mask::ChA,
Mask::ChB,
Mask::ChC,
Mask::ChD,
Mask::Tmpr,
Mask::Batt,
];
pub static ADC_MAJORS: &'static [Mask] = &[
Mask::ChA,
Mask::ChB,
Mask::ChC,
];
Copying a &'static str (i.e. copying the reference only) has no cost. A deep copy of the string would be a clone and would be typed as a String.
If &'static str is too verbose for you, you can always define a type alias.
type Str = &'static str;
HashMap<char, &'static str> corresponds nicely to your original map. However, if you don't need the full range of char for the key and you don't actually need to have the value typed as a char anywhere besides indexing the map, you should use an enum instead, as that will restrict the legal values that can be used as keys.