How can I define two-way tree structure in Rust? [duplicate] - data-structures

This question already has answers here:
How do I express mutually recursive data structures in safe Rust?
(4 answers)
How to model complex recursive data structures (graphs)?
(1 answer)
Closed 4 years ago.
I mean a tree where every node has multiple children and every child refers back to its parent.
I've got this far:
pub struct Post {
content: String,
links: Vec<Post>,
parent: Box<Post>,
}
impl Post {
pub fn new() -> Post {
Post {
content: String::new(),
links: Vec::new(),
parent: Box::new(......),
}
}
}
What do I put in the place of the dots?

Related

How to create abstract structure implementations [duplicate]

This question already has answers here:
Implementing an interface with a wider method signature
(3 answers)
How to implement interface method with return type is an interface in Golang
(1 answer)
Closed 4 months ago.
The community reviewed whether to reopen this question 4 months ago and left it closed:
Original close reason(s) were not resolved
I've got a slice of steps []*Steps where each step has a type and a custom payload depending on it:
type Step struct {
ID string
Name string
Type StepType // Enum: StepA | StepB
Action StepAction // interface implemented by either ActionStepA | ActionStepB
// Other common fields
}
// StepAction is an interface implemented by either ActionStepA | ActionStepB
type StepAction interface {}
type ActionStepA struct {FieldA string} // Fields specific to step A
type ActionStepB struct {FieldB string} // Fields specific to step B
Depending on the Type, the Action will be a different struct: either ActionStepA or ActionStepB which just hold their own step-specific fields.
To Execute these steps, I have a StepExecutor interface:
type StepExecutor interface {
Execute(StepAction) error
}
Ideally, I'd like to have a StepExecutor implementation per StepType which contains the business logic and knows how to execute its type. E.g. have StepAExecutor() which executes ActionStepA and StepBExecutor which executes ActionStepB.
How can I achieve something like this in GOlang? I guess what I need is a concept similar to Abstract Classes?
for _, step := range steps {
executor := getExecutorForStep(step) // returns a StepExecutor type
executor.Execute(step.Action)
}
// ERROR HERE:
fun getExecutorForStep(step *Step) StepExecutor {
switch step.Type {
case StepA: return &StepAExecutor{}
case StepB: return &StepBExecutor{}
}
}
I tried the above but I'm getting errors as the StepExecutor "implementations" are not actually implementations as they have mismatched method signatures:
StepExecutor expects StepAction for the Execute method
StepAExecutor expects ActionStepA for the Execute method
StepBExecutor expects ActionStepB for the Execute method
If go doesn't allow for such a case, I'm happy to redo the architecture with a proper more common one. Let me know if you have any suggestions. I understand that in golang, methods signatures must match literally - I'm just unsure how I can properly structure this problem. I might be in need of a re-architecture.

How to omit map from JSON marshalling only when it's empty? [duplicate]

This question already has answers here:
How to not marshal an empty struct into JSON with Go?
(4 answers)
Closed 10 months ago.
I need to return an empty json {} when the map is not nil, but it's empty. When the map is nil I need it to be omitted.
How could I go about doing this?
type ChildMap map[string]string
type Parent struct {
ID int64
T ChildMap `json:"t,omitempty"`
}
Here's a playground that explains what I'm trying to do quite well:
https://go.dev/play/p/hahseo9nyh3
In 1st case it needs to be omitted (this works), 2nd case I need it returned as {} (doesn't work), 3rd case needs to be displayed (also works)
I had the same requirement long ago and this was the only solution.
Set your Slice on Bar and even with no elements it will render []
A more interesting solution need a specific Unmarshal code (perhaps is more readable than this)
type Foo struct {
Bar *interface{} `json:"bar,omitempty"`
Baz *interface{} `json:"baz,omitempty"`
}

Is there a graceful approach to deserializing Go interface types? [duplicate]

This question already has answers here:
Can I unmarshal JSON into implementers of an Interface?
(2 answers)
Closed 11 months ago.
The community reviewed whether to reopen this question 11 months ago and left it closed:
Original close reason(s) were not resolved
Given the following:
type Foo struct {
Td ThingDoer
// ... other stuff
}
type ThingDoer interface {
doThing()
}
type doerA struct {
AGuts string
}
func (a doerA) doThing() {}
type doerB struct {
BGuts string
}
func (b doerB) doThing() {}
is there a preferred serialization / deserialization strategy for Foo?
Attaching, eg, a MarshalJSON function onto doerA and doerB satisfies the serialization, but then Foo.UnmarshalJSON is effectively stuck: it can't know in advance whether the supplied JSON is of doerA or doerB type.
Edit: The linked "similar" question addresses the specific non-solution example outlined in this question. This question is asking about the existence of a graceful solution.
Imagine you have an structure Foo with one or more fields using interface types.
Lets say you have an interface Bar with two possible structures: Baz and Bam.
You can define auxiliary type (FooConf), without any interface. Only concrete types.
This structure may have a method Build() Foo that will choose the right type on each case.
To be possible define what is the concrete type you can define a signature. For instance an extra field “type” (baz or bam).
You just need to be sure about each type can marshal/unmarshal with consistency.

Appending to a slice in a struct in a map [duplicate]

This question already has answers here:
Append values to array inside of map golang
(2 answers)
Append a slice from a map value does not affect the map
(3 answers)
Need help understanding `map[String]type` behaviour in Go
(1 answer)
Cannot assign to struct field in a map
(5 answers)
Closed 1 year ago.
I'm trying to append to a slice within a map:
type MyOuterStruct struct{
name string
inners map[string]MyInnerStruct
}
type MyInnerStruct struct{
name string
list []int
}
func main() {
ms := MyOuterStruct{
name: "outer",
inners: map[string]MyInnerStruct{
"a": {name: "inner"},
},
}
ms.inners["a"].list = append(ms.inners["a"].list, 4, 5, 6)
fmt.Println(ms.inners["a"].list)
//cannot assign to struct field ms.inners["a"].list in map
}
I know the issue is I'm assigning to an "unaddressable" field, but I'm not sure how to structure this properly.
I've tried the following
myCurrentList := ms.inners["a"].list
myCurrentList = append(myCurrentList, 4, 5, 6)
ms.inners["a"].list = myCurrentList
But this wasn't correct either.
How should I structure the MyInnerStruct so that I can have access to a dynamic slice list than I can append to?
The problem is that ms.inners["a"] returns a copy of the value stored for that key. So when you modify a member of that copy, it is not reflected on the copy stored in the map.
The easiest solution is to define the map as:
map[string]*MyInnerStruct
This way, ms.inners["a"] returns a pointer to the value stored in the map. Another solution is:
x:=ms.inners["a"]
x.list = myCurrentList
ms.inners["a"]=x
This copies the struct stored in the map to x, modifies it, and copies it back.

Why is it impossible to instantiate a data structure due to "overflow while adding drop-check rules"? [duplicate]

This question already has an answer here:
"overflow while adding drop-check rules" while implementing a fingertree
(1 answer)
Closed 4 years ago.
Here is a data structure I can write down and which is accepted by the Rust compiler:
pub struct Pair<S, T>(S, T);
pub enum List<T> {
Nil,
Cons(T, Box<List<Pair<i32, T>>>),
}
However, I cannot write
let x: List<i32> = List::Nil;
playground
as Rust will complain about an "overflow while adding drop-check rules".
Why shouldn't it be possible to instantiate List::Nil?
It should be noted that the following works:
pub struct Pair<S, T>(S, T);
pub enum List<T> {
Nil,
Cons(T, Box<List<T>>),
}
fn main() {
let x: List<i32> = List::Nil;
}
playground
When the type hasn't been instantiated, the compiler is mostly worried about the size of the type being constant and known at compile-time so it can be placed on the stack. The Rust compiler will complain if the type is infinite, and quite often a Box will fix that by creating a level of indirection to a child node, which is also of known size because it boxes its own child too.
This won't work for your type though.
When you instantiate List<T>, the type of the second argument of the Cons variant is:
Box<List<Pair<i32, T>>>
Notice that the inner List has a type argument Pair<i32, T>, not T.
That inner list also has a Cons, whose second argument has type:
Box<List<Pair<i32, Pair<i32, T>>>>
Which has a Cons, whose second argument has type:
Box<List<Pair<i32, Pair<i32, Pair<i32, T>>>>>
And so on.
Now this doesn't exactly explain why you can't use this type. The size of the type will increase linearly with how deeply it is within the List structure. When the list is short (or empty) it doesn't reference any complex types.
Based on the error text, the reason for the overflow is related to drop-checking. The compiler is checking that the type is dropped correctly, and if it comes across another type in the process it will check if that type is dropped correctly too. The problem is that each successive Cons contains a completely new type, which gets bigger the deeper you go, and the compiler has to check if each of these will be dropped correctly. The process will never end.

Resources