Elixir: how to make struct enumerable - struct

I have a struct:
my_struct = %MyStruct{a: 1, b: 2}
how do I make it enumerable, so I can use the Enum methods on it?

You can use Map.to_list(struct) instead of Enum.to_list, since structs are just maps with a __struct__ key.

Related

Is there a way to pass compile time constant to repr directive?

const CELL_ALIGNMENT: usize = std::mem::align_of::<EntryType>();
#[repr(align(CELL_ALIGNMENT))]
pub struct AlignedCell;
#[repr(C)]
pub struct AlignedHeader {
_align: [AlignedCell; 0],
count: usize,
}
CELL_ALIGNMENT is a constant. But it looks like repr doesn't allow constant. Only literal is allowed. Is there any way to get around this?
No, you cannot use an expression in #[repr(align(_))]. It must be a literal.
The next best thing: you can assert the alignment of your struct matches another at compile-time by using the static-assertions crate:
#[repr(align(8))]
pub struct AlignedCell;
static_assertions::assert_eq_align!(AlignedCell, EntryType);
It doesn't set the alignment automatically, but you'll get a compiler error if its wrong.

Rust create a vector of custom struct type

I'm using config-rs crate. I want to set an array to a default value in my configuration. I want to use set_default() method from the crate that accepts an argument of type Value<Array> https://docs.rs/config/latest/config/builder/struct.ConfigBuilder.html#method.set_default
I'm new to rust and having a hard time as to how I can quickly create a vector<Value>
let default: Vec<ValueKind>= vec![1,2,3];// Errors
let default: Vec<Value>= vec![1,2,3]; // Errros
If you want to create a Vec<T>, the items have to be of type T. Rust does not perform implicit conversions so you need to write a little more code to make this work. It won't even allow implicit conversions between primitive types (Ex: i32 to i64).
For this, you can create a new Value or ValueKind by using From. I know this can be done because the documentation states that ValueKind implements From<i32>. The same thing also applies to Value, but it is much harder to spot when reading through the documentation.
// Same applies to `Value`.
let default: Vec<ValueKind> = vec![ValueKind::from(1), ValueKind::from(2), ValueKind::from(3)];
To make this easier, you also have a few other options. Into is implemented automatically for all types implimenting From, we can replace the lengthy ValueKind::from(1) with a shorter 1.into() call.
let default: Vec<ValueKind> = vec![1.into(), 2.into(), 3.into()];
If you have a lot of values you could also choose to use an iterator to convert an array of values all in one go.
let default: Vec<ValueKind> = [1, 2, 3, 4, 5, 6, 7, 8, 9]
.into_iter()
.map(|x| ValueKind::from(x))
.collect();
That being said, I am somewhat surprised the crate authors did not give the option to use Vec<i32> as-is (Though I have not checked the documentation on this since I do not know how it is used)*. It is not too difficult to write a generic function which accepts any iterable type like a Vec, array, or a bunch of other things, and turn it into ValueKind or Value as it goes.
/// Takes some iterable value and turns it into a Vec<ValueKind>.
pub fn to_valuekind<A, T>(values: A) -> Vec<ValueKind>
where
A: IntoIterator<Item = T>,
ValueKind: From<T>,
{
values.into_iter().map(|x| ValueKind::from(x)).collect()
}
*Looks like it is a restriction on how set_default functions. It accepts any Into<Value>, but by doing so they can't also implement across IntoIterator since it could theoretically cause a conflict if a type implemented both Into<Value> and IntoIterator<T> where T: Into<Value>.

Implementing inner type's traits on outer type

With the struct:
struct U85 (
[u8; 5]
);
I get the error:
error[E0608]: cannot index into a value of type `&U85`
--> /home/fadedbee/test.rs:11:40
|
11 | s.serialize_bytes(&self[..])
|
whereas when I use the simple type [u8; 5] everything is fine.
What trait of [u8; 5] causes the indexing error?
How can I implement it for U85?
The x[y] syntax is implemented with the Index and IndexMut traits. One catch with indexing for slices is that x, x..y, .., ..y, x.. are all different types. You can either pick-and-choose what you want to support, but if you just want to do what slices can do, you can implement it like so:
use std::ops::Index;
use std::slice::SliceIndex;
struct U85([u8; 5]);
impl<I> Index<I> for U85 where I: SliceIndex<[u8]> {
type Output = I::Output;
fn index(&self, index: I) -> &I::Output {
&self.0[index]
}
}
If you find yourself implementing traits for wrapper types a lot, you can look into using the derive_more crate, which will allow you to derive traits (like Index) that defer to the inner type.
use derive_more::Index;
#[derive(Index)]
struct U85([u8; 5]);

Why doesn't the struct update syntax work on non-exhaustive structs?

In the struct update syntax, the "spreaded" struct must be the same type as the resulting struct. So the spreaded struct has to contain all fields already.
What, then, is left that is not "exhausted"? Why is the struct update syntax not allowed for non-exhaustive struct?
use some_crate::NonExhaustiveStruct;
let a = NonExhaustiveStruct::default();
let b = {
some_field: true,
..a //Why doesn't this work?
};
This is currently an explicitly unsupported edge case: https://rust-lang.github.io/rfcs/2008-non-exhaustive.html#functional-record-updates. Within the same crate struct spread update syntax is allowed on non-exhausive structs but it is not allowed when the struct is defined in a separate crate.
The reasoning for this is that a private field could be added in future, and code outside the crate can't do spread updates of structs with private fields.

What are the differences between the multiple ways to create zero-sized structs?

I found four different ways to create a struct with no data:
struct A{} // empty struct / empty braced struct
struct B(); // empty tuple struct
struct C(()); // unit-valued tuple struct
struct D; // unit struct
(I'm leaving arbitrarily nested tuples that contain only ()s and single-variant enum declarations out of the question, as I understand why those shouldn't be used).
What are the differences between these four declarations? Would I use them for specific purposes, or are they interchangeable?
The book and the reference were surprisingly unhelpful. I did find this accepted RFC (clarified_adt_kinds) which goes into the differences a bit, namely that the unit struct also declares a constant value D and that the tuple structs also declare constructors B() and C(_: ()). However it doesn't offer a design guideline on why to use which.
My guess would be that when I export them with pub, there are differences in which kinds can actually be constructed outside of my module, but I found no conclusive documentation about that.
There are only two functional differences between these four definitions (and a fifth possibility I'll mention in a minute):
Syntax (the most obvious). mcarton's answer goes into more detail.
When the struct is marked pub, whether its constructor (also called struct literal syntax) is usable outside the module it's defined in.
The only one of your examples that is not directly constructible from outside the current module is C. If you try to do this, you will get an error:
mod stuff {
pub struct C(());
}
let _c = stuff::C(()); // error[E0603]: tuple struct `C` is private
This happens because the field is not marked pub; if you declare C as pub struct C(pub ()), the error goes away.
There's another possibility you didn't mention that gives a marginally more descriptive error message: a normal struct, with a zero-sized non-pub member.
mod stuff {
pub struct E {
_dummy: (),
}
}
let _e = stuff::E { _dummy: () }; // error[E0451]: field `_dummy` of struct `main::stuff::E` is private
(Again, you can make the _dummy field available outside of the module by declaring it with pub.)
Since E's constructor is only usable inside the stuff module, stuff has exclusive control over when and how values of E are created. Many structs in the standard library take advantage of this, like Box (to take an obvious example). Zero-sized types work in exactly the same way; in fact, from outside the module it's defined in, the only way you would know that an opaque type is zero-sized is by calling mem::size_of.
See also
What is an idiomatic way to create a zero-sized struct that can't be instantiated outside its crate?
Why define a struct with single private field of unit type?
struct D; // unit struct
This is the usual way for people to write a zero-sized struct.
struct A{} // empty struct / empty braced struct
struct B(); // empty tuple struct
These are just special cases of basic struct and tuple struct which happen to have no parameters. RFC 1506 explains the rational to allow those (they didn't used to):
Permit tuple structs and tuple variants with 0 fields. This restriction is artificial and can be lifted trivially. Macro writers dealing with tuple structs/variants will be happy to get rid of this one special case.
As such, they could easily be generated by macros, but people will rarely write those on their own.
struct C(()); // unit-valued tuple struct
This is another special case of tuple struct. In Rust, () is a type just like any other type, so struct C(()); isn't much different from struct E(u32);. While the type itself isn't very useful, forbidding it would make yet another special case that would need to be handled in macros or generics (struct F<T>(T) can of course be instantiated as F<()>).
Note that there are many other ways to have empty types in Rust. Eg. it is possible to have a function return Result<(), !> to indicate that it doesn't produce a value, and cannot fail. While you might think that returning () in that case would be better, you might have to do that if you implement a trait that dictates you to return Result<T, E> but lets you choose T = () and E = !.

Resources