Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: deprecate * in favor of new ++ concatenation operator #22461

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,19 @@ julia> hcat(c...)
"""
hcat(X...) = cat(Val{2}, X...)

"""
++(X...)

`++` is a generic concatenation operator. By default, it
calls [`vcat`](@ref), concatenating arrays and elements thereof.
For strings and characters, it performs string concatenation.
Similarly, for other types it may perform an appropriate concatenation
operation.
"""
++(X...) = concat(concat_typeof(X...), X...)
concat(::Type{<:Any}, X...) = vcat(X...) # default
concat_rule(::Type{<:AbstractArray}, S) = (@_inline_meta; Array) # arrays should concatenate to arrays

typed_vcat(T::Type, X...) = cat_t(Val{1}, T, X...)
typed_hcat(T::Type, X...) = cat_t(Val{2}, T, X...)

Expand Down
2 changes: 1 addition & 1 deletion base/abstractarraymath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ _rshps(shp, shp_i, sz, ::Tuple{}, o) =
(n = length(shp); N = n + length(sz); _reperr("inner", n, N))
_rshps(shp, shp_i, sz, i, ::Tuple{}) =
(n = length(shp); N = n + length(sz); _reperr("outer", n, N))
_reperr(s, n, N) = throw(ArgumentError("number of " * s * " repetitions " *
_reperr(s, n, N) = throw(ArgumentError("number of " ++ s ++ " repetitions " ++
"($n) cannot be less than number of dimensions of input ($N)"))

@propagate_inbounds function _repeat(A::AbstractArray, inner, outer)
Expand Down
2 changes: 1 addition & 1 deletion base/atomics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ for typ in atomictypes
fn = Symbol("atomic_", rmw, "!")
if (rmw == "max" || rmw == "min") && typ <: Unsigned
# LLVM distinguishes signedness in the operation, not the integer type.
rmw = "u" * rmw
rmw = "u" ++ rmw
end
if typ <: Integer
@eval $fn(x::Atomic{$typ}, v::$typ) =
Expand Down
2 changes: 1 addition & 1 deletion base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ julia> string.(("one","two","three","four"), ": ", 1:4)
"three: 3"
"four: 4"

julia> Nullable("X") .* "Y"
julia> Nullable("X") .++ "Y"
Nullable{String}("XY")

julia> broadcast(/, 1.0, Nullable(2.0))
Expand Down
2 changes: 1 addition & 1 deletion base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ parse_input_line(s::AbstractString) = parse_input_line(String(s))
function parse_input_line(io::IO)
s = ""
while !eof(io)
s *= readline(io, chomp=false)
s = s ++ readline(io, chomp=false)
e = parse_input_line(s)
if !(isa(e,Expr) && e.head === :incomplete)
return e
Expand Down
4 changes: 2 additions & 2 deletions base/dates/periods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ for period in (:Year, :Month, :Week, :Day, :Hour, :Minute, :Second, :Millisecond
period_str = string(period)
accessor_str = lowercase(period_str)
# Convenience method for show()
@eval _units(x::$period) = " " * $accessor_str * (abs(value(x)) == 1 ? "" : "s")
@eval _units(x::$period) = " " ++ $accessor_str ++ (abs(value(x)) == 1 ? "" : "s")
# periodisless
@eval periodisless(x::$period, y::$period) = value(x) < value(y)
# AbstractString parsing (mainly for IO code)
Expand Down Expand Up @@ -334,7 +334,7 @@ function Base.string(x::CompoundPeriod)
else
s = ""
for p in x.periods
s *= ", " * string(p)
s = string(s, ", ", p)
end
return s[3:end]
end
Expand Down
16 changes: 10 additions & 6 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,8 @@ export $

# promote_op method where the operator is also a type
function promote_op(op::Type, Ts::Type...)
depwarn("promote_op(op::Type, ::Type...) is deprecated as it is no " *
"longer needed in Base. If you need its functionality, consider " *
depwarn("promote_op(op::Type, ::Type...) is deprecated as it is no " ++
"longer needed in Base. If you need its functionality, consider " ++
"defining it locally.", :promote_op)
if isdefined(Core, :Inference)
return Core.Inference.return_type(op, Tuple{Ts...})
Expand Down Expand Up @@ -721,8 +721,8 @@ _promote_array_type(::typeof(\), ::Type{<:Integer}, ::Type{Bool}, T::Type) = T
_promote_array_type(F, ::Type{<:Integer}, ::Type{Bool}, T::Type) = T
_promote_array_type{T<:AbstractFloat}(F, ::Type{<:Union{Complex, Real}}, ::Type{Complex{T}}, ::Type) = Complex{T}
function promote_array_type(F, R, S, T)
Base.depwarn("`promote_array_type` is deprecated as it is no longer needed " *
"in Base. See https://github.com/JuliaLang/julia/issues/19669 " *
Base.depwarn("`promote_array_type` is deprecated as it is no longer needed " ++
"in Base. See https://github.com/JuliaLang/julia/issues/19669 " ++
"for more information.", :promote_array_type)
_promote_array_type(F, R, S, T)
end
Expand Down Expand Up @@ -1165,8 +1165,8 @@ end
return func
else
msg = "$f($sig; negate=$negate) is deprecated, use $f("
negate && (msg *= "!")
msg *= "$sig) instead."
negate && (msg = msg ++ "!")
msg = msg ++ "$sig) instead."
Base.depwarn(msg, f)
return negate ? !func : func
end
Expand Down Expand Up @@ -1434,6 +1434,10 @@ module Operators
end
export Operators

# deprecate old string-concatenation ops in favor of ++
@deprecate (*)(s1::AbstractString, ss::AbstractString...) (++)(s1, ss...)
@deprecate (^)(s::AbstractString, r::Integer) repeat(s,r)

# PR #21956
# This mimics the structure as it was defined in Base to avoid directly breaking code
# that assumes this structure
Expand Down
2 changes: 1 addition & 1 deletion base/distributed/cluster.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ function check_worker_state(w::Worker)
wait(w.c_state)
w.state == W_CREATED && error("peer $(w.id) didn't connect to $(myid()) within $timeout seconds")
else
error("peer $(w.id) is not connected to $(myid()). Topology : " * string(PGRP.topology))
error("peer $(w.id) is not connected to $(myid()). Topology : ", PGRP.topology)
end
end
end
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ export
:,
=>,
∘,
++,
A_ldiv_B!,
A_ldiv_Bc,
A_ldiv_Bt,
Expand Down
8 changes: 4 additions & 4 deletions base/interactiveutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ function _show_cpuinfo(io::IO, info::Sys.CPUinfo, header::Bool=true, prefix::Abs
tck = Sys.SC_CLK_TCK
if header
println(io, info.model, ": ")
print(io, " "^length(prefix))
print(io, repeat(" ",length(prefix)))
if tck > 0
@printf(io, " %5s %9s %9s %9s %9s %9s\n",
"speed", "user", "nice", "sys", "idle", "irq")
Expand Down Expand Up @@ -419,8 +419,8 @@ function gen_call_with_extracted_types(__module__, fcn, ex0)
end
if (!is_macro && ex.head == :thunk) || exret.head == :none
exret = Expr(:call, :error, "expression is not a function call, "
* "or is too complex for @$fcn to analyze; "
* "break it down to simpler parts if possible")
++ "or is too complex for @$fcn to analyze; "
++ "break it down to simpler parts if possible")
end
exret
end
Expand Down Expand Up @@ -690,7 +690,7 @@ function runtests(tests = ["all"], numcores = ceil(Int, Sys.CPU_CORES / 2))
catch
buf = PipeBuffer()
versioninfo(buf)
error("A test has failed. Please submit a bug report (https://github.com/JuliaLang/julia/issues)\n" *
error("A test has failed. Please submit a bug report (https://github.com/JuliaLang/julia/issues)\n" ++
"including error messages above and the output of versioninfo():\n$(readstring(buf))")
end
end
Expand Down
4 changes: 2 additions & 2 deletions base/libgit2/callbacks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ function credentials_callback(libgit2credptr::Ptr{Ptr{Void}}, url_ptr::Cstring,

# parse url for schema and host
urlparts = match(URL_REGEX, url)
schema = urlparts[:scheme] === nothing ? "" : urlparts[:scheme] * "://"
schema = urlparts[:scheme] === nothing ? "" : urlparts[:scheme] ++ "://"
urlusername = urlparts[:user] === nothing ? "" : urlparts[:user]
host = urlparts[:host]

Expand Down Expand Up @@ -241,7 +241,7 @@ function credentials_callback(libgit2credptr::Ptr{Ptr{Void}}, url_ptr::Cstring,
# with the remote host.
if err == 0
if explicit
warn("The explicitly provided credentials were incompatible with " *
warn("The explicitly provided credentials were incompatible with ",
"the server's supported authentication methods")
end
err = Cint(Error.EAUTH)
Expand Down
2 changes: 1 addition & 1 deletion base/libgit2/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function prompt(msg::AbstractString; default::AbstractString="", password::Bool=
if is_windows() && password
error("Command line prompt not supported for password entry on windows. Use winprompt instead")
end
msg = !isempty(default) ? msg*" [$default]:" : msg*":"
msg = !isempty(default) ? msg++" [$default]:" : msg++":"
uinput = if password
Base.getpass(msg)
else
Expand Down
2 changes: 1 addition & 1 deletion base/libuv.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ uverrorname(err::UVError) = uverrorname(err.code)

uv_error(prefix::Symbol, c::Integer) = uv_error(string(prefix),c)
uv_error(prefix::AbstractString, c::Integer) = c < 0 ? throw(UVError(prefix,c)) : nothing
show(io::IO, e::UVError) = print(io, e.prefix*": "*struverror(e)*" ("*uverrorname(e)*")")
show(io::IO, e::UVError) = print(io, e.prefix,": ",struverror(e)," (",uverrorname(e),")")

## event loop ##

Expand Down
4 changes: 2 additions & 2 deletions base/linalg/cholesky.jl
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ end

chol!(x::Number, uplo) = ((C, info) = _chol!(x, uplo); @assertposdef C info)

non_hermitian_error(f) = throw(ArgumentError("matrix is not symmetric/" *
"Hermitian. This error can be avoided by calling $f(Hermitian(A)) " *
non_hermitian_error(f) = throw(ArgumentError("matrix is not symmetric/" ++
"Hermitian. This error can be avoided by calling $f(Hermitian(A)) " ++
"which will ignore either the upper or lower triangle of the matrix."))

# chol!. Destructive methods for computing Cholesky factor of real symmetric or Hermitian
Expand Down
2 changes: 1 addition & 1 deletion base/linalg/generic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1058,7 +1058,7 @@ function linreg(x::AbstractVector, y::AbstractVector)
# b = cov(X, Y)/var(X)
# a = mean(Y) - b*mean(X)
if size(x) != size(y)
throw(DimensionMismatch("x has size $(size(x)) and y has size $(size(y)), " *
throw(DimensionMismatch("x has size $(size(x)) and y has size $(size(y)), " ++
"but these must be the same size"))
end
mx = mean(x)
Expand Down
12 changes: 6 additions & 6 deletions base/linalg/triangular.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ getindex(A::UpperTriangular, i::Integer, j::Integer) =

function setindex!(A::UpperTriangular, x, i::Integer, j::Integer)
if i > j
x == 0 || throw(ArgumentError("cannot set index in the lower triangular part " *
x == 0 || throw(ArgumentError("cannot set index in the lower triangular part " ++
"($i, $j) of an UpperTriangular matrix to a nonzero value ($x)"))
else
A.data[i,j] = x
Expand All @@ -140,10 +140,10 @@ end

function setindex!(A::UnitUpperTriangular, x, i::Integer, j::Integer)
if i > j
x == 0 || throw(ArgumentError("cannot set index in the lower triangular part " *
x == 0 || throw(ArgumentError("cannot set index in the lower triangular part " ++
"($i, $j) of a UnitUpperTriangular matrix to a nonzero value ($x)"))
elseif i == j
x == 1 || throw(ArgumentError("cannot set index on the diagonal ($i, $j) " *
x == 1 || throw(ArgumentError("cannot set index on the diagonal ($i, $j) " ++
"of a UnitUpperTriangular matrix to a non-unit value ($x)"))
else
A.data[i,j] = x
Expand All @@ -153,7 +153,7 @@ end

function setindex!(A::LowerTriangular, x, i::Integer, j::Integer)
if i < j
x == 0 || throw(ArgumentError("cannot set index in the upper triangular part " *
x == 0 || throw(ArgumentError("cannot set index in the upper triangular part " ++
"($i, $j) of a LowerTriangular matrix to a nonzero value ($x)"))
else
A.data[i,j] = x
Expand All @@ -163,10 +163,10 @@ end

function setindex!(A::UnitLowerTriangular, x, i::Integer, j::Integer)
if i < j
x == 0 || throw(ArgumentError("cannot set index in the upper triangular part " *
x == 0 || throw(ArgumentError("cannot set index in the upper triangular part " ++
"($i, $j) of a UnitLowerTriangular matrix to a nonzero value ($x)"))
elseif i == j
x == 1 || throw(ArgumentError("cannot set index on the diagonal ($i, $j) " *
x == 1 || throw(ArgumentError("cannot set index on the diagonal ($i, $j) " ++
"of a UnitLowerTriangular matrix to a non-unit value ($x)"))
else
A.data[i,j] = x
Expand Down
6 changes: 3 additions & 3 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ function find_all_in_cache_path(mod::Symbol)
name = string(mod)
paths = String[]
for prefix in LOAD_CACHE_PATH
path = joinpath(prefix, name*".ji")
path = joinpath(prefix, name++".ji")
if isfile_casesensitive(path)
push!(paths, path)
end
Expand Down Expand Up @@ -345,7 +345,7 @@ function require_modname(name::AbstractString)
if endswith(name, ".jl")
tmp = name[1:end-3]
for prefix in LOAD_CACHE_PATH
path = joinpath(prefix, tmp*".ji")
path = joinpath(prefix, tmp++".ji")
if isfile(path)
return tmp
end
Expand Down Expand Up @@ -658,7 +658,7 @@ function compilecache(name::String)
if !isdir(cachepath)
mkpath(cachepath)
end
cachefile::String = abspath(cachepath, name*".ji")
cachefile::String = abspath(cachepath, name++".ji")
# build up the list of modules that we want the precompile process to preserve
concrete_deps = copy(_concrete_dependencies)
for existing in names(Main)
Expand Down
2 changes: 1 addition & 1 deletion base/markdown/Common/block.jl
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ function list(stream::IO, block::MD)
end
else
newline = false
if startswith(stream, " "^indent)
if startswith(stream, repeat(" ",indent))
# Indented text that is part of the current list item.
print(buffer, readline(stream, chomp=false))
else
Expand Down
4 changes: 2 additions & 2 deletions base/markdown/GitHub/GitHub.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ function fencedcode(stream::IO, block::MD)
ch in flavor && return false

buffer = IOBuffer()
chn = repeat(string(ch),n)
while !eof(stream)
line_start = position(stream)
if startswith(stream, string(ch) ^ n)
if startswith(stream, chn)
if !startswith(stream, string(ch))
if flavor == "math"
push!(block, LaTeX(String(take!(buffer)) |> chomp))
Expand Down Expand Up @@ -63,4 +64,3 @@ end

linebreak, escapes, en_dash, inline_code, asterisk_bold,
asterisk_italic, image, footnote_link, link, autolink]

8 changes: 4 additions & 4 deletions base/markdown/GitHub/table.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ function padcells!(rows, align; len = length, min = 0)
for i = 1:length(rows), j = indices(rows[1],1)
cell = rows[i][j]
lpad, rpad = padding(len(cell), widths[j], align[j])
rows[i][j] = " "^lpad * cell * " "^rpad
rows[i][j] = repeat(" ",lpad) ++ cell ++ repeat(" ",rpad)
end
return rows
end

_dash(width, align) =
align == :l ? ":" * "-"^width * " " :
align == :r ? " " * "-"^width * ":" :
align == :c ? ":" * "-"^width * ":" :
align == :l ? ":" ++ repeat("-",width) ++ " " :
align == :r ? " " ++ repeat("-",width) ++ ":" :
align == :c ? ":" ++ repeat("-",width) ++ ":" :
throw(ArgumentError("Invalid alignment $align"))

function plain(io::IO, md::Table)
Expand Down
7 changes: 4 additions & 3 deletions base/markdown/parse/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -179,20 +179,21 @@ function parse_inline_wrapper(stream::IO, delimiter::AbstractString; rep = false
(read(stream, Char) in delimiter) && return nothing
end
n = nmin
startswith(stream, delimiter^n) || return nothing
startswith(stream, repeat(delimiter,n)) || return nothing
while startswith(stream, delimiter); n += 1; end
!rep && n > nmin && return nothing
!eof(stream) && Char(peek(stream)) in whitespace && return nothing

buffer = IOBuffer()
delimitern = repeat(delimiter,n)
while !eof(stream)
char = read(stream, Char)
write(buffer, char)
if !(char in whitespace || char == '\n' || char in delimiter) && startswith(stream, delimiter^n)
if !(char in whitespace || char == '\n' || char in delimiter) && startswith(stream, delimitern)
trailing = 0
while startswith(stream, delimiter); trailing += 1; end
trailing == 0 && return String(take!(buffer))
write(buffer, delimiter ^ (n + trailing))
write(buffer, repeat(delimiter, n + trailing))
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion base/markdown/render/latex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function latex(io::IO, content::Vector)
end

function latex(io::IO, header::Header{l}) where l
tag = l < 4 ? "sub"^(l-1) * "section" : "sub"^(l-4) * "paragraph"
tag = l < 4 ? repeat("sub",l-1) ++ "section" : repeat("sub",l-4) ++ "paragraph"
wrapinline(io, tag) do
latexinline(io, header.text)
end
Expand Down
4 changes: 2 additions & 2 deletions base/markdown/render/plain.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ end
plain(io::IO, md::MD) = plain(io, md.content)

function plain(io::IO, header::Header{l}) where l
print(io, "#"^l*" ")
print(io, repeat("#",l)++" ")
plaininline(io, header.text)
println(io)
end
Expand Down Expand Up @@ -122,7 +122,7 @@ plaininline(io::IO, md::Italic) = plaininline(io, "*", md.text, "*")
function plaininline(io::IO, md::Code)
if contains(md.code, "`")
n = maximum(length(m) for m in matchall(r"(`+)", md.code))
s = "`"^((iseven(n) ? 1 : 2) + n)
s = repeat("`", (iseven(n) ? 1 : 2) + n)
print(io, s, Base.startswith(md.code, "`") ? " " : "")
print(io, md.code, endswith(md.code, "`") ? " " : "", s)
else
Expand Down
2 changes: 1 addition & 1 deletion base/markdown/render/rst.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function rst(io::IO, list::List)
print(io, bullet)
lines = split(rstrip(sprint(rst, item)), '\n')
for (n, line) in enumerate(lines)
print(io, (n == 1 || isempty(line)) ? "" : " "^length(bullet), line)
print(io, (n == 1 || isempty(line)) ? "" : repeat(" ",length(bullet)), line)
n < length(lines) && println(io)
end
println(io)
Expand Down
Loading