C#. Until semi-recently it was only used for value types (as reference types are supposed to be nullable by default) but these days you can enable explicit nullables, which means that you have to explicitly specify nullability even for reference types.
I like explicit nullables. It's not much more work to type those question marks and it adds a safeguard against null showing up where it shouldn't.
I specifically inspired insisted on it for this picture because the code on the sign uses capitalized names for something that isn't a class, which is a very C# thing to do.
pub trait Gender {}
// implement your own gender, and if u want, publish online! :3
pub struct Masculine;
impl Gender for Masculine {}
pub struct Feminine;
impl Gender for Feminine {}
// removed old api:
// fn two_lovers(one: Masculine, two: Feminine)
// srry not srry for breaking backwards compat
// new version has more flexible api!<3
fn two_lovers(one: Box<dyn Gender>, two: Box<dyn Gender>) {
println!("smooch~");
}
// todo: other functions!!
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn me_and_who() {
two_lovers(Box::new(Feminine), Box::new(Feminine));
}
}
Good call with using a shared reference so now we can kiss our partner(s) more than once!!
Kissing many partners with one big smooch might be hard tho, maybe we need to change the implementation to use combinatorics so that everyone kisses each of their partners at least once.
Since there's no way to tell who kisses who, i can cheat by printing nCr times :3
pub fn lovers(partners: &[&dyn Gender]) {
match partners.len() {
0 => {
println!("ghost smooch~");
}
1 => {
println!("mirror smooch~");
}
p => {
// p >= 2, safe to unwrap
for _ in 0..ncr(p, 2).unwrap() {
println!("smooch~");
}
}
}
}