diff --git a/README.md b/README.md index 38db52b..264690a 100644 --- a/README.md +++ b/README.md @@ -52,17 +52,17 @@ The package exports the following bindings: ```julia-repl julia> using EnforcedTypeSignatureCallables -julia> typed_callable(Float32, sin)(0.3f0) +julia> typed_callable(sin, Float32)(0.3f0) 0.29552022f0 -julia> typed_callable(Float32, sin)(0.3) +julia> typed_callable(sin, Float32)(0.3) ERROR: TypeError: in typeassert, expected Float32, got a value of type Float64 [...] -julia> typed_callable(Float64, Tuple{Int, Int}, hypot)(3, 4) +julia> typed_callable(hypot, Float64, Tuple{Int, Int})(3, 4) 5.0 -julia> typed_callable(Float64, Tuple{Int, Int}, hypot)(3, 4.0) +julia> typed_callable(hypot, Float64, Tuple{Int, Int})(3, 4.0) ERROR: TypeError: in typeassert, expected Tuple{Int64, Int64}, got a value of type Tuple{Int64, Float64} [...] ``` @@ -133,7 +133,7 @@ suffices to call `typed_callable` once: ```julia function accepts_a_function_from_the_user(func, other_arguments...) - func = typed_callable(Float64, func) + func = typed_callable(func, Float64) # any call of `func` is now guaranteed not to return anything other than `Float64` end ``` @@ -146,7 +146,7 @@ function accepts_a_function_from_the_user_type_safe(func::CallableWithReturnType end function accepts_a_function_from_the_user(func, other_arguments...) - func = typed_callable(Float64, func) + func = typed_callable(func, Float64) accepts_a_function_from_the_user_type_safe(func, other_arguments...) end ``` diff --git a/src/EnforcedTypeSignatureCallables.jl b/src/EnforcedTypeSignatureCallables.jl index 4d60113..0e6fa5b 100644 --- a/src/EnforcedTypeSignatureCallables.jl +++ b/src/EnforcedTypeSignatureCallables.jl @@ -93,7 +93,7 @@ function return_type_enforcer(::Type{Return}) where {Return} end """ - typed_callable(return_type::Type, argument_types::Type{<:Tuple}, callable)::CallableWithTypeSignature{return_type, argument_types} + typed_callable(callable, return_type::Type, argument_types::Type{<:Tuple})::CallableWithTypeSignature{return_type, argument_types} Creates a callable from `callable` with: @@ -108,14 +108,14 @@ Examples: ```julia-repl julia> using EnforcedTypeSignatureCallables -julia> typed_callable(Float32, Tuple{Float32, Float32}, hypot)(3.1f0, 3.0f0) +julia> typed_callable(hypot, Float32, Tuple{Float32, Float32})(3.1f0, 3.0f0) 4.313931f0 -julia> typed_callable(Float32, Tuple{Float32, Float32}, hypot)(3.1f0, 3.0) +julia> typed_callable(hypot, Float32, Tuple{Float32, Float32})(3.1f0, 3.0) ERROR: TypeError: in typeassert, expected Tuple{Float32, Float32}, got a value of type Tuple{Float32, Float64} ``` """ -function typed_callable(::Type{Return}, ::Type{Arguments}, callable::Callable) where { +function typed_callable(callable::Callable, ::Type{Return}, ::Type{Arguments}) where { Return, Arguments <: Tuple, Callable, } ret = return_type_enforcer(Return) @@ -124,7 +124,7 @@ function typed_callable(::Type{Return}, ::Type{Arguments}, callable::Callable) w end """ - typed_callable(return_type::Type, callable)::CallableWithReturnType{return_type} + typed_callable(callable, return_type::Type)::CallableWithReturnType{return_type} Creates a callable from `callable` with guaranteed return type `return_type` @@ -141,14 +141,14 @@ julia> typed_callable(Int, Int)(3) julia> typed_callable(Int, Int) isa CallableWithReturnType{Int} true -julia> typed_callable(Float64, cos)(3) +julia> typed_callable(cos, Float64)(3) -0.9899924966004454 -julia> typed_callable(Float32, cos)(3.0) +julia> typed_callable(cos, Float32)(3.0) ERROR: TypeError: in typeassert, expected Float32, got a value of type Float64 ``` """ -function typed_callable(::Type{Return}, callable::Callable) where { +function typed_callable(callable::Callable, ::Type{Return}) where { Return, Callable, } ret = return_type_enforcer(Return) diff --git a/test/runtests.jl b/test/runtests.jl index 6de6709..979dc5b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,12 +13,12 @@ using Aqua: Aqua @test CallableWithReturnType{Float32} == ComposedFunction{Base.Fix2{typeof(typeassert), Type{Float32}}} end @testset "construction" begin - @test (@inferred typed_callable(Float64, cos)) isa CallableWithReturnType - @test (@inferred typed_callable(Float64, cos)) isa CallableWithReturnType{Float64} - @test (@inferred typed_callable(Float64, cos)) isa CallableWithReturnType{Float64, typeof(cos)} + @test (@inferred typed_callable(cos, Float64)) isa CallableWithReturnType + @test (@inferred typed_callable(cos, Float64)) isa CallableWithReturnType{Float64} + @test (@inferred typed_callable(cos, Float64)) isa CallableWithReturnType{Float64, typeof(cos)} end @testset "return type enforcement" begin - f = typed_callable(Int, only)::CallableWithReturnType + f = typed_callable(only, Int)::CallableWithReturnType x_int = Any[3] x_f64 = Any[3.0] @test 3 === @inferred f(x_int) @@ -33,24 +33,24 @@ using Aqua: Aqua @test_throws TypeError CallableWithTypeSignature{<:Any, Int} end @testset "construction" begin - @test (@inferred typed_callable(Float64, Tuple{Int, Int}, hypot)) isa CallableWithTypeSignature - @test (@inferred typed_callable(Float64, Tuple{Int, Int}, hypot)) isa CallableWithTypeSignature{Float64} - @test (@inferred typed_callable(Float64, Tuple{Int, Int}, hypot)) isa CallableWithTypeSignature{Float64, Tuple{Int, Int}} - @test (@inferred typed_callable(Float64, Tuple{Int, Int}, hypot)) isa CallableWithTypeSignature{Float64, Tuple{Int, Int}, typeof(hypot)} - @test (@inferred typed_callable(Int, Tuple{Float32}, Int)) isa CallableWithTypeSignature - @test (@inferred typed_callable(Int, Tuple{Float32}, Int)) isa CallableWithTypeSignature{Int} - @test (@inferred typed_callable(Int, Tuple{Float32}, Int)) isa CallableWithTypeSignature{Int, Tuple{Float32}} - @test (@inferred typed_callable(Int, Tuple{Float32}, Int)) isa CallableWithTypeSignature{Int, Tuple{Float32}, Type{Int}} + @test (@inferred typed_callable(hypot, Float64, Tuple{Int, Int})) isa CallableWithTypeSignature + @test (@inferred typed_callable(hypot, Float64, Tuple{Int, Int})) isa CallableWithTypeSignature{Float64} + @test (@inferred typed_callable(hypot, Float64, Tuple{Int, Int})) isa CallableWithTypeSignature{Float64, Tuple{Int, Int}} + @test (@inferred typed_callable(hypot, Float64, Tuple{Int, Int})) isa CallableWithTypeSignature{Float64, Tuple{Int, Int}, typeof(hypot)} + @test (@inferred typed_callable(Int, Int, Tuple{Float32})) isa CallableWithTypeSignature + @test (@inferred typed_callable(Int, Int, Tuple{Float32})) isa CallableWithTypeSignature{Int} + @test (@inferred typed_callable(Int, Int, Tuple{Float32})) isa CallableWithTypeSignature{Int, Tuple{Float32}} + @test (@inferred typed_callable(Int, Int, Tuple{Float32})) isa CallableWithTypeSignature{Int, Tuple{Float32}, Type{Int}} @test_throws MethodError typed_callable(Int, Int, Int) # arguments type must subtype `Tuple` end @testset "arguments type enforcement" begin @testset "non-`Type`" begin - f = typed_callable(Any, Tuple{Int}, -)::CallableWithTypeSignature + f = typed_callable(-, Any, Tuple{Int})::CallableWithTypeSignature @test -3 === @inferred f(3) @test_throws TypeError f(3.0) end @testset "`Type`" begin - f = typed_callable(Any, Tuple{Int}, Int8)::CallableWithTypeSignature + f = typed_callable(Int8, Any, Tuple{Int})::CallableWithTypeSignature @test Int8(3) === @inferred f(3) @test_throws TypeError f(3.0) end @@ -59,12 +59,12 @@ using Aqua: Aqua x_int = Any[3] x_f64 = Any[3.0] @testset "non-`Type`" begin - f = typed_callable(Int, Tuple, only)::CallableWithTypeSignature + f = typed_callable(only, Int, Tuple)::CallableWithTypeSignature @test 3 === @inferred f(x_int) @test_throws TypeError f(x_f64) end @testset "`Type`" begin - f = typed_callable(Int, Tuple, Int)::CallableWithTypeSignature + f = typed_callable(Int, Int, Tuple)::CallableWithTypeSignature @test 3 === @inferred f(3) @test 3 === @inferred f(3.0) end