# Val类型是怎么用的，有点看不懂

Val类型是干什么的，doc里的解释没看不懂，来个大佬解释下

``````Return Val{c}(), which contains no run-time data. Types like this can be used to pass the information between functions through the value c, which must be an isbits value. The intent of this construct is to be able to dispatch on constants directly (at compile time) without having to test the value of the constant at run time.
``````

``````function test(a::Vector{Int}, ::Val{2})
return 2 .* a
end

function test(a::Vector{Int}, ::Val{3})
return a.^3
end

a = [1, 2, 3]
println(test(a, Val(2)))
println(test(a, Val(3)))
``````

[2, 4, 6]
[1, 8, 27]

``````Val(x) = Val{x}()
``````

1 个赞

Julia 编译器支持 constant propagation 之后，使用 `Val` 的场景已经非常少了。

X-ref: 24362, 24011

``````julia> f(x) = sin(x)
f (generic function with 1 method)

julia> g(x) = cos(x)
g (generic function with 1 method)

julia> h(x, y=1) = y == 1 ? f(x) : g(x)
h (generic function with 2 methods)

julia> bar(x) = h(x, 2)
bar (generic function with 1 method)

julia> baz(x) = h(x, 1)
baz (generic function with 1 method)

julia> @code_typed bar(3)
CodeInfo(
1 ─ %1 = (Base.sitofp)(Float64, x)::Float64
│   %2 = invoke Base.Math.cos(%1::Float64)::Float64
└──      return %2
) => Float64

julia> @code_typed baz(3)
CodeInfo(
1 ─ %1 = (Base.sitofp)(Float64, x)::Float64
│   %2 = invoke Base.Math.sin(%1::Float64)::Float64
└──      return %2
) => Float64
``````
2 个赞 典型场景应该比较少，暂时想不到，相对的：

1. if-else 的典型场景：`getproperty(value, name::Symbol)` 没有设计成利用 Val 进行 dispatch
2. trait-based dispatch: 通常会自定义trait type 而不是直接用 Val

``````julia> f(x)=if x==0 1 else 2 end
f (generic function with 1 method)

julia> g()=f(5)
g (generic function with 1 method)

julia> @code_llvm g()

;  @ REPL:1 within `g'
; Function Attrs: uwtable
define i64 @julia_g_16696() #0 {
top:
ret i64 2
}
``````