I have a deeply nested struct which contains two slices, as seen below:
package main
import "fmt"
type bar struct {
v1 []int
v2 []int
}
type foo struct{ bar bar }
type tar struct{ foo foo }
func main() {
f := &tar{foo: foo{bar: bar{v1: [2], v2: [3]}}}
fmt.Printf("Hello, playground %s", f)
}
How do I initialize the two slices? Or how do I get this code working?
Here is the Golang Play for it: http://play.golang.org/p/zLutROI4YH.
It's possible with []int{1,2,3} notation, example (solves your problem):
&tar{foo: foo{bar: bar{v1: []int{2}, v2: []int{2}}}}
P.S. I strongly advise you to read The Go Programming Language Specification and FAQ section.
v1 and v2 are slices. The way you initialize those is with make([]int, YOUR_INITIAL_SIZE) instead of [2] and [3].
Related
I can define an associated function foo for an array like this:
pub trait T {
fn foo();
}
impl<X> T for [X; 2] {
fn foo() { panic!("Whatever") }
}
But how do I now call this function? I noticed that syntax like [usize;2]::foo() is invalid.
You can use the fully qualifidied syntax <Type as Trait>::function(). Here is your example:
pub trait Trait {
fn foo();
}
impl<X> Trait for [X; 2] {
fn foo() {
panic!("Whatever");
}
}
fn main() {
<[usize; 2] as Trait>::foo();
}
See it on the playground.
Short answer: You need to use angle brackets: <[usize; 2]>::foo().
Long answer:
If you'll look in the reference, you'll see the syntax:
CallExpression :
Expression ( CallParams? )
Inside Expression, you have PathExpression. There are two kinds of PathExpression s: PathInExpression and QualifiedPathInExpression. PathInExpression is a simple path of the form a::b::c::<generics>::d::<generics> etc.. This is what you use when you type e.g. String::new() or String::from("abc").
QualifiedPathInExpression, on the other hand, has the form QualifiedPathType (:: PathExprSegment)+, or in simple words, QualifiedPathType followed by one or more instances of two colons then PathExprSegement. PathExprSegment is defined as a name (identifier) optionally followed by two colons and generics: i.e., foo or foo::<a, b, c>.
And what is QualifiedPathType ? It is defined as < Type (as TypePath)? >, or a type enclosed in angle brackets, optionally followed by as and a TypePath, which is very similar to PathExpression with some differences.
Type is any Rust type syntax: a path (e.g. a::b<generics> or a::b::<generics>, trait objects (dyn Trait), impl Trait, tuples ((T1, T2, T3, ...)), arrays ([T; N]), slices ([T]), references (&T or &mut T, potentially with a lifetime), and more.
All of this means that when you call a method, unless the method type is a simple path - that is, has the form a::b::c, potentially with generics, you must enclose the type in angle brackets - <Type>::method(). That includes arrays, slices, references, tuples, function pointers (fn(Args) -> Ret), and more. [usize; 2]::foo() is not a valid Rust syntax, only <[usize; 2]>::foo() is.
Of course, there is another reason to use this form: UFCS (Universal Function Call Syntax). When you want to specify the trait (usually for disambiguition), you must use the form <Type as Trait>::method() (this is the "(as TypePath)?" we saw).
In Go, a memory-efficient way of storing values you want to retrieve by key that has no associated value is to use a map of empty structs keyed with the data you want to store. For instance, if you have a list of strings you want to check have been previously seen by your program, you could do something like this:
var seen = map[string]struct{}{}
for _, str := range strings {
if _, ok := seen[str]; ok {
// do something
} else {
seen[str] = struct{}{}
}
}
Is there a Rust equivalent to this? I am aware that Rust doesn't have anonymous structs like Go, so what Rust type would use the least amount of memory in a map like the above example? Or is there a different, more idiomatic approach?
A HashSet is defined as a HashMap with the unit tuple as the value:
pub struct HashSet<T, S = RandomState> {
map: HashMap<T, (), S>,
}
The same is true for BTreeSet / BTreeMap:
pub struct BTreeSet<T> {
map: BTreeMap<T, ()>,
}
what Rust type would use the least amount of memory
Any type with only one possible value uses zero bytes. () is an easy-to-type one.
See also:
What does an empty set of parentheses mean when used in a generic type declaration?
I'm using a newtype, wrapping an array of integers:
struct Foo([int, ..5]);
Since, apparently, I cannot simply do this:
let foo = Foo([1,2,3,4,5]);
let bar = foo[2];
How exacty do I access the wrapped array?
There are one-and-a-half (soon to be two) ways:
#![feature(tuple_indexing)]
struct Foo([int, ..5]);
fn main() {
let foo = Foo([1,2,3,4,5]);
let Foo([_, foo_1, ..]) = foo;
let foo_3 = foo.0[3];
println!("[_, {}, _, {}, _]", foo_1, foo_3);
}
Specifically, tuple_indexing is likely to be un-gated soon, so you won't need the feature attribute to use it.
Basically, Foo is a tuple struct; that is, it behaves more or less just like a tuple that happens to have a name.
Running this code
extern crate debug;
fn main() {
let x = &5i;
println!("{:?}", x);
}
prints &5. How is this data type called? I would have expected to see something like a pointer to int.
rustc 0.12.0-pre-nightly (09abbbdaf 2014-09-11 00:05:41 +0000)
The type of &5i is &int, which is called a reference to int, or maybe a shared reference, or an immutable reference.
Incidentally, "{:?}" yields a representation of the value based on reflection, not a representation of the type. The only way I'm aware of to get the name of a type is to involve it in a type error.
fn main() {
let i = &5i;
let () = i;
}
but even then you only get it to mention &int and &-ptr and not a politically correct, up-to-date in common community parlance, prose description.
I came across some output I don't understand using Vec::get. Here's the code:
fn main() {
let command = [('G', 'H'), ('H', '5')];
for i in 0..3 {
print!(" {} ", i);
println!("{:?}", command.get(i));
}
}
the output is
0 Some(('G', 'H'))
1 Some(('H', '5'))
2 None
I've dabbled in Haskell before, and by that I mean looked at a tutorial site for 10 minutes and ran back to C++, but I remember reading something about Some and None for Haskell. I was surprised to see this here in Rust. Could someone explain why .get() returns Some or None?
The signature of get (for slices, not Vec, since you're using an array/slice) is
fn get(&self, index: usize) -> Option<&T>
That is, it returns an Option, which is an enum defined like
pub enum Option<T> {
None,
Some(T),
}
None and Some are the variants of the enum, that is, a value with type Option<T> can either be a None, or it can be a Some containing a value of type T. You can create the Option enum using the variants as well:
let foo = Some(42);
let bar = None;
This is the same as the core data Maybe a = Nothing | Just a type in Haskell; both represent an optional value, it's either there (Some/Just), or it's not (None/Nothing).
These types are often used to represent failure when there's only one possibility for why something failed, for example, .get uses Option to give type-safe bounds-checked array access: it returns None (i.e. no data) when the index is out of bounds, otherwise it returns a Some containing the requested pointer.
See also:
Why don't Option's Some and None variants need to be qualified?
What is the difference between Some and Option in Rust?
Think of Some and None as the canonical "safe" way of working around the fact that the Rust language does not support "safe" use of NULL pointers. Since the length of your Vec is 3, and you have only specified two pairs, the third pair is effectively NULL; instead of returning NULL, it returns None.
Rust provides safety guarantees by forcing us at compile-time, via Some / None, to always deal with the possibility of None being returned.
command is not a vector (type Vec<T>), it is a fixed-size array (type [(char, char); 2] in your case), and arrays are automatically borrowed into slices (views into arrays), hence you can use all methods defined on slices, including get:
Returns the element of a slice at the given index, or None if the index is out of bounds.
The behavior is pretty obvious: when given index is valid, it returns Some with the element under that index, otherwise it returns None.
There is another way to access elements in a slice - the indexing operator, which should be familiar to you:
let nums = [1, 2, 3];
let x = nums[1];
It returns the element of the slice directly, but it will fail the current task if the index is out of bounds:
fn main() {
let x = [1, 2];
for i in 0..3 {
println!("{}", x[i]);
}
}
This program fails:
% ./main2
1
2
task '<main>' failed at 'index out of bounds: the len is 2 but the index is 2', main2.rs:4
The get() method is needed for convenience; it saves you from checking in advance if the given index is valid.
If you don't know what Some and None really are and why they are needed in general, you should read the official tutorial, it explains it because it is very basic concept.
Option enum has 2 variants.
1- None is used to indicate failure or no value
2- Some which is tuple-struct that wraps the value
If you need to write this structure in OOB, for example in typescript, you would write like this. This would make it easier to visualize the situation
Define Option interface as derived class
interface Option<T = any> {
// pass all the methods here
// unwrap is used to access the wrapped value
unwrap(): T;
}
write Some class which inherits from Option
Some class returns a value
class Some<T> implements Option<T> {
private value: T;
constructor(v: T) {
this.value = v;
}
unwrap(): T {
return this.value
}}
Write None class which also inherits from Option
None class returns null
class None<T> implements Option<T> {
// you do not need constructor here
unwrap(): T {
return null as T;
}
}
The other answers discussing the return type for get() being option enum are accurate, but I think what is helpful is how to remove the some from the prints. To do that a quick way is to just call the unwrap on the option, although this is not production recommended. For a discussion on option take a look at the rust book here.
Updated with unwrap code in playground (below)
fn main() {
let command = [('G', 'H'), ('H', '5')];
for i in 0..3 {
print!(" {} ", i);
println!("{:?}", command.get(i).unwrap());
}
}