Distinguish Types of the Arguments
Objective: Define a fucntion that:
- Returns inverted value for boolean argument.
- Returns opposite value for integer argument.
- Returns object with coordinates swapped for argument of Point type.
- Prints warning and returns value of the argumen for any other type.
Test it where type of the argument is known in advance time and when it determined only in runtime.
Python
from typing import Union
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
def flip(a: Union[bool, int, Point]):
if isinstance(a, bool):
return not a
if isinstance(a, int):
return -a
if isinstance(a, Point):
return Point(a.y, a.x)
print(f"Warning: Type {a.__class__.__name__} not flippable");
return a
# types known in advance
print(f"{flip(False)=}")
print(f"{flip(3)=}")
print(f"{flip(Point(5, 7))=}")
print(f"{flip(33.3)=}")
# types determined in runtime
items = [False, 3, Point(5, 7), 33.3]
for item in items:
flipped = flip(item)
print(f"{item} flipped is {flipped}")
Rust
#![feature(auto_traits)] #![feature(negative_impls)] use std::ops::Neg; use std::any::type_name; auto trait Flippable { } impl !Flippable for bool {} impl !Flippable for i32 {} impl !Flippable for i64 {} #[derive(Debug)] struct Point { x: i32, y: i32 } fn flip_num<T: Neg<Output = T>> (a: T) -> T { -a } trait Flip { fn flip(a: Self) -> Self; } impl Flip for bool { fn flip(a: bool) -> bool { !a } } impl Flip for i32 { fn flip(a: i32) -> i32 { flip_num(a) } } impl Flip for i64 { fn flip(a: i64) -> i64 { flip_num(a) } } impl Flip for Point { fn flip(a: Point) -> Point { Point{x: a.y, y: a.x} } } impl<T> Flip for T where T: Flippable { fn flip(a: T) -> T { println!("Warning: Type {} not flippable", type_name::<T>() ); a } } fn flip<T: Flip>(a: T) -> T { Flip::flip(a) } fn main() { // types known in compile time dbg!( flip(true)); dbg!( flip(3 as i32) ); dbg!( flip(33 as i64) ); dbg!( flip(Point{x: 5, y: 7}) ); dbg!( flip(33.3) ); // types determined in runtime /* Error: not possible to use it this way let items: Vec<&dyn std::any::Any> = vec![&true, &(3 as i32), &(3 as i64), &Point{x: 5, y: 7}, &33.3]; for item in items { flip(*item); } */ }
Crystal
struct Point
property x : Int32
property y : Int32
def initialize(@x, @y)
end
end
def flip(a : Bool)
!a
end
# implementation for all integer types
def flip(a : Int)
-a
end
def flip(a : Point)
Point.new(a.y, a.x)
end
# implementation for all remaining types
def flip(a)
puts "Warning: Type #{a.class} not flippable"
a
end
# types known in compile time
p! flip false
p! flip 3_i32
p! flip 33_i64
p! flip Point.new(5, 7)
p! flip 33.3
# types determined in runtime
items = [false, 3_i32, 3_i64, Point.new(5, 7), 33.3]
items.each do |item|
flipped = flip item
puts "#{item} flipped is #{flipped}"
end