Is it possible to define a struct in Cython and then define another struct that inherits from that struct?
For example, if you did it in C++, then it would look like: C++ Struct inheritance in Cython However, you cannot do the same related syntax in Cython:
cdef struct Base:
# base members
# this doesn't work
cdef struct Derived : Base :
# derived members
If not, why is it not possible and what are some ways around that?
Related
I'm trying to create a proc-macro to derive and implement a trait for structs and I need that all fields within the struct implement Display.
How do I check that?
And furthermore how do I check if an attribute implements Iterator as well? (I want to handle if the item of the iterator implements display too).
I'm using syn and quote crates. And I managed to parse my struct and generate the implementation. But for types like Vec and Option I would like to check if they implement Iterator and handle it properly.
The syn::Field struct has the ty attribute which I believe should be a starting point, but looking into the docs I couldn't guess any way to check if this type implements a certain trait.
Add trait bounds and/or static assertions to the generated code. Macros run before type information is available since they can affect type information.
I read these docs about structs, but I don't understand about unit structs. It says:
Unit structs are most commonly used as marker. They have a size of zero bytes, but unlike empty enums they can be instantiated, making them isomorphic to the unit type (). Unit structs are useful when you need to implement a trait on something, but don’t need to store any data inside it.
they only give this piece of code as an example:
struct Unit;
What is a real world example of using a unit struct?
Standard library
Global
The global memory allocator, Global, is a unit struct:
pub struct Global;
It has no state of its own (because the state is global), but it implements traits like Allocator.
std::fmt::Error
The error for string formatting, std::fmt::Error, is a unit struct:
pub struct Error;
It has no state of its own, but it implements traits like Error.
RangeFull
The type for the .. operator, RangeFull, is a unit struct:
pub struct RangeFull;
It has no state of its own, but it implements traits like RangeBounds.
Crates
chrono::Utc
The Utc timezone is a unit struct:
pub struct Utc;
It has no state of its own, but it implements traits like TimeZone and is thus usable as a generic argument to Date and DateTime.
In addition to providing a basis for stateless trait implementations, you may also see unit structs created simply to serve as a marker (as mentioned in the quote) to be used in some other structure. Some examples:
In std::marker, there are PhantomData and PhantomPinned which are used to augment other types in concert with the compiler for variance, auto-generated traits, or other behavior. These in particular are special cases and not really a usable pattern outside the standard library.
You can see marker types used in the typestate pattern. Like Rocket<P> in Rocket v0.5. It uses P as simply an indicator of what "pahse" the application is in and provides methods only with specific phases (like can't configure after it is started). Technically Build/Ingite/Orbit are empty structs and not unit structs, but that distinction isn't meaningful here.
You can also see marker types used similarly for defining Format options in the tracing-subscriber crate. The Compact type (a unit struct) is used in conjunction with it to provide different methods and behavior that are not tied to itself directly (Compact implements no traits, and has no methods; the specialization comes from Format<Compact, T> implementing FormatEvent).
I've just split my program into an executable and a large file full of struct definitions (structs.rs).
In order to use the structs and their fields for the main executable, I have to prepend each struct definition, and every field definition with pub.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Foo {
pub bar: u8,
pub baz: [u8; 4]
}
This reduces readability.
Is there a way of avoiding all of these pubs?
Or should I be using another way of decomposing my program into multiple files?
This is expected. Modules and crates are a privacy boundary in Rust. The default privacy level for structs and their fields is "same module and its submodules", so parent modules and sibling modules need to have a permission to touch struct's fields.
In Rust structs typically have only a few fields, but the fields may have important invariants to uphold. For example, if Vec.len was public, you could cause unsafe out of bounds access. As a precaution, Rust requires programmers to think through whether they can allow access to each field.
It's unusual to have thousands of structs or structs with thousands of fields, unless they're mirroring some external data definition. If that's the case, consider auto-generating struct definitions with a macro or build.rs.
Can you set a Python class instance member variable to be a Cython object? Is this possible?
If that is not possible, can we set a Python class instance member variable to be something which points to a Cython object?
It's unclear what you mean by "class instance member variable" and "Cython object." I'll assume this rewording is what you mean:
Can you set a member variable of a pure Python class to be a Cython cppclass instance?
No. Pure Python instances can have Python references to other Python instances. At the C layer this means that the __dict__ can contain PyObject* pointers, but not generic C or C++ pointers to structs that don't obey the PyObject* semantics.
In Cython, you can use the cppclass keyword to create new C++ classes that are not PyObject variants (cdef cppclass CppClassDefinedInCython: ...). They're C++ classes like you'd create in a .h file.
Cython also allows you to declare new class objects (cdef class PyObjectClassDefinedInCython: ...). Under the hood, these are classes whose first set of fields have the same memory layout as all PyObject C structs and obey the pure C PyObject semantics. If you cdef fields in that class, then you can have the class contain arbitrary C and C++ data structures that are available to the C or C++ code generated by Cython.
If you're mixing C or C++ code with Python using Cython, you'll want to look up some tutorials such as: https://cython.readthedocs.io/en/latest/src/userguide/wrapping_CPlusPlus.html
Rust's enums are algebraic datatypes. As far as I can tell this seems to subsume what struct is. What is different about struct that necessitates keeping it?
First of all, you are correct that semantically enum is strictly superior to the struct as to what it can represent, and therefore struct is somewhat redundant.
However, there are other elements at play here.
ease of use: the values within an enum can only be accessed (directly) through matching; contrast with the ease of use of accessing a struct field. You could write accessors for each and every field, but that is really cumbersome.
distinction: an enum is a tagged union, a struct has a fixed-layout; we (programmers) generally like to put labels on things, and therefore giving different names to different functionality can be appreciated.
As I see it, struct is therefore syntactic sugar. I usually prefer lean and mean, but a bit of sugar can go a long way in increasing what can be represented tersely.
Firstly, Rust has a wide array of data types:
Structs with named fields (struct Foo {bar: uint})
Tuple structs (struct Foo(pub Bar, Baz))
Structs with no fields (struct Foo;)
Enums, with various types of variants:
Variants with no fields (eg None)
Tuple variants (eg Some(T))
Struct variants (eg Some { pub inner :T })
This gives the programmer some flexibility in defining datatypes. Often, you don't want named fields, especially if the struct/variant has only one field. Rust lets you use tuple structs/tuple variants in that case.
If structs were removed from Rust there would be no loss of functionality, enums with struct variants could be used again. But there would be an overwhelming number of single-variant enums which would be unnecessary and cumbersome to use.
Not 100% correct, but another nice way to think about it : enum isn't actually superior to struct, the syntax sugar just makes it look like it is.
An enum is a sum type meaning that it's value is one value of one of a set of other types. The Result<T, E> type is either of type T or E. So each enum variant has exactly one type associated with it. Everything else (no type, tuple variants and struct variants) could be syntax sugar.
enum Animal {
// without syntax sugar
Cat(i32),
// desugars to `Dog(())` (empty tuple/unit)
Dog,
// desugars to `Horse((i32, bool))` (tuple)
Horse(i32, bool),
// desugars to `Eagle(GeneratedEagleType)` and a struct definition outside
// of this enum `struct GeneratedEagleType { weight: i32, male: bool }`
Eagle { weight: i32, male: bool }
}
So it would be enough if each enum variant would be associated with exactly one type. And in that case enum is not superior to struct, because it cannot construct product types (like struct).
To be able write the "type definition" inside the enum variant definition is just for convenience.
Also: struct is superior to "tuple structs" and "tuples", too. If we ignore the names those three things are nearly equivalent. But Rust still has those three different kinds of types for convenience.
Please note that I don't know if those enum definitions are actually syntax sugar or not. But they could be and that might help think about. it
Visibility
Not to find reason in what may be a transient implementation detail (I'm not on the core team and have no insight), but
A public enum can not hold or contain a private struct.
A public struct can hold or contain a private enum.
See also
Why does "can't leak private type" only apply to structs and not enums?
You are right that enums and traits and their inheritance by structs both implement algebraic datatypes.
However traits is an extensible set of types, where any stuct can be attributed any trait from any piece of code. Using introspection, it is possible to expect a value with a given trait, and dynamically dig out the actual type of a struct. But that type is among a set of types that is unpredictable, because any struct could be given the said trait from anywhere.
Whereas enums define once and for all a limited type hierarchy, making it predictable and straightforward to go match subtypes as if they were simple values. The language features surrounding enums can therefore be optimized so that the type checks occur statically, providing much greater performance, and some sugar in the language. But also the hierarchy description is contained to the enum definition, and does not impact the trait type system.
TL;DR: enum narrows down a hierarchy of types in a contained manner, instead of relying on traits that are extensible by any piece of code and impacts everything.
Another important distinction along with the above answers is that enum at one point can ONLY be one of the values stated while struct represents values for all the parameters for that instance.
eg.
enum Things{
Box,
Page(i32),
}
struct Things{
box: Option<String>,
page: i32,
}
In the above case a single enum can either be a Box or a Page, while a single instance of struct will represent a box and a page.