I tried to learn Go but I frequently feel frustrating because some basic features that other languages has seems not working in Go. So basically, I would like to use struct type that is
define in other file. I was able to use functions except struct type. In main.go,
package main
import (
"list"
)
func main() {
lst := list.NewList(false)
lst.Insert(5)
lst.Insert(7)
lst.InsertAt(2, 1)
lst.PrintList()
}
This works perfectly (and all other functions) as I expect (list is in $GOPATH). In package list, I defined struct as follow:
type LinkedList struct {
head *node
size int
isFixed bool
}
I wanted to use this struct in other struct, so I attempted to do something like this,
type SomeType struct {
lst *LinkedList
}
But unfortunately, I got error that the type LinkedList is not defined. How can I use a struct that is defined in other package?
The LinkedList type is in the list namespace, so change your usage of the type to:
type SomeType struct {
lst *list.LinkedList
}
Related
Consider the following contrived example:
mod Parent {
fn my_fn() {
struct MyStruct;
mod Inner {
use super::MyStruct; //Error: unresolved import `super::MyStruct`. No `MyStruct` in `Parent`
}
}
}
How can I import MyStruct here from the inner module?
Motivation
While the above is code that you'll never write manually, it is code that is useful to generate. A real-world use-case would be a derive-macro. Let's say I want this:
#[derive(Derivative)]
struct MyStruct;
Now it's useful to isolate the generated code in its own module, to isolate the generated code from the source code (e.g. to avoid naming collisions, leaking of use declarations, etc.). So I want the generated code to be something like this:
mod _Derivative_MyStruct {
use super::MyStruct;
impl Derivative for MyStruct { }
}
However, the example above fails if the struct is defined in a function, due to the problem at the top. e.g. this won't work:
fn my_fn() {
#[derive(Derivative)];
struct MyStruct;
}
as it expands into:
fn my_fn() {
#[derive(Derivative)];
struct MyStruct;
mod _Derivative_MyStruct {
use super::MyStruct; // error
impl Derivative for MyStruct {}
}
}
This is especially troublesome for doctests, as these are implicitly wrapped in a function. E.g. this will give the unresolved import problem:
/// Some interesting documentation
/// ```
/// #[derive(Derivative)]
/// struct MyStruct;
/// ```
Without the ability to refer to the outer scope, I either need to give up isolation, or require wrapping in modules at the call site. I'd like to avoid this.
This is issue #79260. I don't think there is a solution.
However, you can define the nested items inside an unnamed const (const _: () = { /* code */ };) instead of a module. This prevents name collisions and is the idiomatic thing to do in macros that need to define names. Do note however that this does not have a way to refer to items inside the const from outside it.
This question already has an answer here:
Any way to get associated type from struct?
(1 answer)
Closed 10 months ago.
So I'm making a little tictactoe to learn Rust. I define a Board which is a struct containing a 3 by 3 array called "tiles".
pub struct Board {
pub tiles: [[Option<Players>; 3]; 3],
}
Then, I try to create a method that uses the element "tiles" as a parameter
impl Board {
pub fn print_board (board: Board::tiles) {
}
However, Rust gets all offended and tells me this.
ambiguous associated typerustcE0223 game.rs(10, 32): use fully-qualified syntax: "<Board as Trait>::tiles"
First of all, I have no idea what this mean, but then I try to do as it says:
impl Board {
pub fn print_board (board: <Board as Trait>::tiles) {
}
it gives me squiggles under "Trait" where it says
failed to resolve: use of undeclared type "Trait" use of undeclared type "Trait"
Rust, o Rust what ever am I supposed to do?
Board::tiles doesn't make syntactic sense. If board is a value of type Board, then board.tiles is a data member of the struct. Neither Board::tiles nor board.tiles is a type so you can't use it for defining the type of an argument.
You can either take the type of the data member explicitly, like this: pub fn print_board(board: [[Option<Players>; 3]; 3]).
Or if you don't want to write out that type again and again you can use a type alias like this
pub type TileArray = [[Option<Players>; 3]; 3];
pub struct Board {
pub tiles: TileArray,
}
impl Board {
pub fn print_board(board: TileArray) {
// ...
}
}
The error message is confusing to you because you're specifying a type of a function parameter, but attempting to use the name of a value to do that. Your syntax is just completely invalid. The syntax SomeType::Something can make some sense, where Something is an associated type of some trait implemented by SomeType. This is the compiler's best guess of making sense of the syntax you gave it, so it's trying to correct you based on that. That syntax still wouldn't be correct, since you'd need the fully-qualified syntax indicated by the error message.
Is there some compiler built-in functionality going on, or would it be possible to implement your own enum with its variants globally accessible with rust code alone? If yes, how?
Edit: Sorry if I wasn't clear. My Question was about Some and None, not Option. For example:
enum MyOption<T> {
MySome(T),
MyNone,
}
impl<T> MyOption<T> {
fn is_some(&self) -> bool {
match self {
Self::MySome(_) => true,
Self::MyNone => false,
}
}
}
Even from "inside", I have to tell the compiler to find them in Self. So is there a way to do it like Option and have my MySome and MyNone linked to MyOption from anywhere I write them?
Rust has a module called the "prelude", accessible at std::prelude, and all of its members are imported into every module by default.
If you define your own names that shadow names in the prelude, your names take precedence. This is common for types like Result, in the following pattern:
type Result<T> = std::result::Result<T, MyCustomError>;
Whenever this is in scope, it takes precedence over the Result type included from the prelude.
Note that some things in the prelude are treated in special ways by the compiler (for example Box has built-in functionality) but you can still override the name.
You can import enum variants like regular items. For example, you can write:
use MyOption::*;
fn handle_my_option(o: MyOption) {
match o {
MyOk(foo) => {},
MyNone => {},
}
}
However, you can't have these automatically imported like the ones in the prelude (you can't add anything the prelude essentially).
If you have lots of these types, you can bundle them into a file and glob import them:
// src/my_prelude.rs
pub use crate::my_option::MyOption; // reexport the enum itself
pub use crate::my_option::MyOption::*; // reexport the individual variants
// any other things you want everywhere
// src/foo.rs
use crate::my_prelude::*;
fn foo() -> MyOption<()> {
if bar() {
MySome(()),
} else {
MyNone
}
}
Rust has a prelude module which is implicitly included in every file.
This module reexports commonly used things such as Option and its variants, but also types such as String, traits such as Clone, and functions such as drop.
Rust allows declaring a structure inside a function but it doesn't allow assigning a variable with it in a simple way.
fn f1() -> (something) {
struct mystruct {
x: i32,
}
let s = mystruct;
s
}
fn f2(s: something) {
let obj = s { x: 5 };
println!(obj.x);
}
fn main() {
let s = f1();
f2(s);
}
Is it possible to store a struct into a variable in a different way? How do I write the struct type correctly? In my project, I want to declare a struct inside a function and create instances inside of another one.
How to store a struct into a variable in Rust?
Rust is a statically typed language, and as such it is not possible to store a type into a variable, then use this variable to construct an instance of the type.
This is the reason you are not able to express what the type of s is; there is simply no vocabulary in the language for this.
Depending on what you want to do, you may wish to look into:
Generics: fn f2<T: Default>() would allow creating an instance of any type T implementing the Default trait.
Run-time polymorphism: A factory function FnOnce(i32) -> Box<Trait> could produce an instance of any type implementing Trait from a i32.
Consider the following implementation:
pub struct BST {
root: Link,
}
type Link = Option<Box<Node>>;
struct Node {
left: Link,
elem: i32,
right: Link,
}
impl Link { /* misc */ }
impl BST { /* misc */ }
I keep getting the error:
cannot define inherent impl for a type outside of the crate where the type is defined; define and implement a trait or new type instead
I was able to find others had this same issue back in February, but there was seemingly no solution at the time.
Is there any fix or another way for me to implement my Link typedef in Rust?
Is there any fix
Not really. A type alias (type Foo = Bar) does not create a new type. All it does is create a different name that refers to the existing type.
In Rust, you are not allowed to implement inherent methods for a type that comes from another crate.
another way for me to implement
The normal solution is to create a brand new type. In fact, it goes by the name newtype!
struct Link(Option<Box<Node>>);
impl Link {
// methods all up in here
}
There's no runtime disadvantage to this - both versions will take the exact same amount of space. Additionally, you won't accidentally expose any methods you didn't mean to. For example, do you really want clients of your code to be able to call Option::take?
Another solution is to create your own trait, and then implement it for your type. From the callers point of view, it looks basically the same:
type Link = Option<Box<Node>>;
trait LinkMethods {
fn cool_method(&self);
}
impl LinkMethods for Link {
fn cool_method(&self) {
// ...
}
}
The annoyance here is that the trait LinkMethods has to be in scope to call these methods. You also cannot implement a trait you don't own for a type you don't own.
See also:
How do I implement a trait I don't own for a type I don't own?