type A struct {
B struct {
Some string
Len int
}
}
Simple question. How to initialize this struct? I would like to do something like this:
a := &A{B:{Some: "xxx", Len: 3}}
Expectedly I'm getting an error:
missing type in composite literal
Sure, I can create a separated struct B and initialize it this way:
type Btype struct {
Some string
Len int
}
type A struct {
B Btype
}
a := &A{B:Btype{Some: "xxx", Len: 3}}
But it not so useful than the first way. Is there a shortcut to initialize anonymous structure?
The assignability rules are forgiving for anonymous types which leads to another possibility where you can retain the original definition of A while allowing short composite literals of that type to be written. If you really insist on an anonymous type for the B field, I would probably write something like:
package main
import "fmt"
type (
A struct {
B struct {
Some string
Len int
}
}
b struct {
Some string
Len int
}
)
func main() {
a := &A{b{"xxx", 3}}
fmt.Printf("%#v\n", a)
}
Playground
Output
&main.A{B:struct { Some string; Len int }{Some:"xxx", Len:3}}
do it this way:
type Config struct {
Element struct {
Name string
ConfigPaths []string
}
}
config = Config{}
config.Element.Name = "foo"
config.Element.ConfigPaths = []string{"blah"}
This is simpler imo:
type A struct {
B struct {
Some string
Len int
}
}
a := A{
struct {
Some string
Len int
}{"xxx", 3},
}
fmt.Printf("%+v", a)
Related
I have an example Pest grammar:
WHITESPACE = _{ " " }
identifier = #{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")* }
int_literal = { DECIMAL_NUMBER+ }
assignment_op = { ":=" }
formula = { (identifier ~ assignment_op ~ int_literal) | int_literal }
file = { formula ~ EOI }
and a pest-ast derives:
extern crate pest_derive;
extern crate from_pest;
extern crate pest_ast;
extern crate pest;
mod parser {
#[derive(Parser)]
#[grammar = "talk/formula.pest"]
pub struct Parser;
}
mod ast {
use super::parser::Rule;
use pest::Span;
fn span_into_str(span: Span) -> &str {
span.as_str()
}
#[derive(Debug, FromPest)]
#[pest_ast(rule(Rule::int_literal))]
pub struct IntLiteral {
#[pest_ast(outer(with(span_into_str), with(str::parse::<i64>), with(Result::unwrap)))]
pub value: i64
}
#[derive(Debug, FromPest)]
#[pest_ast(rule(Rule::identifier))]
pub struct Identifier {
#[pest_ast(inner(with(span_into_str), with(String::from)))]
pub value: String
}
#[derive(Debug, FromPest)]
#[pest_ast(rule(Rule::assignment_op))]
pub struct AssignmentOp {
}
#[derive(Debug, FromPest)]
#[pest_ast(rule(Rule::formula))]
pub enum Formula {
Assignment {
lvalue: Identifier,
a: AssignmentOp, // can I skip this?
rvalue: IntLiteral,
},
IntLiteral {
rvalue: IntLiteral,
}
}
#[cfg(test)]
mod tests {
use super::*;
use super::ast::*;
use pest::Parser;
use from_pest::FromPest;
#[test]
fn test_formula0() {
let source = "a := 12";
let mut parse_tree = parser::Parser::parse(parser::Rule::formula, source).unwrap();
println!("parse tree = {:#?}", parse_tree);
let syntax_tree: Formula = Formula::from_pest(&mut parse_tree).expect("infallible");
println!("syntax tree = {:#?}", syntax_tree);
}
}
Running the test, I'm getting infallible: NoMatch panic.
Does pest-ast even support deriving enum variants with fields?
Can I match enum variant to a parenthesed () group of terminals?
Can I skip some terminals? I don't exactly need to know := was used if I get an AssignmentExpression { lvalue, rvalue } in the end.
I found an example in pest-ast issue #8. Grammar rules:
seq = { a ~ b ~ c }
choice = { a | b | c }
compund_seq = { a ~ (b | c) }
compound_choice = { (a ~ b) | (b ~ c) }
assign = { (a|b|c) ~ "=" ~ number }
assigns = { (assign ~ ",")* ~ assign ~ ","? }
correspond to code:
enum choice<'pest>{
struct _1(a<'pest>),
struct _2(b<'pest>),
struct _3(c<'pest>),
}
struct compound_seq<'pest>(
#[pest_ast(outer)] Span<'pest>,
a<'pest>,
enum _2 {
struct _1(b<'pest>),
struct _2(c<'pest>),
},
);
enum compound_choice<'pest>{
struct _1(
#[pest_ast(outer)] Span<'pest>,
a<'pest>,
b<'pest>,
),
struct _2(
#[pest_ast(outer)] Span<'pest>,
b<'pest>,
c<'pest>,
),
}
struct assign<'pest>(
#[pest_ast(outer)] Span<'pest>,
enum _1 {
struct _1(a<'pest>),
struct _2(b<'pest>),
struct _3(c<'pest>),
},
number<'pest>,
);
struct assigns<'pest>(
#[pest_ast(outer)] Span<'pest>,
Vec<struct _1(assign<'pest>)>,
assign<'pest>,
);
Once I knew I was on the right track, I figured out the error in my code, completely unrelated to the question asked. It was that Identifier rule should use outer span instead of inner.
#[derive(Debug, FromPest)]
#[pest_ast(rule(Rule::identifier))]
pub struct Identifier {
#[pest_ast(outer(with(span_into_str), with(String::from)))]
pub value: String
}
The most useful debugging tool was to print the raw syntax tree the Identifier rule produced:
#[test]
fn test_identifier() {
let source = "foobar";
let mut parse_tree = parser::Parser::parse(parser::Rule::identifier, source).unwrap();
println!("parse tree = {:#?}", parse_tree);
let syntax_tree: Identifier = Identifier::from_pest(&mut parse_tree).expect("infallible");
println!("syntax tree = {:#?}", syntax_tree);
assert_eq!(syntax_tree.value, "foobar".to_string());
}
I also had to remove struct inside an enum to have Formula compile:
#[derive(Debug, FromPest)]
#[pest_ast(rule(Rule::formula))]
pub enum Formula {
Assignment {
lvalue: Identifier,
// a: AssignmentOp,
rvalue: IntLiteral,
},
OrTest {
or_test: IntLiteral,
}
}
The answers to the questions:
Does pest-ast even support deriving enum variants with fields?
Yes, example above.
Can I match enum variant to a parenthesed () group of terminals?
No answer yet. This hasn't worked for me.
Can I skip some terminals? I don't exactly need to know := was used if I get an AssignmentExpression { lvalue, rvalue } in the end.
pest-ast works with the tree produced by pest. In order to skip something, make it a silent rule in the source grammar.
I am new to Go (coming from python) and I am having a bit of a hard time here. I am trying to allow any type of slice into my struct/func and it just contains a count of the length of that slice.
import "go/types"
type Response struct {
Count int `json:"count"`
Results []types.Struct `json:"results`
}
func NewResponse(results []types.Struct) (r *Response) {
r.Count = len(results)
r.Results = results
return
}
you can use interface{} as any type.
type Response struct {
Count int `json:"count"`
Results []interface{} `json:"results`
}
UPDATE
len(rsp.results) should work.
http://play.golang.org/p/RA2zVzWl2q
Arbitrary types are totally legit in Go. In your case, it might be appropriate to use []interface{} as the type of Results. When ever the types need to be known, use type switch.
package main
import (
"fmt"
)
type Response struct {
Count int `json:"count"`
Results []interface{} `json:"results`
}
func NewResponse(results []interface{}) (r *Response) {
r.Count = len(results)
r.Results = results
return
}
func AssertResultType(results []interface{}) {
for _, v := range results {
switch v := v.(type) {
default:
fmt.Printf("unexpected type %T\n", v) //t has unexpected type
case bool:
fmt.Printf("boolean %t\n", v) // t has type bool
case int:
fmt.Printf("integer %d\n", v) // t has type int
case string:
fmt.Printf("string %q\n", v) // t has type string
}
}
}
func main() {
args := []interface{}{1, "hello", true, "foo", 21}
r := NewResponse(args)
AssertResultType(r.Results)
}
In case of JSON, *json.RawMessage can be marshaled to type []byte
type Response struct {
Count int `json:"count"`
Results *json.RawMessage `json:"results`
}
Assuming, that I have a Graph struct, like so:
type Graph struct {
nodes []int
adjList map[int][]int
}
// some methods on the struct
// constructor
func New() *Graph {
g := new(Graph)
g.adjList = make(map[int][]int)
return g
}
Now, I create a new instance of that struct, with: aGraph := New().
How do I access the fields of this particular instance of the Graph struct (aGraph)?
In other words, how do I access aGraph's version of the nodes array, (from within another top-level function for example)?
Any help is extremely appreciated!
Here is one example:
package main
import (
"fmt"
)
// example struct
type Graph struct {
nodes []int
adjList map[int][]int
}
func New() *Graph {
g := new(Graph)
g.adjList = make(map[int][]int)
return g
}
func main() {
aGraph := New()
aGraph.nodes = []int {1,2,3}
aGraph.adjList[0] = []int{1990,1991,1992}
aGraph.adjList[1] = []int{1890,1891,1892}
aGraph.adjList[2] = []int{1890,1891,1892}
fmt.Println(aGraph)
}
Output:&{[1 2 3 4 5] map[0:[1990 1991 1992] 1:[1890 1891 1892] 2:[1790 1791 1792]]}
I see some Rust code that looks like this:
#![feature(default_type_params)]
After a lot of Googling, I get nothing about it. What is this? When should I use it?
It is enabling feature called default type parameters, but you already know that, so let me show you an example:
#![feature(default_type_params)]
struct Foo<A=(int, char)> { // default type parameter here!
a: A
}
fn default_foo(x: Foo) {
let (_i, _c): (int, char) = x.a;
}
fn main() {
default_foo(Foo { a: (1, 'a') })
}
Without default type parameters, you would need to explicitly set parameters:
struct Foo<A> {
a: A
}
fn default_foo(x: Foo<(int, char>)) {
let (_i, _c): (int, char) = x.a;
}
fn main() {
default_foo(Foo { a: (1, 'a') })
}
Example stolen from here: https://github.com/rust-lang/rust/pull/11217
In light of the fact that golang does not support unions, what is the best way to achieve:
type foo struct {
words []string
nums []int
}
such that only words or nums can be used at once. One thing I've tried is:
type foo struct {
values []interface{}
}
but I prefer something that restricts the types to the two mentioned or something with pointers.
Use a foo package to hide the implementation. For example,
package foo
const (
typeWords = iota + 1
typeNums
)
type Foo struct {
fooType byte
words []string
nums []int
}
func NewWords(words []string) *Foo {
return &Foo{fooType: typeWords, words: words}
}
func NewNums(nums []int) *Foo {
return &Foo{fooType: typeNums, nums: nums}
}
func (f *Foo) Words() []string {
if f.fooType != typeWords {
return nil
}
return f.words
}
func (f *Foo) Nums() []int {
if f.fooType != typeNums {
return nil
}
return f.nums
}
ADDENDUM:
Since we are hiding the implementation of package foo, we can implement it another way. For example, we could adopt twinj's suggestion and use an interface. To ensure some degree of generality, let's add another []string type Phrases. The value types are used to distinguish between the two []string types.
package foo
type (
valueWords []string
valuePhrases []string
valueNums []int
)
type Foo struct {
value interface{}
}
func NewWords(words []string) *Foo {
return &Foo{value: valueWords(words)}
}
func (f *Foo) Words() []string {
value, ok := f.value.(valueWords)
if !ok {
return nil
}
return value
}
func NewPhrases(phrases []string) *Foo {
return &Foo{value: valuePhrases(phrases)}
}
func (f *Foo) Phrases() []string {
value, ok := f.value.(valuePhrases)
if !ok {
return nil
}
return value
}
func NewNums(nums []int) *Foo {
return &Foo{value: valueNums(nums)}
}
func (f *Foo) Nums() []int {
value, ok := f.value.(valueNums)
if !ok {
return nil
}
return value
}
Another option would be to use an interface and type assertion.
type Foo struct {
values interface{}
}
func (o *Foo) Words() []string {
if v, ok := o.values.([]string); ok {
return v
}
return nil
}
func (o *Foo) Nums() []int {
if v, ok := o.values.([]int); ok {
return v
}
return nil
}
Check out the Go playground example: GoPlay
Note:
Foo cannot be an interface type (type Foo []interface{} or type Foo interface{}) but can be a struct which contains an interface type.
You also cannot assert []interface{} to another slice type as an []interface{} is a type in its own right. See here