From 5afc33594f9534c827abd81878e7f547b0cb216d Mon Sep 17 00:00:00 2001 From: "William S. Moses" Date: Tue, 7 May 2019 14:35:10 -0400 Subject: [PATCH 01/16] Fix compilation with external LLVM --- deps/llvm.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deps/llvm.mk b/deps/llvm.mk index 0a9d117e1afcc..c0f1123eea14b 100644 --- a/deps/llvm.mk +++ b/deps/llvm.mk @@ -460,11 +460,13 @@ $(eval $(call LLVM_PATCH,llvm-D57118-powerpc)) # remove for 9.0 endif # LLVM_VER 8.0 # Add a JL prefix to the version map. DO NOT REMOVE +ifneq ($(LLVM_VER), svn) ifeq ($(LLVM_VER_SHORT), 6.0) $(eval $(call LLVM_PATCH,llvm-symver-jlprefix)) else $(eval $(call LLVM_PATCH,llvm7-symver-jlprefix)) endif +endif # declare that all patches must be applied before running ./configure $(LLVM_BUILDDIR_withtype)/build-configured: | $(LLVM_PATCH_PREV) From 5773574f4faa1fb889dd6ae4ca5e7454baf1c93c Mon Sep 17 00:00:00 2001 From: Mark Van de Vyver Date: Tue, 14 May 2019 09:21:54 +1000 Subject: [PATCH 02/16] Clarify default values: Position vs Keyword Tries to address my confusion and that of David Klaffenbach here: https://discourse.julialang.org/t/define-f-with-keyword-arguments-function-f-does-not-accept-keyword-arguments/24186 Maybe others also too sheepish to speak-up publicly? --- doc/src/manual/methods.md | 54 ++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 07f0c998f4105..6c72793327007 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -797,10 +797,38 @@ would be called only when the number of `indices` matches the dimensionality of When only the type of supplied arguments needs to be constrained `Vararg{T}` can be equivalently written as `T...`. For instance `f(x::Int...) = x` is a shorthand for `f(x::Vararg{Int}) = x`. -## Note on Optional and keyword Arguments +## Note on Optional/Default Positional and Keyword Arguments -As mentioned briefly in [Functions](@ref man-functions), optional arguments are implemented as syntax for multiple -method definitions. For example, this definition: +There are two styles for setting optional agruments (a.k.a default values). + +1. Using position arguments. +1. Using keyword arguments. + +Keyword arguments behave differently from ordinary positional arguments. +Specifically, they do not participate in method dispatch. + +!!! note Function methods are dispatched based *only* on positional arguments. +Keyword arguments are processed after the matching method is identified. + +!!! warning A consequence of the above note on dispatch: +If a function, say `f`, has a method that uses position based default values and elsewhere in your +code you have the same function name with a method defined to use keyword based default values; +then the default value returned by `f()` will be the last definition Julia processed. +**There will be no ambiguity warning** +```jldoctest +julia> f(a=1,b=2)=5 +f (generic function with 3 methods) + +julia> f(;a=1,b=2)=10 +f (generic function with 3 methods) + +julia> f() +10 +``` + +**Position** based default/optional arguments are implemented as a shorthand for multiple method +definitions (this was mentioned briefly in [Functions](@ref man-functions)). +For example, this definition: ```julia f(a=1,b=2) = a+2b @@ -827,9 +855,23 @@ to a function, not to any specific method of that function. It depends on the ty arguments which method is invoked. When optional arguments are defined in terms of a global variable, the type of the optional argument may even change at run-time. -Keyword arguments behave quite differently from ordinary positional arguments. In particular, -they do not participate in method dispatch. Methods are dispatched based only on positional arguments, -with keyword arguments processed after the matching method is identified. +**Keyword** based default/optional arguments create only one method. +For example, consider this definition (note the leading `;`), in a new REPL: + +```jldoctest +julia> f(;a=1,b=2) = 2a+4b +f (generic function with 1 method) +julia> f(a=2) +12 + +julia> f(b=4) +18 + +julia> f() +10 +``` + +This means that calling `f()` is equivalent to calling `f(;a=1,b=2)` or `f(a=1,b=2)`. In all cases the result is `10`. ## Function-like objects From ac118fb01255315ecd14b76819569be73008c271 Mon Sep 17 00:00:00 2001 From: Mark Van de Vyver Date: Tue, 14 May 2019 12:05:44 +1000 Subject: [PATCH 03/16] Remove alerts. Add issue #9498 and example. Added an example of issue #9498 - since it is not scheduled to be fixed until Julia 2.0. Kept the example of ambiguous/last-seen default code being run because that is the core use case for default values. --- doc/src/manual/methods.md | 48 +++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 6c72793327007..d38dc3b0adb49 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -806,15 +806,21 @@ There are two styles for setting optional agruments (a.k.a default values). Keyword arguments behave differently from ordinary positional arguments. Specifically, they do not participate in method dispatch. - -!!! note Function methods are dispatched based *only* on positional arguments. +Function methods are dispatched based *only* on positional arguments. Keyword arguments are processed after the matching method is identified. -!!! warning A consequence of the above note on dispatch: +However, an existing issue means that function method dispatch behaves differently when +doing a function call with or without keyword arguments. +This issue is currently scheduled to be fixed in Julia 2.0. +See [Issue #9498](https://github.com/JuliaLang/julia/issues/9498) for further details. + +One consequence of keyword arguments not influencing dispatch decisions is that the default +method executed will be the last defined: If a function, say `f`, has a method that uses position based default values and elsewhere in your code you have the same function name with a method defined to use keyword based default values; then the default value returned by `f()` will be the last definition Julia processed. -**There will be no ambiguity warning** +*There will be no ambiguity warning* + ```jldoctest julia> f(a=1,b=2)=5 f (generic function with 3 methods) @@ -825,6 +831,40 @@ f (generic function with 3 methods) julia> f() 10 ``` +An example of [Issue #9498](https://github.com/JuliaLang/julia/issues/9498), which works when methods are defined in one order: + +```jldoctest +julia> bar(x, y; c) = x + y + c +bar (generic function with 1 method) + +julia> bar(x, y) = x / y +bar (generic function with 1 method) + +julia> bar(3,4) +0.75 + +julia> bar(3,4, c=5) +12 +``` + +Yet, throws an error if the code is defined in a different order + +```jldoctest +julia> bar(x, y) = x / y +bar (generic function with 1 method) + +julia> bar(x, y; c) = x + y + c +bar (generic function with 1 method) + +julia> bar(3,4,c=5) +12 + +julia> bar(3,4) +ERROR: UndefKeywordError: keyword argument c not assigned +Stacktrace: + [1] bar(::Int64, ::Int64) at ./REPL[2]:1 + [2] top-level scope at none:0 +``` **Position** based default/optional arguments are implemented as a shorthand for multiple method definitions (this was mentioned briefly in [Functions](@ref man-functions)). From 81cd13c9936d848b0b0941edd328d46276084917 Mon Sep 17 00:00:00 2001 From: Mark Van de Vyver Date: Tue, 14 May 2019 12:28:49 +1000 Subject: [PATCH 04/16] Fix referencing --- doc/src/manual/functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/functions.md b/doc/src/manual/functions.md index 1c68f087bbe76..38716232a0fdb 100644 --- a/doc/src/manual/functions.md +++ b/doc/src/manual/functions.md @@ -493,10 +493,10 @@ julia> Date(2000) ``` Optional arguments are actually just a convenient syntax for writing multiple method definitions -with different numbers of arguments (see [Note on Optional and keyword Arguments](@ref)). +with different numbers of arguments (see [Note on Optional and keyword Arguments](@ref man-note-default-arguments)). This can be checked for our `Date` function example by calling `methods` function. -## Keyword Arguments +## Keyword Arguments(@id man-keyword-arguments) Some functions need a large number of arguments, or have a large number of behaviors. Remembering how to call such functions can be difficult. Keyword arguments can make these complex interfaces From 30de3651635a0116f17b0061f0222874d6bbc2af Mon Sep 17 00:00:00 2001 From: Mark Van de Vyver Date: Tue, 14 May 2019 12:32:26 +1000 Subject: [PATCH 05/16] Add references to functions page --- doc/src/manual/methods.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index d38dc3b0adb49..05865559692c3 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -797,14 +797,14 @@ would be called only when the number of `indices` matches the dimensionality of When only the type of supplied arguments needs to be constrained `Vararg{T}` can be equivalently written as `T...`. For instance `f(x::Int...) = x` is a shorthand for `f(x::Vararg{Int}) = x`. -## Note on Optional/Default Positional and Keyword Arguments +## Note on Optional/Default Positional and Keyword Arguments(@id note-default-arguments) There are two styles for setting optional agruments (a.k.a default values). 1. Using position arguments. 1. Using keyword arguments. -Keyword arguments behave differently from ordinary positional arguments. +[Keyword arguments](@ref man-keyword-arguments) behave differently from ordinary positional arguments. Specifically, they do not participate in method dispatch. Function methods are dispatched based *only* on positional arguments. Keyword arguments are processed after the matching method is identified. From 35e25fd57f5cf4a8e6036a4e280c0a7a9915e101 Mon Sep 17 00:00:00 2001 From: Mark Van de Vyver Date: Tue, 14 May 2019 12:37:07 +1000 Subject: [PATCH 06/16] Fix id man-note-default-arguments --- doc/src/manual/methods.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 05865559692c3..f7b4b21548eec 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -797,7 +797,7 @@ would be called only when the number of `indices` matches the dimensionality of When only the type of supplied arguments needs to be constrained `Vararg{T}` can be equivalently written as `T...`. For instance `f(x::Int...) = x` is a shorthand for `f(x::Vararg{Int}) = x`. -## Note on Optional/Default Positional and Keyword Arguments(@id note-default-arguments) +## Note on Optional/Default Positional and Keyword Arguments(@id man-note-default-arguments) There are two styles for setting optional agruments (a.k.a default values). From b05c0c7507a7a2052b88594470a41f876bb7122d Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 14 May 2019 09:09:44 -0400 Subject: [PATCH 07/16] bugfix in Hermitian + complex*I (#32001) --- stdlib/LinearAlgebra/src/uniformscaling.jl | 24 ++++++++++----------- stdlib/LinearAlgebra/test/uniformscaling.jl | 18 +++++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/stdlib/LinearAlgebra/src/uniformscaling.jl b/stdlib/LinearAlgebra/src/uniformscaling.jl index af1aee3ec8cd4..258bcb09bb04f 100644 --- a/stdlib/LinearAlgebra/src/uniformscaling.jl +++ b/stdlib/LinearAlgebra/src/uniformscaling.jl @@ -141,23 +141,21 @@ end # matrix breaks the hermiticity, if the UniformScaling is non-real. # However, to preserve type stability, we do not special-case a # UniformScaling{<:Complex} that happens to be real. -function (+)(A::Hermitian{T,S}, J::UniformScaling{<:Complex}) where {T,S} - A_ = copytri!(copy(parent(A)), A.uplo) - B = convert(AbstractMatrix{Base._return_type(+, Tuple{eltype(A), typeof(J)})}, A_) - @inbounds for i in diagind(B) - B[i] += J +function (+)(A::Hermitian, J::UniformScaling{<:Complex}) + TS = Base._return_type(+, Tuple{eltype(A), typeof(J)}) + B = copytri!(copy_oftype(parent(A), TS), A.uplo, true) + for i in diagind(B) + B[i] = A[i] + J end return B end -function (-)(J::UniformScaling{<:Complex}, A::Hermitian{T,S}) where {T,S} - A_ = copytri!(copy(parent(A)), A.uplo) - B = convert(AbstractMatrix{Base._return_type(+, Tuple{eltype(A), typeof(J)})}, A_) - @inbounds for i in eachindex(B) - B[i] = -B[i] - end - @inbounds for i in diagind(B) - B[i] += J +function (-)(J::UniformScaling{<:Complex}, A::Hermitian) + TS = Base._return_type(+, Tuple{eltype(A), typeof(J)}) + B = copytri!(copy_oftype(parent(A), TS), A.uplo, true) + B .= .-B + for i in diagind(B) + B[i] = J - A[i] end return B end diff --git a/stdlib/LinearAlgebra/test/uniformscaling.jl b/stdlib/LinearAlgebra/test/uniformscaling.jl index f8535eb6e1756..929e116ea6359 100644 --- a/stdlib/LinearAlgebra/test/uniformscaling.jl +++ b/stdlib/LinearAlgebra/test/uniformscaling.jl @@ -180,15 +180,17 @@ let @test @inferred(J - T) == J - Array(T) @test @inferred(T\I) == inv(T) - if isa(A, Array) - T = Hermitian(randn(3,3)) - else - T = Hermitian(view(randn(3,3), 1:3, 1:3)) + for elty in (Float64, ComplexF64) + if isa(A, Array) + T = Hermitian(randn(elty, 3,3)) + else + T = Hermitian(view(randn(elty, 3,3), 1:3, 1:3)) + end + @test @inferred(T + J) == Array(T) + J + @test @inferred(J + T) == J + Array(T) + @test @inferred(T - J) == Array(T) - J + @test @inferred(J - T) == J - Array(T) end - @test @inferred(T + J) == Array(T) + J - @test @inferred(J + T) == J + Array(T) - @test @inferred(T - J) == Array(T) - J - @test @inferred(J - T) == J - Array(T) @test @inferred(I\A) == A @test @inferred(A\I) == inv(A) From 95c95b62c268b259eed044f699378f4988e94142 Mon Sep 17 00:00:00 2001 From: Jerry Ling Date: Tue, 14 May 2019 06:28:48 -0700 Subject: [PATCH 08/16] Mention rationals are checked for overflow in docstring. (#31926) --- base/rational.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/base/rational.jl b/base/rational.jl index b15319b647999..4f5552a05e42a 100644 --- a/base/rational.jl +++ b/base/rational.jl @@ -4,6 +4,7 @@ Rational{T<:Integer} <: Real Rational number type, with numerator and denominator of type `T`. +Rationals are checked for overflow. """ struct Rational{T<:Integer} <: Real num::T From 0523d1d93b1b29018ce8363316b09498645c9700 Mon Sep 17 00:00:00 2001 From: Jerry Ling Date: Tue, 14 May 2019 07:58:51 -0700 Subject: [PATCH 09/16] REPL docs for __init__ (#31930) --- base/docs/basedocs.jl | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index fdac8e5715590..58b901903fbbb 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -100,6 +100,29 @@ end """ kw"module" +""" + __init__ + +`__init__()` function in your module would executes immediately *after* the module is loaded at +runtime for the first time (i.e., it is only called once and only after all statements in the +module have been executed). Because it is called *after* fully importing the module, `__init__` +functions of submodules will be executed *first*. Two typical uses of __init__ are calling +runtime initialization functions of external C libraries and initializing global constants +that involve pointers returned by external libraries. +See the [manual section about modules](@ref modules) for more details. + +# Examples +```julia +const foo_data_ptr = Ref{Ptr{Cvoid}}(0) +function __init__() + ccall((:foo_init, :libfoo), Cvoid, ()) + foo_data_ptr[] = ccall((:foo_data, :libfoo), Ptr{Cvoid}, ()) + nothing +end +``` +""" +kw"__init__" + """ baremodule From b4b46342ea71604f07416a8652afa12913128a54 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 14 May 2019 12:15:43 -0400 Subject: [PATCH 10/16] Remove tiers of support (#32022) The tiers of support are now maintained in one place, i.e. on the downloads page on the website. It was difficult to have an accurate list of tiers for master, and much simpler to have support tiers for the latest stable release instead. Thus, the downloads page is the right place to host this information and curate it. --- README.md | 44 ++++---------------------------------------- 1 file changed, 4 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index d5be276988069..7690684f371f0 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,10 @@ helpful to start contributing to the Julia codebase. If you would rather not compile the latest Julia from source, platform-specific tarballs with pre-compiled binaries are also -[available for download](https://julialang.org/downloads/). +[available for download](https://julialang.org/downloads/). The +downloads page also provides details on the +[different tiers of support](https://julialang.org/downloads/#support-tiers) +for OS and platform combinations. If everything works correctly, you will see a Julia banner and an interactive prompt into which you can enter expressions for @@ -64,45 +67,6 @@ installations are neither maintained nor endorsed by the Julia project. They may be outdated, broken and/or unmaintained. We recommend you use the official Julia binaries instead. -## Currently Supported Platforms - -| Operating System | Architecture | CI | Binaries | Support Level | -|:----------------:|:----------------:|:--:|:--------:|:-------------:| -| macOS 10.8+ | x86-64 (64-bit) | ✓ | ✓ | Tier 1 | -| Windows 7+ | x86-64 (64-bit) | ✓ | ✓ | Tier 1 | -| | i686 (32-bit) | ✓ | ✓ | Tier 1 | -| FreeBSD 11.0+ | x86-64 (64-bit) | [✓](https://build.julialang.org/#/builders/68) | ✓ | Tier 1 | -| Linux 2.6.18+ | x86-64 (64-bit) | ✓ | ✓ | Tier 1 | -| | i686 (32-bit) | ✓ | ✓ | Tier 1 | -| | ARM v7 (32-bit) | | | Tier 3 | -| | ARM v8 (64-bit) | | | Tier 3 | -| | x86-64 musl libc | | | Tier 3 | -| | PowerPC (64-bit) | | | Tier 4 | -| | PTX (64-bit) | [✓](https://gitlab.com/JuliaGPU/CUDAnative.jl/pipelines) | | [External](https://github.com/JuliaGPU/CUDAnative.jl) | - -All systems marked with ✓ for CI are tested using continuous integration for every commit. -Systems with ✓ for binaries have official binaries available on the -[downloads](https://julialang.org/downloads) page and are tested regularly. -The PTX backend is supported by the [JuliaGPU](https://github.com/JuliaGPU) organization and -requires the [CUDAnative.jl](https://github.com/JuliaGPU/CUDAnative.jl) package. - -### Support Tiers - -* Tier 1: Julia is guaranteed to build from source and pass all tests on these platforms - when built with default options. Official binaries are available for releases and CI is - run on every commit. - -* Tier 2: Julia is guaranteed to build from source using default build options, but may - or may not pass all tests. Official binaries are available on a case-by-case basis. - -* Tier 3: Julia may or may not build. If it does, it is unlikely to pass tests. - -* Tier 4: Julia is known not to build. - -It is possible that Julia will build and work on other platforms too, -and we're always looking to improve our platform coverage. If you're -using Julia on a platform not listed here, let us know! - ## Building Julia First, make sure you have all the [required From 40d72ad113a53c2dfe5a345c54ff9deabea06516 Mon Sep 17 00:00:00 2001 From: "Viral B. Shah" Date: Tue, 14 May 2019 18:11:45 -0400 Subject: [PATCH 11/16] Move ack out to its own repo in JuliaEditorSupport. (#32021) https://github.com/JuliaEditorSupport/roadmap/issues/6 --- contrib/README.md | 2 -- contrib/ack/README.md | 2 -- contrib/ack/ackrc | 2 -- 3 files changed, 6 deletions(-) delete mode 100644 contrib/ack/README.md delete mode 100644 contrib/ack/ackrc diff --git a/contrib/README.md b/contrib/README.md index aacef59415921..fbc736cea0931 100644 --- a/contrib/README.md +++ b/contrib/README.md @@ -31,7 +31,5 @@ If your favorite IDE, is not listed there, [open an issue in the JuliaEditorSupp | Name | Description | | ------------------------------ | ----------------------------------------------------------- | -|[ ackrc ](https://github.com/JuliaLang/julia/blob/master/contrib/ackrc ) | Config for Ack search tool | |[ debug_bootstrap.gdb ](https://github.com/JuliaLang/julia/blob/master/contrib/debug_bootstrap.gdb) | Bootstrap process using the debug build | -|[ README.ackrc.txt ](https://github.com/JuliaLang/julia/blob/master/contrib/README.ackrc.txt) | README for ackrc config file | |[ valgrind-julia.supp ](https://github.com/JuliaLang/julia/blob/master/contrib/valgrind-julia.supp) | Suppressions for Valgrind debugging tool | diff --git a/contrib/ack/README.md b/contrib/ack/README.md deleted file mode 100644 index 2dedceeaf7bcb..0000000000000 --- a/contrib/ack/README.md +++ /dev/null @@ -1,2 +0,0 @@ -The 'ackrc' file is for Ack (http://beyondgrep.com/) -Place its contents in your ~/.ackrc file. diff --git a/contrib/ack/ackrc b/contrib/ack/ackrc deleted file mode 100644 index 0a0292f922180..0000000000000 --- a/contrib/ack/ackrc +++ /dev/null @@ -1,2 +0,0 @@ ---type-set=julia=.jl ---type-add=julia:firstlinematch:/^#!.*\bjulia/ From 923645c4360ce90364a18635203f926a01727ec7 Mon Sep 17 00:00:00 2001 From: Mark Van de Vyver Date: Tue, 14 May 2019 09:21:54 +1000 Subject: [PATCH 12/16] Clarify default values: Position vs Keyword Tries to address my confusion and that of David Klaffenbach here: https://discourse.julialang.org/t/define-f-with-keyword-arguments-function-f-does-not-accept-keyword-arguments/24186 Maybe others also too sheepish to speak-up publicly? --- doc/src/manual/methods.md | 54 ++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 07f0c998f4105..50919d0e60d00 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -797,10 +797,38 @@ would be called only when the number of `indices` matches the dimensionality of When only the type of supplied arguments needs to be constrained `Vararg{T}` can be equivalently written as `T...`. For instance `f(x::Int...) = x` is a shorthand for `f(x::Vararg{Int}) = x`. -## Note on Optional and keyword Arguments +## Note on Optional/Default Positional and Keyword Arguments -As mentioned briefly in [Functions](@ref man-functions), optional arguments are implemented as syntax for multiple -method definitions. For example, this definition: +There are two styles for setting optional agruments (a.k.a default values). + +1. Using position arguments. +1. Using keyword arguments. + +Keyword arguments behave differently from ordinary positional arguments. +Specifically, they do not participate in method dispatch. + +!!! note Function methods are dispatched based *only* on positional arguments. +Keyword arguments are processed after the matching method is identified. + +!!! warning A consequence of the above note on dispatch: +If a function, say `f`, has a method that uses position based default values and elsewhere in your +code you have the same function name with a method defined to use keyword based default values; +then the default value returned by `f()` will be the last definition Julia processed. +**There will be no ambiguity warning** +```jldoctest +julia> f(a=1,b=2)=5 +f (generic function with 3 methods) + +julia> f(;a=1,b=2)=10 +f (generic function with 3 methods) + +julia> f() +10 +``` + +**Position** based default/optional arguments are implemented as a shorthand for multiple method +definitions (this was mentioned briefly in [Functions](@ref man-functions)). +For example, this definition: ```julia f(a=1,b=2) = a+2b @@ -827,9 +855,23 @@ to a function, not to any specific method of that function. It depends on the ty arguments which method is invoked. When optional arguments are defined in terms of a global variable, the type of the optional argument may even change at run-time. -Keyword arguments behave quite differently from ordinary positional arguments. In particular, -they do not participate in method dispatch. Methods are dispatched based only on positional arguments, -with keyword arguments processed after the matching method is identified. +**Keyword** based default/optional arguments create only one method. +For example, consider this definition (note the leading `;`), in a new REPL: + +```jldoctest +julia> f(;a=1,b=2) = 2a+4b +f (generic function with 1 method) +julia> f(a=2) +12 + +julia> f(b=4) +18 + +julia> f() +10 +``` + +This means that calling `f()` is equivalent to calling `f(;a=1,b=2)` or `f(a=1,b=2)`. In all cases the result is `10`. ## Function-like objects From b173b8925cf94d930ea48661a61661592597e919 Mon Sep 17 00:00:00 2001 From: Mark Van de Vyver Date: Tue, 14 May 2019 12:05:44 +1000 Subject: [PATCH 13/16] Remove alerts. Add issue #9498 and example. Added an example of issue #9498 - since it is not scheduled to be fixed until Julia 2.0. Kept the example of ambiguous/last-seen default code being run because that is the core use case for default values. --- doc/src/manual/methods.md | 48 +++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 50919d0e60d00..1a83543c2e001 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -806,15 +806,21 @@ There are two styles for setting optional agruments (a.k.a default values). Keyword arguments behave differently from ordinary positional arguments. Specifically, they do not participate in method dispatch. - -!!! note Function methods are dispatched based *only* on positional arguments. +Function methods are dispatched based *only* on positional arguments. Keyword arguments are processed after the matching method is identified. -!!! warning A consequence of the above note on dispatch: +However, an existing issue means that function method dispatch behaves differently when +doing a function call with or without keyword arguments. +This issue is currently scheduled to be fixed in Julia 2.0. +See [Issue #9498](https://github.com/JuliaLang/julia/issues/9498) for further details. + +One consequence of keyword arguments not influencing dispatch decisions is that the default +method executed will be the last defined: If a function, say `f`, has a method that uses position based default values and elsewhere in your code you have the same function name with a method defined to use keyword based default values; then the default value returned by `f()` will be the last definition Julia processed. -**There will be no ambiguity warning** +*There will be no ambiguity warning* + ```jldoctest julia> f(a=1,b=2)=5 f (generic function with 3 methods) @@ -825,6 +831,40 @@ f (generic function with 3 methods) julia> f() 10 ``` +An example of [Issue #9498](https://github.com/JuliaLang/julia/issues/9498), which works when methods are defined in one order: + +```jldoctest +julia> bar(x, y; c) = x + y + c +bar (generic function with 1 method) + +julia> bar(x, y) = x / y +bar (generic function with 1 method) + +julia> bar(3,4) +0.75 + +julia> bar(3,4, c=5) +12 +``` + +Yet, throws an error if the code is defined in a different order + +```jldoctest +julia> bar(x, y) = x / y +bar (generic function with 1 method) + +julia> bar(x, y; c) = x + y + c +bar (generic function with 1 method) + +julia> bar(3,4,c=5) +12 + +julia> bar(3,4) +ERROR: UndefKeywordError: keyword argument c not assigned +Stacktrace: + [1] bar(::Int64, ::Int64) at ./REPL[2]:1 + [2] top-level scope at none:0 +``` **Position** based default/optional arguments are implemented as a shorthand for multiple method definitions (this was mentioned briefly in [Functions](@ref man-functions)). From aa189227a9b6ad38cbbb63214ec5589200ad10db Mon Sep 17 00:00:00 2001 From: Mark Van de Vyver Date: Tue, 14 May 2019 12:28:49 +1000 Subject: [PATCH 14/16] Fix referencing --- doc/src/manual/functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/functions.md b/doc/src/manual/functions.md index 1c68f087bbe76..38716232a0fdb 100644 --- a/doc/src/manual/functions.md +++ b/doc/src/manual/functions.md @@ -493,10 +493,10 @@ julia> Date(2000) ``` Optional arguments are actually just a convenient syntax for writing multiple method definitions -with different numbers of arguments (see [Note on Optional and keyword Arguments](@ref)). +with different numbers of arguments (see [Note on Optional and keyword Arguments](@ref man-note-default-arguments)). This can be checked for our `Date` function example by calling `methods` function. -## Keyword Arguments +## Keyword Arguments(@id man-keyword-arguments) Some functions need a large number of arguments, or have a large number of behaviors. Remembering how to call such functions can be difficult. Keyword arguments can make these complex interfaces From b58c8af01c45abce28ebcb8b68433a3c911a3d1b Mon Sep 17 00:00:00 2001 From: Mark Van de Vyver Date: Tue, 14 May 2019 12:32:26 +1000 Subject: [PATCH 15/16] Add references to functions page --- doc/src/manual/methods.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index 1a83543c2e001..ec8247887214c 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -797,14 +797,14 @@ would be called only when the number of `indices` matches the dimensionality of When only the type of supplied arguments needs to be constrained `Vararg{T}` can be equivalently written as `T...`. For instance `f(x::Int...) = x` is a shorthand for `f(x::Vararg{Int}) = x`. -## Note on Optional/Default Positional and Keyword Arguments +## Note on Optional/Default Positional and Keyword Arguments(@id note-default-arguments) There are two styles for setting optional agruments (a.k.a default values). 1. Using position arguments. 1. Using keyword arguments. -Keyword arguments behave differently from ordinary positional arguments. +[Keyword arguments](@ref man-keyword-arguments) behave differently from ordinary positional arguments. Specifically, they do not participate in method dispatch. Function methods are dispatched based *only* on positional arguments. Keyword arguments are processed after the matching method is identified. From edfa26aafff4ddfd12e2b4d9aafdb78ac815c193 Mon Sep 17 00:00:00 2001 From: Mark Van de Vyver Date: Tue, 14 May 2019 12:37:07 +1000 Subject: [PATCH 16/16] Fix id man-note-default-arguments --- doc/src/manual/methods.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/src/manual/methods.md b/doc/src/manual/methods.md index ec8247887214c..a2595136c1d4c 100644 --- a/doc/src/manual/methods.md +++ b/doc/src/manual/methods.md @@ -797,7 +797,7 @@ would be called only when the number of `indices` matches the dimensionality of When only the type of supplied arguments needs to be constrained `Vararg{T}` can be equivalently written as `T...`. For instance `f(x::Int...) = x` is a shorthand for `f(x::Vararg{Int}) = x`. -## Note on Optional/Default Positional and Keyword Arguments(@id note-default-arguments) +## Note on Optional/Default Positional and Keyword Arguments(@id man-note-default-arguments) There are two styles for setting optional agruments (a.k.a default values).