I'm trying to implement a toy search algorithm and need to maintain a set of explored states. A state is a struct:
type VWState struct {
botLocation VWCoords
dirtLocations []VWCoords
}
My first thought was that a simple Set could be implemented using a map[VWState]bool, but I can't seem to figure out a way to make it work. If I try to use a VWState as a key to a map, I get the following panic:
Panic: runtime error: hash of unhashable type vw.VWState (PC=0x40EB0D)
Is there a way to make this work? Can I implement a custom hashing function for the struct, or should I be looking at some other ways to implement this?
Any help would be greatly appreciated.
You can use a pointer to your struct as a map key:
map[*VWState]bool
If you want to be able to compare equivalent structs, you can create a method to output a key for the map. String() would be convenient, since you could also use it to print your struct, or tie in a hash function and output something shorter, even an int.
Something as simple as this may suffice, though you could make the output shorter if you like (being careful not to recursively call String() in your format line):
func (s VWState) String() string {
return fmt.Sprintf("%#v", s)
}
func main() {
m := make(map[string]bool)
s := VWState{}
m[s.String()] = true
}
If there is a sensible maximum length for dirtLocations then you could use an array instead of a slice. Arrays are hashable (provided the element is hashable).
type VWState struct {
botLocation VWCoords
dirtLocations [4]VWCoords
}
You'll then need to either add a count of the number of valid dirtLocations or detect the zero value of VWCoords to work out how many slots in dirtLocations are valid.
Related
Code like this:
pub fn sample_from_categorical_logits(prob_logits: Tensor) -> (Tensor, Tensor) {
let prob_obj = match prob_logits.size().len() {
3 => Categorical::from_logits(prob_logits),
2 => Categorical::from_logits(prob_logits.unsqueeze(1)),
_ => panic!("illegal..."),
};
(prob_obj.sample(&[]), (*prob_obj.probs()).copy())//TODO: can copy be avoided?
}
I can get an immutable reference on a field of object prob_obj through prob_obj.prob(). Now I need to return the value of it, because I need to read(only) this value for some calculation, and return this value and calculated value further.
Tensor is a 3rd struct doesn't implement Copy trait.
I know I can't return a reference of a local object. But in this case, since I no longer need the whole prob_obj object, I wonder if there is a more efficient way other than copying the field, like move in C++.
I googled, found something like Cow, Mem::take, and UnSafe, but they seem to be not the use case here.
I wonder if there is a more efficient way other than copying the field, like move in C++.
Well yes, moving. But moving requires having ownership of the object, meaning you need a version of probs() which consumes the object in order to return its bits.
Or one which returns a mutable reference in order to use mem::take or mem::swap.
Like you would in C++, really, it's not like you can just move stuff out of a const reference (at best that's going to perform a copy).
Introduction
In my rust library, I have "Shape" objects (called Types in rust). Each shape object has attributes.
Some of those attributes like "color", "name" etc are string values, some of these attributes are integers, and some bool.
The way attributes module is implemented is such that for each attribute there is a different getter and setter function.
An example
pub struct Attributes{
//--strings
bounding_rectangle_color:String,
shadow_color:String,
name:String,
color:String,
...
pub fn set_bounding_rectangle_color(&mut self,v:String){
self.bounding_rectangle_color = v;
}
pub fn get_bounding_rectangle_color(&self)->String{
String::from(&self.bounding_rectangle_color)
}
This is (in my humble opinion) the correct way of doing it since each attribute has its own get and set function these functions will soon have some logic specific to that attribute.
The Challange
Though having separate getters and setters for each attribute is great however the same API can not be exposed to the user being confusing.
the user should have something like
let some_result:???? = my_shape.get_attr(attribute_name);
The problem is that the get_attr function has to return either a bool or string or int etc (but it can not return 2 different types).
Please keep in mind the problem is getting get_attr and not set_attr since in set_attr we can just take in a string and change it internally to whatever.
I want to wrap the attributes module in a wrapper such that internally attributes can use separate getter and setter for each value whereas from the top the wrapper should be able to communicate with attribute module using a simple API like
let value = shape.get_attr(attribute_name);
What I have tried so far
Tuple Structs
I tried to use a tuple struct in place of each attribute inside this tuple there will be the data type of this attribute (ie either bool, string, etc).
BUT the problem was the same that at some point that tuple had to return a value and that value type can not be unknown at compile time
Returning Functions
Once again when we return a function we have to tell the return type of that function as well.
Summary
Rust does not have union types, am I just trying to re-implement union types??? am I going in the wrong direction .. please help
The easiest way to return multiple types is to return an enum. For example, you could define an enum as follows (with the exact types/names up to you):
enum Return {
Int(usize),
String(String),
Bool(bool),
}
From here, you could have a function like so:
fn do_something(num: usize) -> Return {
match num {
1 => Return::Int(1),
2 => Return::String(String::from("two")),
3 => Return::Bool(true),
_ => unreachable!(),
}
}
Now, depending on the input parameter, it will return different types. To actually do something with the types, you could do something like:
if let Return::Int(int) = do_something(1) {
// do something with the int
}
However, it might be best to try and find another way to solve your problem - having a single getter/setter is not really better than having individual getters/setters, and could lead to your code being confusing.
Scala's value classes provide a way to use the type system without allocating runtime objects (structs in case of Rust). I'm looking for an equivalent in Rust.
The use case I'd like to cover is passing around a string that represents a URI, by annotating relevant signatures with something like Uri instead of String, and, ideally, use this Uri when a String is expected. All this with minimal overhead.
An obvious solution would be to use structs with one field:
struct Uri { val: String }
This has the drawback of slightly awkward usage, not being acceptable where a String is expected, and I'm unsure of its overhead.
Is there something similar to Scala's value classes in Rust? Is there some other mechanism that facilitates this use case?
I believe the thing you are looking for is the "strong type system". In Rust it is represented with a tuple struct with one field (a newtype):
struct Uri(pub String);
This creates a strong type with the least overhead. I'd say this just creates a mark for the compiler that this type is Uri and nothing else. Since this is a strong type, you can't simply pass String to it and get a String from it, you must do a conversion manually.
Simple example gives you a strong type on top of the String:
struct Uri(pub String);
fn takes_uri(uri: Uri) {
println!("URI: {}", uri.0);
}
fn takes_string(uri: String) {
println!("String: {}", uri);
}
fn main() {
let uri = Uri("https://stackoverflow.com".to_owned());
takes_uri(uri);
// takes_string(uri); // This does not compile
}
The key thing with strong types is that you can not implicitly cast them so this requires the code writer to write explicit code.
If I have a number of structs that I want to store:
type Stuff struct {
a string
b string
}
I can do it with a slice, but it seems like it would use less memory to use a proper set structure.
Unfortunately Go doesn't have a set structure. Everyone recommends using map[Stuff]struct{} but that doesn't work because Stuff is a struct. Anyone have any good solutions? Ideally without having to download a library.
Usually set and map data structures require more memory than storing a list of values in plain array or slice as set and map provide additional features efficiently like uniqueness or value retrieval by key.
If you want minimal memory usage, simply store them in a slice, e.g. []Stuff. If you use the values in multiple places, it might also be profitable to just store their pointers, e.g. []*Stuff and so each places that store the same Stuff values can store the same pointer (without duplicating the value).
If you only want to store unique struct values, then indeed the set would be the most convenient choice, in Go realized with a map.
There's nothing wrong with map[Stuff]struct{}, it works. The requirement for the key type for maps:
The comparison operators == and != must be fully defined for operands of the key type; thus the key type must not be a function, map, or slice.
Stuff is a struct, and structs in Go are comparable if:
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
If your Stuff struct is what you posted, it is comparable: it only contains fields of the comparable type string.
Also note that if you want a set data structure, it's clearer if you use bool as the value type (e.g. map[Stuff]bool) and true as the value, and then you can simply use indexing to test if a value is in the map as the index expression yields the zero value of the value type (false for bool) if the key (Stuff in your case) is not in the map, properly telling the value you're looking for is not in the "set". (And if it is in the map, its associated true value is the result of the index expression - properly telling it is in the map).
As icza said, a map of structs is a valid option.
But instead of implementing the Set yourself, I would use one of the new generic implementations that are out there since Go 1.18.
See this one for example: https://github.com/amit7itz/goset
package main
import (
"fmt"
"github.com/amit7itz/goset"
)
type Stuff struct {
a string
b string
}
func main() {
set := goset.NewSet[Stuff]()
set.Add(Stuff{a: "1", b: "2"})
set.Add(Stuff{a: "2", b: "3"})
set.Add(Stuff{a: "2", b: "3"})
fmt.Println(set) // Set[main.Stuff]{{2 3} {1 2}}
fmt.Println(set.Len()) // 2
}
In Java, all objects inherit from java.lang.Object. In Go, all types/structs implement the empty interface interface {}. Is there any similar construct in the Rust language?
If the answer is no, what makes it unnecessary? Is it because all entities in Rust (except modules) can be parameterized by type? Does that remove the need for a common "supertype" or common Trait shared by all Rust entities/structs/enums?
Yes, there is a trait. It is std::any::Any.
From the docs:
The Any trait is implemented by all 'static types, and can be used for dynamic typing
The way I understand it, if not completely unnecessary, it is less necessary in Rust to have a base type.
Note that the introduction of parametric polymorphism (generics) has removed most of the use cases for Object also in java.
With Object you can implement a "generic" method that can work with any kind of java type. On the other hand, when you have an Object you can't do much with it... You have to cast it back to the actual subtype to use it.
For instance, the old non-generic version of java collections worked with Objects, This means you had to work like this (sample is straight from this post on Oracle's site):
LinkedList list = new LinkedList();
list.add(new Integer(1));
Integer num = (Integer) list.get(0);
add takes an Object (so you can use the collection with any type). But get returns an Object too, so you have to cast it back to Integer based on the knowledge that you (the programmer) have on what you originally inserted in the LinkedList. There's very little type safety here.
The new generic version of the same container, since java 1.5, is:
LinkedList<Integer> list = new LinkedList<Integer>();
list.add(new Integer(1));
Integer num = list.get(0);
Now you have a list of Integer, so add takes Integer and get returns Integer. Object is nowhere to be seen any more (although due to type erasure it's just there, barely hiding under the hood...)
Note that Go's main use of interface{} stems from the fact that Go does not have generics. The main pattern of use for interface{} is roughly the same. You use it when you have to work with multiple types and you sort-of cast it (although in a safer way and with a more elegant pattern) back to a more useful type before using it.
With that in mind, you could theoretically use Any in Rust in the same way (checking actual type and casting to it before using it). It's just that you will likely not find many cases where this might be useful.
The code below works on rustc 0.13-nightly (2015-01-01), although I'm sure there are better ways to write it...
use std::any::{Any, AnyRefExt};
// just a couple of random types
struct Foo {
a: f64
}
enum Bar {
Baz(int),
Qux
}
fn main() {
// create an array of things that could have any type
let anything = &[&1i as &Any, &Foo{a: 2.} as &Any, &Bar::Qux as &Any];
// iterate and print only the integer
for &any in anything.iter() {
if any.is::<int>() { // check if type is int
match any.downcast_ref::<int>() { // cast to int
Some(a) => { println!("{}", *a); }
None => panic!()
}
// or just (shorter version of the match)
println!("{}", *any.downcast_ref::<int>().unwrap());
}
}
}