Created
February 28, 2019 21:57
-
-
Save jimblandy/a61a22a56805738fdbc54c7e453cb8ee to your computer and use it in GitHub Desktop.
Solution to the Squeeze challenge.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// You'll need this at the top of your crate: | |
// #![feature(optin_builtin_traits)] | |
//! The `squeeze` function. | |
//! | |
//! Omit unit values. That is: | |
//! - `squeeze(x, ())` returns `x`. | |
//! - `squeeze((), x)` returns `x`. | |
//! - `squeeze(x, y)` returns `(x, y)`, when neither `x` nor `y` is `()`. | |
//! - `squeeze((), ())` returns `()`. | |
//! | |
//! If you need to, you can write the return type of `squeeze(x, y)` as | |
//! `<(X, Y) as Squeeze>::Out`. | |
pub fn squeeze<X, Y>(x: X, y: Y) -> <X as Squeeze<Y>>::Output | |
where X: Squeeze<Y> | |
{ | |
Squeeze::squeeze(x, y) | |
} | |
pub trait Squeeze<Y> { | |
type Output; | |
fn squeeze(self, other: Y) -> Self::Output; | |
} | |
pub auto trait NonTrivial { } | |
impl !NonTrivial for () { } | |
impl<X: NonTrivial, Y: NonTrivial> Squeeze<Y> for X { | |
type Output = (X, Y); | |
fn squeeze(self, other: Y) -> (X, Y) { | |
(self, other) | |
} | |
} | |
impl<X: NonTrivial> Squeeze<()> for X { | |
type Output = X; | |
fn squeeze(self, _other: ()) -> X { | |
self | |
} | |
} | |
impl<Y: NonTrivial> Squeeze<Y> for () { | |
type Output = Y; | |
fn squeeze(self, other: Y) -> Y { | |
other | |
} | |
} | |
impl Squeeze<()> for () { | |
type Output = (); | |
fn squeeze(self, _other: ()) -> () { | |
() | |
} | |
} | |
#[cfg(test)] | |
mod test { | |
use super::squeeze; | |
#[test] | |
fn test_squeeze() { | |
// The idea here is that any non-() type would work. | |
assert_eq!(squeeze(1i32, 2i32), (1, 2)); | |
assert_eq!(squeeze(true, false), (true, false)); | |
assert_eq!(squeeze("foo", Some("bar")), ("foo", Some("bar"))); | |
assert_eq!(squeeze(1i32, ()), 1); | |
assert_eq!(squeeze("foo", ()), "foo"); | |
assert_eq!(squeeze(Some(1.3), ()), Some(1.3)); | |
assert_eq!(squeeze((), 2i32), 2); | |
assert_eq!(squeeze((), "foo"), "foo"); | |
assert_eq!(squeeze((), Some(1.3)), Some(1.3)); | |
assert_eq!(squeeze((), ()), ()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment