From 2447f79ce0749ae17b8948811a976769ff0ad94b Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 4 Jan 2015 05:02:43 -0600 Subject: [PATCH] Revert "Revert "Add documentation and test for Val{T}"" This reverts commit ef7f5d41d2023d459f2a47f16424078fbbfca1bf. This is modified to incorporate the verdict in the discussion of #9452. --- NEWS.md | 2 ++ doc/manual/types.rst | 35 ++++++++++++++++++++++++++++++++++- doc/stdlib/base.rst | 8 ++++++++ test/core.jl | 10 ++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 39810e08535d4..1cd1b747c76d9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -143,6 +143,7 @@ Library improvements * The `randexp` and `randexp!` functions are exported ([#9144]) + * A new `Val{T}` type allows one to dispatch on bits-type values ([#9452]) Deprecated or removed --------------------- @@ -1145,3 +1146,4 @@ Too numerous to mention. [#9271]: https://github.com/JuliaLang/julia/issues/9271 [#9294]: https://github.com/JuliaLang/julia/issues/9294 [#9569]: https://github.com/JuliaLang/julia/issues/9569 +[#9452]: https://github.com/JuliaLang/julia/issues/9452 diff --git a/doc/manual/types.rst b/doc/manual/types.rst index 92d459ab8b57a..90ca1d6c09b9a 100644 --- a/doc/manual/types.rst +++ b/doc/manual/types.rst @@ -692,7 +692,7 @@ surrounded by curly braces:: This declaration defines a new parametric type, ``Point{T}``, holding two "coordinates" of type ``T``. What, one may ask, is ``T``? Well, that's precisely the point of parametric types: it can be any type at -all (or an integer, actually, although here it's clearly used as a +all (or any bits type, actually, although here it's clearly used as a type). ``Point{Float64}`` is a concrete type equivalent to the type defined by replacing ``T`` in the definition of ``Point`` with :class:`Float64`. Thus, this single declaration actually declares an @@ -1243,6 +1243,39 @@ If you apply :func:`super` to other type objects (or non-type objects), a julia> super((Float64,Int64)) ERROR: `super` has no method matching super(::Type{(Float64,Int64)}) +"Value types" +------------- + +As one application of these ideas, Julia includes a parametric type, +``Val{T}``, designated for dispatching on bits-type *values*. For +example, if you pass a boolean to a function, you have to test the +value at run-time: + +.. doctest:: + + function firstlast(b::Bool) + return b ? "First" : "Last" + end + + println(firstlast(true)) + +You can instead cause the conditional to be evaluated during function +compilation by using the ``Val`` trick: + +.. doctest:: + + firstlast(::Type{Val{true}}) = "First" + firstlast(::Type{Val{false}}) = "Last" + + println(firstlast(Val{true})) + +Any legal type parameter (Types, Symbols, Integers, floating-point +numbers, tuples, etc.) can be passed via ``Val``. + +For consistency across Julia, the call site should always pass a +``Val`` type rather than creating an instance, i.e., use +``foo(Val{:bar})`` rather than ``foo(Val{:bar}())``. + Nullable Types: Representing Missing Values ------------------------------------------- diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index 1e3b94dab8dfa..54e042188c13e 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -438,6 +438,14 @@ Types Compute a type that contains the intersection of ``T`` and ``S``. Usually this will be the smallest such type or one close to it. +.. function:: Val{c} + + Create a "value type" out of ``c``, which must be an ``isbits`` + value. The intent of this construct is to be able to dispatch on + constants, e.g., ``f(Val{false})`` allows you to dispatch directly + (at compile-time) to an implementation ``f(::Type{Val{false}})``, + without having to test the boolean value at runtime. + Generic Functions ----------------- diff --git a/test/core.jl b/test/core.jl index 051538412a9b9..bf8689a0cba83 100644 --- a/test/core.jl +++ b/test/core.jl @@ -502,6 +502,16 @@ begin @test is(g(a),a) end +# dispatch using Val{T}. See discussion in #9452 for instances vs types +begin + local firstlast + firstlast(::Type{Val{true}}) = "First" + firstlast(::Type{Val{false}}) = "Last" + + @test firstlast(Val{true}) == "First" + @test firstlast(Val{false}) == "Last" +end + # try/finally begin after = 0