• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #38002

06 Feb 2025 06:14AM UTC coverage: 20.322% (-2.4%) from 22.722%
#38002

push

local

web-flow
bpart: Fully switch to partitioned semantics (#57253)

This is the final PR in the binding partitions series (modulo bugs and
tweaks), i.e. it closes #54654 and thus closes #40399, which was the
original design sketch.

This thus activates the full designed semantics for binding partitions,
in particular allowing safe replacement of const bindings. It in
particular allows struct redefinitions. This thus closes
timholy/Revise.jl#18 and also closes #38584.

The biggest semantic change here is probably that this gets rid of the
notion of "resolvedness" of a binding. Previously, a lot of the behavior
of our implementation depended on when bindings were "resolved", which
could happen at basically an arbitrary point (in the compiler, in REPL
completion, in a different thread), making a lot of the semantics around
bindings ill- or at least implementation-defined. There are several
related issues in the bugtracker, so this closes #14055 closes #44604
closes #46354 closes #30277

It is also the last step to close #24569.
It also supports bindings for undef->defined transitions and thus closes
#53958 closes #54733 - however, this is not activated yet for
performance reasons and may need some further optimization.

Since resolvedness no longer exists, we need to replace it with some
hopefully more well-defined semantics. I will describe the semantics
below, but before I do I will make two notes:

1. There are a number of cases where these semantics will behave
slightly differently than the old semantics absent some other task going
around resolving random bindings.
2. The new behavior (except for the replacement stuff) was generally
permissible under the old semantics if the bindings happened to be
resolved at the right time.

With all that said, there are essentially three "strengths" of bindings:

1. Implicit Bindings: Anything implicitly obtained from `using Mod`, "no
binding", plus slightly more exotic corner cases around conflicts

2. Weakly declared bindin... (continued)

11 of 111 new or added lines in 7 files covered. (9.91%)

1273 existing lines in 68 files now uncovered.

9908 of 48755 relevant lines covered (20.32%)

105126.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

36.04
/base/operators.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
## types ##
4

5
"""
6
    <:(T1, T2)::Bool
7

8
Subtyping relation, defined between two types. In Julia, a type `S` is said to be a
9
*subtype* of a type `T` if and only if we have `S <: T`.
10

11
For any type `L` and any type `R`, `L <: R` implies that any value `v` of type `L`
12
is also of type `R`. I.e., `(L <: R) && (v isa L)` implies `v isa R`.
13

14
The subtyping relation is a *partial order*. I.e., `<:` is:
15

16
* *reflexive*: for any type `T`, `T <: T` holds
17

18
* *antisymmetric*: for any type `A` and any type `B`, `(A <: B) && (B <: A)`
19
  implies `A == B`
20

21
* *transitive*: for any type `A`, any type `B` and any type `C`;
22
  `(A <: B) && (B <: C)` implies `A <: C`
23

24
See also info on [Types](@ref man-types), [`Union{}`](@ref), [`Any`](@ref), [`isa`](@ref).
25

26
# Examples
27
```jldoctest
28
julia> Float64 <: AbstractFloat
29
true
30

31
julia> Vector{Int} <: AbstractArray
32
true
33

34
julia> Matrix{Float64} <: Matrix{AbstractFloat}  # `Matrix` is invariant
35
false
36

37
julia> Tuple{Float64} <: Tuple{AbstractFloat}    # `Tuple` is covariant
38
true
39

40
julia> Union{} <: Int  # The bottom type, `Union{}`, subtypes each type.
41
true
42

43
julia> Union{} <: Float32 <: AbstractFloat <: Real <: Number <: Any  # Operator chaining
44
true
45
```
46

47
The `<:` keyword also has several syntactic uses which represent the same subtyping relation,
48
but which do not execute the operator or return a Bool:
49

50
* To specify the lower bound and the upper bound on a parameter of a
51
  [`UnionAll`](@ref) type in a [`where`](@ref) statement.
52

53
* To specify the lower bound and the upper bound on a (static) parameter of a
54
  method, see [Parametric Methods](@ref).
55

56
* To define a subtyping relation while declaring a new type, see [`struct`](@ref)
57
  and [`abstract type`](@ref).
58
"""
59
(<:)
60

61
import Core: >:
62

63
"""
64
    >:(T1, T2)
65

66
Supertype operator, equivalent to `T2 <: T1`.
67
"""
68
>:
69

70
"""
71
    supertype(T::Union{DataType, UnionAll})
72

73
Return the direct supertype of type `T`.
74
`T` can be a [`DataType`](@ref) or a [`UnionAll`](@ref) type. Does not support
75
type [`Union`](@ref)s. Also see info on [Types](@ref man-types).
76

77
# Examples
78
```jldoctest
79
julia> supertype(Int32)
80
Signed
81

82
julia> supertype(Vector)
83
DenseVector (alias for DenseArray{T, 1} where T)
84
```
85
"""
86
supertype(T::DataType) = (@_total_meta; T.super)
22✔
87
supertype(T::UnionAll) = (@_total_meta; UnionAll(T.var, supertype(T.body)))
×
88

89
## generic comparison ##
90

91
"""
92
    ==(x, y)
93

94
Generic equality operator. Falls back to [`===`](@ref).
95
Should be implemented for all types with a notion of equality, based on the abstract value
96
that an instance represents. For example, all numeric types are compared by numeric value,
97
ignoring type. Strings are compared as sequences of characters, ignoring encoding.
98
Collections of the same type generally compare their key sets, and if those are `==`, then compare the values
99
for each of those keys, returning true if all such pairs are `==`.
100
Other properties are typically not taken into account (such as the exact type).
101

102
This operator follows IEEE semantics for floating-point numbers: `0.0 == -0.0` and
103
`NaN != NaN`.
104

105
The result is of type `Bool`, except when one of the operands is [`missing`](@ref),
106
in which case `missing` is returned
107
([three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic)).
108
Collections generally implement three-valued logic akin to [`all`](@ref), returning
109
missing if any operands contain missing values and all other pairs are equal.
110
Use [`isequal`](@ref) or [`===`](@ref) to always get a `Bool` result.
111

112
# Implementation
113
New numeric types should implement this function for two arguments of the new type, and
114
handle comparison to other types via promotion rules where possible.
115

116
Equality and hashing are intimately related; two values that are considered [`isequal`](@ref) **must**
117
have the same [`hash`](@ref) and by default `isequal` falls back to `==`. If a type customizes the behavior of `==` and/or [`isequal`](@ref),
118
then [`hash`](@ref) must be similarly implemented to ensure `isequal` and `hash` agree. `Set`s, `Dict`s, and many other internal
119
implementations assume that this invariant holds.
120

121
If some type defines `==`, [`isequal`](@ref), and [`isless`](@ref) then it should
122
also implement [`<`](@ref) to ensure consistency of comparisons.
123
"""
124
==
125

126
"""
127
    isequal(x, y) -> Bool
128

129
Similar to [`==`](@ref), except for the treatment of floating point numbers
130
and of missing values. `isequal` treats all floating-point `NaN` values as equal
131
to each other, treats `-0.0` as unequal to `0.0`, and [`missing`](@ref) as equal
132
to `missing`. Always returns a `Bool` value.
133

134
`isequal` is an equivalence relation - it is reflexive (`===` implies `isequal`), symmetric
135
(`isequal(a, b)` implies `isequal(b, a)`) and transitive (`isequal(a, b)` and
136
`isequal(b, c)` implies `isequal(a, c)`).
137

138
# Implementation
139
The default implementation of `isequal` calls `==`, so a type that does not involve
140
floating-point values generally only needs to define `==`.
141

142
`isequal` is the comparison function used by hash tables (`Dict`). `isequal(x,y)` must imply
143
that `hash(x) == hash(y)`.
144

145
This typically means that types for which a custom `==` or `isequal` method exists must
146
implement a corresponding [`hash`](@ref) method (and vice versa). Collections typically
147
implement `isequal` by calling `isequal` recursively on all contents.
148

149
Furthermore, `isequal` is linked with [`isless`](@ref), and they work together to
150
define a fixed total ordering, where exactly one of `isequal(x, y)`, `isless(x, y)`, or
151
`isless(y, x)` must be `true` (and the other two `false`).
152

153
Scalar types generally do not need to implement `isequal` separate from `==`, unless they
154
represent floating-point numbers amenable to a more efficient implementation than that
155
provided as a generic fallback (based on `isnan`, `signbit`, and `==`).
156

157
# Examples
158
```jldoctest
159
julia> isequal([1., NaN], [1., NaN])
160
true
161

162
julia> [1., NaN] == [1., NaN]
163
false
164

165
julia> 0.0 == -0.0
166
true
167

168
julia> isequal(0.0, -0.0)
169
false
170

171
julia> missing == missing
172
missing
173

174
julia> isequal(missing, missing)
175
true
176
```
177
"""
178
isequal(x, y) = (x == y)::Bool # all `missing` cases are handled in missing.jl
337,925✔
179

180
signequal(x, y) = signbit(x)::Bool == signbit(y)::Bool
×
181
signless(x, y) = signbit(x)::Bool & !signbit(y)::Bool
×
182

183
isequal(x::AbstractFloat, y::AbstractFloat) = (isnan(x) & isnan(y)) | signequal(x, y) & (x == y)::Bool
×
184
isequal(x::Real,          y::AbstractFloat) = (isnan(x) & isnan(y)) | signequal(x, y) & (x == y)::Bool
×
185
isequal(x::AbstractFloat, y::Real         ) = (isnan(x) & isnan(y)) | signequal(x, y) & (x == y)::Bool
×
186

187
"""
188
    isless(x, y)
189

190
Test whether `x` is less than `y`, according to a fixed total order (defined together with
191
[`isequal`](@ref)). `isless` is not defined for pairs `(x, y)` of all types. However, if it
192
is defined, it is expected to satisfy the following:
193
- If `isless(x, y)` is defined, then so is `isless(y, x)` and `isequal(x, y)`,
194
  and exactly one of those three yields `true`.
195
- The relation defined by `isless` is transitive, i.e.,
196
  `isless(x, y) && isless(y, z)` implies `isless(x, z)`.
197

198
Values that are normally unordered, such as `NaN`,
199
are ordered after regular values.
200
[`missing`](@ref) values are ordered last.
201

202
This is the default comparison used by [`sort!`](@ref).
203

204
# Implementation
205
Non-numeric types with a total order should implement this function.
206
Numeric types only need to implement it if they have special values such as `NaN`.
207
Types with a partial order should implement [`<`](@ref).
208
See the documentation on [Alternate Orderings](@ref) for how to define alternate
209
ordering methods that can be used in sorting and related functions.
210

211
# Examples
212
```jldoctest
213
julia> isless(1, 3)
214
true
215

216
julia> isless("Red", "Blue")
217
false
218
```
219
"""
220
function isless end
221

222
isless(x::AbstractFloat, y::AbstractFloat) = (!isnan(x) & (isnan(y) | signless(x, y))) | (x < y)
×
223
isless(x::Real,          y::AbstractFloat) = (!isnan(x) & (isnan(y) | signless(x, y))) | (x < y)
×
224
isless(x::AbstractFloat, y::Real         ) = (!isnan(x) & (isnan(y) | signless(x, y))) | (x < y)
×
225

226
# Performance optimization to reduce branching
227
# This is useful for sorting tuples of integers
228
# TODO: remove this when the compiler can optimize the generic version better
229
# See #48724 and #48753
230
isless(a::Tuple{BitInteger, BitInteger}, b::Tuple{BitInteger, BitInteger}) =
×
231
    isless(a[1], b[1]) | (isequal(a[1], b[1]) & isless(a[2], b[2]))
232

233
"""
234
    isgreater(x, y)
235

236
Not the inverse of `isless`! Test whether `x` is greater than `y`, according to
237
a fixed total order compatible with `min`.
238

239
Defined with `isless`, this function is usually `isless(y, x)`, but `NaN` and
240
[`missing`](@ref) are ordered as smaller than any regular value with `missing`
241
smaller than `NaN`.
242

243
So `isless` defines an ascending total order with `NaN` and `missing` as the
244
largest values and `isgreater` defines a descending total order with `NaN` and
245
`missing` as the smallest values.
246

247
!!! note
248

249
    Like `min`, `isgreater` orders containers (tuples, vectors, etc)
250
    lexicographically with `isless(y, x)` rather than recursively with itself:
251

252
    ```jldoctest
253
    julia> Base.isgreater(1, NaN) # 1 is greater than NaN
254
    true
255

256
    julia> Base.isgreater((1,), (NaN,)) # But (1,) is not greater than (NaN,)
257
    false
258

259
    julia> sort([1, 2, 3, NaN]; lt=Base.isgreater)
260
    4-element Vector{Float64}:
261
       3.0
262
       2.0
263
       1.0
264
     NaN
265

266
    julia> sort(tuple.([1, 2, 3, NaN]); lt=Base.isgreater)
267
    4-element Vector{Tuple{Float64}}:
268
     (NaN,)
269
     (3.0,)
270
     (2.0,)
271
     (1.0,)
272
    ```
273

274
# Implementation
275
This is unexported. Types should not usually implement this function. Instead, implement `isless`.
276
"""
277
isgreater(x, y) = isunordered(x) || isunordered(y) ? isless(x, y) : isless(y, x)
×
278

279
"""
280
    isunordered(x)
281

282
Return `true` if `x` is a value that is not orderable according to [`<`](@ref), such as `NaN`
283
or `missing`.
284

285
The values that evaluate to `true` with this predicate may be orderable with respect to other
286
orderings such as [`isless`](@ref).
287

288
!!! compat "Julia 1.7"
289
    This function requires Julia 1.7 or later.
290
"""
291
isunordered(x) = false
×
292
isunordered(x::AbstractFloat) = isnan(x)
×
293
isunordered(x::Missing) = true
×
294

295
==(T::Type, S::Type) = (@_total_meta; ccall(:jl_types_equal, Cint, (Any, Any), T, S) != 0)
6,222✔
296
!=(T::Type, S::Type) = (@_total_meta; !(T == S))
3,524✔
297
==(T::TypeVar, S::Type) = false
×
298
==(T::Type, S::TypeVar) = false
×
299

300
## comparison fallbacks ##
301

302
"""
303
    !=(x, y)
304
    ≠(x,y)
305

306
Not-equals comparison operator. Always gives the opposite answer as [`==`](@ref).
307

308
# Implementation
309
New types should generally not implement this, and rely on the fallback definition
310
`!=(x,y) = !(x==y)` instead.
311

312
# Examples
313
```jldoctest
314
julia> 3 != 2
315
true
316

317
julia> "foo" ≠ "foo"
318
false
319
```
320
"""
321
!=(x, y) = !(x == y)
8,043,050✔
322
const ≠ = !=
323

324
"""
325
    ===(x,y) -> Bool
326
    ≡(x,y) -> Bool
327

328
Determine whether `x` and `y` are identical, in the sense that no program could distinguish
329
them. First the types of `x` and `y` are compared. If those are identical, mutable objects
330
are compared by address in memory and immutable objects (such as numbers) are compared by
331
contents at the bit level. This function is sometimes called "egal".
332
It always returns a `Bool` value.
333

334
# Examples
335
```jldoctest
336
julia> a = [1, 2]; b = [1, 2];
337

338
julia> a == b
339
true
340

341
julia> a === b
342
false
343

344
julia> a === a
345
true
346
```
347
"""
348
===
349
const ≡ = ===
350

351
import Core: !==
352
"""
353
    !==(x, y)
354
    ≢(x,y)
355

356
Always gives the opposite answer as [`===`](@ref).
357

358
# Examples
359
```jldoctest
360
julia> a = [1, 2]; b = [1, 2];
361

362
julia> a ≢ b
363
true
364

365
julia> a ≢ a
366
false
367
```
368
"""
369
!==
370

371
const ≢ = !==
372

373
"""
374
    <(x, y)
375

376
Less-than comparison operator. Falls back to [`isless`](@ref).
377
Because of the behavior of floating-point NaN values, this operator implements
378
a partial order.
379

380
# Implementation
381
New types with a canonical partial order should implement this function for
382
two arguments of the new type.
383
Types with a canonical total order should implement [`isless`](@ref) instead.
384

385
See also [`isunordered`](@ref).
386

387
# Examples
388
```jldoctest
389
julia> 'a' < 'b'
390
true
391

392
julia> "abc" < "abd"
393
true
394

395
julia> 5 < 3
396
false
397
```
398
"""
399
<(x, y) = isless(x, y)
1,924,367✔
400

401
"""
402
    >(x, y)
403

404
Greater-than comparison operator. Falls back to `y < x`.
405

406
# Implementation
407
Generally, new types should implement [`<`](@ref) instead of this function,
408
and rely on the fallback definition `>(x, y) = y < x`.
409

410
# Examples
411
```jldoctest
412
julia> 'a' > 'b'
413
false
414

415
julia> 7 > 3 > 1
416
true
417

418
julia> "abc" > "abd"
419
false
420

421
julia> 5 > 3
422
true
423
```
424
"""
425
>(x, y) = y < x
14,047,910✔
426

427
"""
428
    <=(x, y)
429
    ≤(x,y)
430

431
Less-than-or-equals comparison operator. Falls back to `(x < y) | (x == y)`.
432

433
# Examples
434
```jldoctest
435
julia> 'a' <= 'b'
436
true
437

438
julia> 7 ≤ 7 ≤ 9
439
true
440

441
julia> "abc" ≤ "abc"
442
true
443

444
julia> 5 <= 3
445
false
446
```
447
"""
448
<=(x, y) = (x < y) | (x == y)
2,119,446✔
449
const ≤ = <=
450

451
"""
452
    >=(x, y)
453
    ≥(x,y)
454

455
Greater-than-or-equals comparison operator. Falls back to `y <= x`.
456

457
# Examples
458
```jldoctest
459
julia> 'a' >= 'b'
460
false
461

462
julia> 7 ≥ 7 ≥ 3
463
true
464

465
julia> "abc" ≥ "abc"
466
true
467

468
julia> 5 >= 3
469
true
470
```
471
"""
472
>=(x, y) = (y <= x)
15,996,331✔
473
const ≥ = >=
474

475
# this definition allows Number types to implement < instead of isless,
476
# which is more idiomatic:
477
isless(x::Real, y::Real) = x<y
15,546✔
478

479
"""
480
    cmp(x,y)
481

482
Return -1, 0, or 1 depending on whether `x` is less than, equal to, or greater than `y`,
483
respectively. Uses the total order implemented by `isless`.
484

485
# Examples
486
```jldoctest
487
julia> cmp(1, 2)
488
-1
489

490
julia> cmp(2, 1)
491
1
492

493
julia> cmp(2+im, 3-im)
494
ERROR: MethodError: no method matching isless(::Complex{Int64}, ::Complex{Int64})
495
[...]
496
```
497
"""
498
cmp(x, y) = isless(x, y) ? -1 : ifelse(isless(y, x), 1, 0)
×
499

500
"""
501
    cmp(<, x, y)
502

503
Return -1, 0, or 1 depending on whether `x` is less than, equal to, or greater than `y`,
504
respectively. The first argument specifies a less-than comparison function to use.
505
"""
506
cmp(<, x, y) = (x < y) ? -1 : ifelse(y < x, 1, 0)
×
507

508
# cmp returns -1, 0, +1 indicating ordering
509
cmp(x::Integer, y::Integer) = ifelse(isless(x, y), -1, ifelse(isless(y, x), 1, 0))
91✔
510

511
"""
512
    max(x, y, ...)
513

514
Return the maximum of the arguments, with respect to [`isless`](@ref).
515
If any of the arguments is [`missing`](@ref), return `missing`.
516
See also the [`maximum`](@ref) function to take the maximum element from a collection.
517

518
# Examples
519
```jldoctest
520
julia> max(2, 5, 1)
521
5
522

523
julia> max(5, missing, 6)
524
missing
525
```
526
"""
527
max(x, y) = ifelse(isless(y, x), x, y)
2,845✔
528

529
"""
530
    min(x, y, ...)
531

532
Return the minimum of the arguments, with respect to [`isless`](@ref).
533
If any of the arguments is [`missing`](@ref), return `missing`.
534
See also the [`minimum`](@ref) function to take the minimum element from a collection.
535

536
# Examples
537
```jldoctest
538
julia> min(2, 5, 1)
539
1
540

541
julia> min(4, missing, 6)
542
missing
543
```
544
"""
545
min(x,y) = ifelse(isless(y, x), y, x)
×
546

547
"""
548
    minmax(x, y)
549

550
Return `(min(x,y), max(x,y))`.
551

552
See also [`extrema`](@ref) that returns `(minimum(x), maximum(x))`.
553

554
# Examples
555
```jldoctest
556
julia> minmax('c','b')
557
('b', 'c')
558
```
559
"""
560
minmax(x,y) = isless(y, x) ? (y, x) : (x, y)
×
561

562
## definitions providing basic traits of arithmetic operators ##
563

564
"""
565
    identity(x)
566

567
The identity function. Returns its argument.
568

569
See also: [`one`](@ref), [`oneunit`](@ref), and [`LinearAlgebra`](@ref man-linalg)'s `I`.
570

571
# Examples
572
```jldoctest
573
julia> identity("Well, what did you expect?")
574
"Well, what did you expect?"
575
```
576
"""
577
identity(@nospecialize x) = x
2✔
578

579
+(x::Number) = x
×
580
*(x::Number) = x
×
581
(&)(x::Integer) = x
×
582
(|)(x::Integer) = x
×
583
xor(x::Integer) = x
×
584

585
const ⊻ = xor
586
const ⊼ = nand
587
const ⊽ = nor
588

589
# foldl for argument lists. expand fully up to a point, then
590
# switch to a loop. this allows small cases like `a+b+c+d` to be managed
591
# efficiently, without a major slowdown for `+(x...)` when `x` is big.
592
# n.b.: keep this method count small, so it can be inferred without hitting the
593
# method count limit in inference
594
afoldl(op, a) = a
8,294✔
595
function afoldl(op, a, bs...)
2✔
596
    l = length(bs)
344✔
597
    i =  0; y = a;            l == i && return y
344✔
598
    #@nexprs 31 i -> (y = op(y, bs[i]); l == i && return y)
599
    i =  1; y = op(y, bs[i]); l == i && return y
4,494✔
600
    i =  2; y = op(y, bs[i]); l == i && return y
4,367✔
601
    i =  3; y = op(y, bs[i]); l == i && return y
346✔
602
    i =  4; y = op(y, bs[i]); l == i && return y
4✔
603
    i =  5; y = op(y, bs[i]); l == i && return y
4✔
604
    i =  6; y = op(y, bs[i]); l == i && return y
2✔
605
    i =  7; y = op(y, bs[i]); l == i && return y
2✔
606
    i =  8; y = op(y, bs[i]); l == i && return y
1✔
607
    i =  9; y = op(y, bs[i]); l == i && return y
1✔
608
    i = 10; y = op(y, bs[i]); l == i && return y
1✔
609
    i = 11; y = op(y, bs[i]); l == i && return y
×
610
    i = 12; y = op(y, bs[i]); l == i && return y
×
611
    i = 13; y = op(y, bs[i]); l == i && return y
×
612
    i = 14; y = op(y, bs[i]); l == i && return y
×
613
    i = 15; y = op(y, bs[i]); l == i && return y
×
614
    i = 16; y = op(y, bs[i]); l == i && return y
×
615
    i = 17; y = op(y, bs[i]); l == i && return y
×
616
    i = 18; y = op(y, bs[i]); l == i && return y
×
617
    i = 19; y = op(y, bs[i]); l == i && return y
×
618
    i = 20; y = op(y, bs[i]); l == i && return y
×
619
    i = 21; y = op(y, bs[i]); l == i && return y
×
620
    i = 22; y = op(y, bs[i]); l == i && return y
×
621
    i = 23; y = op(y, bs[i]); l == i && return y
×
622
    i = 24; y = op(y, bs[i]); l == i && return y
×
623
    i = 25; y = op(y, bs[i]); l == i && return y
×
624
    i = 26; y = op(y, bs[i]); l == i && return y
×
625
    i = 27; y = op(y, bs[i]); l == i && return y
×
626
    i = 28; y = op(y, bs[i]); l == i && return y
×
627
    i = 29; y = op(y, bs[i]); l == i && return y
×
628
    i = 30; y = op(y, bs[i]); l == i && return y
×
629
    i = 31; y = op(y, bs[i]); l == i && return y
×
630
    for i in (i + 1):l
×
631
        y = op(y, bs[i])
×
632
    end
×
633
    return y
×
634
end
635
setfield!(typeof(afoldl).name.mt, :max_args, 34, :monotonic)
636

637
for op in (:+, :*, :&, :|, :xor, :min, :max, :kron)
638
    @eval begin
639
        # note: these definitions must not cause a dispatch loop when +(a,b) is
640
        # not defined, and must only try to call 2-argument definitions, so
641
        # that defining +(a,b) is sufficient for full functionality.
642
        ($op)(a, b, c, xs...) = (@inline; afoldl($op, ($op)(($op)(a,b),c), xs...))
1,141,460✔
643
        # a further concern is that it's easy for a type like (Int,Int...)
644
        # to match many definitions, so we need to keep the number of
645
        # definitions down to avoid losing type information.
646
    end
647
end
648

649
function kron! end
650

651
const var"'" = adjoint
652

653
"""
654
    \\(x, y)
655

656
Left division operator: multiplication of `y` by the inverse of `x` on the left. Gives
657
floating-point results for integer arguments.
658

659
# Examples
660
```jldoctest
661
julia> 3 \\ 6
662
2.0
663

664
julia> inv(3) * 6
665
2.0
666

667
julia> A = [4 3; 2 1]; x = [5, 6];
668

669
julia> A \\ x
670
2-element Vector{Float64}:
671
  6.5
672
 -7.0
673

674
julia> inv(A) * x
675
2-element Vector{Float64}:
676
  6.5
677
 -7.0
678
```
679
"""
680
\(x,y) = adjoint(adjoint(y)/adjoint(x))
×
681

682
# Core <<, >>, and >>> take either Int or UInt as second arg. Signed shift
683
# counts can shift in either direction, and are translated here to unsigned
684
# counts. Integer datatypes only need to implement the unsigned version.
685

686
"""
687
    <<(x, n)
688

689
Left bit shift operator, `x << n`. For `n >= 0`, the result is `x` shifted left
690
by `n` bits, filling with `0`s. This is equivalent to `x * 2^n`. For `n < 0`,
691
this is equivalent to `x >> -n`.
692

693
# Examples
694
```jldoctest
695
julia> Int8(3) << 2
696
12
697

698
julia> bitstring(Int8(3))
699
"00000011"
700

701
julia> bitstring(Int8(12))
702
"00001100"
703
```
704
See also [`>>`](@ref), [`>>>`](@ref), [`exp2`](@ref), [`ldexp`](@ref).
705
"""
706
function <<(x::Integer, c::Integer)
×
707
    @inline
×
708
    typemin(Int) <= c <= typemax(Int) && return x << (c % Int)
×
709
    (x >= 0 || c >= 0) && return zero(x) << 0  # for type stability
×
710
    oftype(x, -1)
×
711
end
712
function <<(x::Integer, c::Unsigned)
×
713
    @inline
×
714
    if c isa UInt
×
715
        throw(MethodError(<<, (x, c)))
×
716
    end
717
    c <= typemax(UInt) ? x << (c % UInt) : zero(x) << UInt(0)
×
718
end
UNCOV
719
<<(x::Integer, c::Int) = c >= 0 ? x << unsigned(c) : x >> unsigned(-c)
×
720

721
"""
722
    >>(x, n)
723

724
Right bit shift operator, `x >> n`. For `n >= 0`, the result is `x` shifted
725
right by `n` bits, filling with `0`s if `x >= 0`, `1`s if `x < 0`, preserving
726
the sign of `x`. This is equivalent to `fld(x, 2^n)`. For `n < 0`, this is
727
equivalent to `x << -n`.
728

729
# Examples
730
```jldoctest
731
julia> Int8(13) >> 2
732
3
733

734
julia> bitstring(Int8(13))
735
"00001101"
736

737
julia> bitstring(Int8(3))
738
"00000011"
739

740
julia> Int8(-14) >> 2
741
-4
742

743
julia> bitstring(Int8(-14))
744
"11110010"
745

746
julia> bitstring(Int8(-4))
747
"11111100"
748
```
749
See also [`>>>`](@ref), [`<<`](@ref).
750
"""
751
function >>(x::Integer, c::Integer)
×
752
    @inline
×
753
    if c isa UInt
×
754
        throw(MethodError(>>, (x, c)))
×
755
    end
756
    typemin(Int) <= c <= typemax(Int) && return x >> (c % Int)
×
757
    (x >= 0 || c < 0) && return zero(x) >> 0
×
758
    oftype(x, -1)
×
759
end
760
>>(x::Integer, c::Int) = c >= 0 ? x >> unsigned(c) : x << unsigned(-c)
×
761

762
"""
763
    >>>(x, n)
764

765
Unsigned right bit shift operator, `x >>> n`. For `n >= 0`, the result is `x`
766
shifted right by `n` bits, filling with `0`s. For `n < 0`, this is equivalent
767
to `x << -n`.
768

769
For [`Unsigned`](@ref) integer types, this is equivalent to [`>>`](@ref). For
770
[`Signed`](@ref) integer types, this is equivalent to `signed(unsigned(x) >> n)`.
771

772
# Examples
773
```jldoctest
774
julia> Int8(-14) >>> 2
775
60
776

777
julia> bitstring(Int8(-14))
778
"11110010"
779

780
julia> bitstring(Int8(60))
781
"00111100"
782
```
783

784
[`BigInt`](@ref)s are treated as if having infinite size, so no filling is required and this
785
is equivalent to [`>>`](@ref).
786

787
See also [`>>`](@ref), [`<<`](@ref).
788
"""
789
function >>>(x::Integer, c::Integer)
×
790
    @inline
×
791
    typemin(Int) <= c <= typemax(Int) ? x >>> (c % Int) : zero(x) >>> 0
×
792
end
793
function >>>(x::Integer, c::Unsigned)
×
794
    @inline
×
795
    if c isa UInt
×
796
        throw(MethodError(>>>, (x, c)))
×
797
    end
798
    c <= typemax(UInt) ? x >>> (c % UInt) : zero(x) >>> 0
×
799
end
800
>>>(x::Integer, c::Int) = c >= 0 ? x >>> unsigned(c) : x << unsigned(-c)
×
801

802
# operator alias
803

804
"""
805
    rem(x, y)
806
    %(x, y)
807

808
Remainder from Euclidean division, returning a value of the same sign as `x`, and smaller in
809
magnitude than `y`. This value is always exact.
810

811
See also: [`div`](@ref), [`mod`](@ref), [`mod1`](@ref), [`divrem`](@ref).
812

813
# Examples
814
```jldoctest
815
julia> x = 15; y = 4;
816

817
julia> x % y
818
3
819

820
julia> x == div(x, y) * y + rem(x, y)
821
true
822

823
julia> rem.(-5:5, 3)'
824
1×11 adjoint(::Vector{Int64}) with eltype Int64:
825
 -2  -1  0  -2  -1  0  1  2  0  1  2
826
```
827
"""
828
rem
829
const % = rem
830

831
"""
832
    div(x, y)
833
    ÷(x, y)
834

835
The quotient from Euclidean (integer) division. Generally equivalent
836
to a mathematical operation x/y without a fractional part.
837

838
See also: [`cld`](@ref), [`fld`](@ref), [`rem`](@ref), [`divrem`](@ref).
839

840
# Examples
841
```jldoctest
842
julia> 9 ÷ 4
843
2
844

845
julia> -5 ÷ 3
846
-1
847

848
julia> 5.0 ÷ 2
849
2.0
850

851
julia> div.(-5:5, 3)'
852
1×11 adjoint(::Vector{Int64}) with eltype Int64:
853
 -1  -1  -1  0  0  0  0  0  1  1  1
854
```
855
"""
856
div
857
const ÷ = div
858

859
"""
860
    mod1(x, y)
861

862
Modulus after flooring division, returning a value `r` such that `mod(r, y) == mod(x, y)`
863
in the range ``(0, y]`` for positive `y` and in the range ``[y,0)`` for negative `y`.
864

865
With integer arguments and positive `y`, this is equal to `mod(x, 1:y)`, and hence natural
866
for 1-based indexing. By comparison, `mod(x, y) == mod(x, 0:y-1)` is natural for computations with
867
offsets or strides.
868

869
See also [`mod`](@ref), [`fld1`](@ref), [`fldmod1`](@ref).
870

871
# Examples
872
```jldoctest
873
julia> mod1(4, 2)
874
2
875

876
julia> mod1.(-5:5, 3)'
877
1×11 adjoint(::Vector{Int64}) with eltype Int64:
878
 1  2  3  1  2  3  1  2  3  1  2
879

880
julia> mod1.([-0.1, 0, 0.1, 1, 2, 2.9, 3, 3.1]', 3)
881
1×8 Matrix{Float64}:
882
 2.9  3.0  0.1  1.0  2.0  2.9  3.0  0.1
883
```
884
"""
885
mod1(x::T, y::T) where {T<:Real} = (m = mod(x, y); ifelse(m == 0, y, m))
461✔
886

887

888
"""
889
    fld1(x, y)
890

891
Flooring division, returning a value consistent with `mod1(x,y)`
892

893
See also [`mod1`](@ref), [`fldmod1`](@ref).
894

895
# Examples
896
```jldoctest
897
julia> x = 15; y = 4;
898

899
julia> fld1(x, y)
900
4
901

902
julia> x == fld(x, y) * y + mod(x, y)
903
true
904

905
julia> x == (fld1(x, y) - 1) * y + mod1(x, y)
906
true
907
```
908
"""
909
fld1(x::T, y::T) where {T<:Real} = (m = mod1(x, y); fld((x - m) + y, y))
×
910
function fld1(x::T, y::T) where T<:Integer
×
911
    d = div(x, y)
×
912
    return d + (!signbit(x ⊻ y) & (d * y != x))
×
913
end
914

915
"""
916
    fldmod1(x, y)
917

918
Return `(fld1(x,y), mod1(x,y))`.
919

920
See also [`fld1`](@ref), [`mod1`](@ref).
921
"""
922
fldmod1(x, y) = (fld1(x, y), mod1(x, y))
×
923

924

925
"""
926
    widen(x)
927

928
If `x` is a type, return a "larger" type, defined so that arithmetic operations
929
`+` and `-` are guaranteed not to overflow nor lose precision for any combination
930
of values that type `x` can hold.
931

932
For fixed-size integer types less than 128 bits, `widen` will return a type with
933
twice the number of bits.
934

935
If `x` is a value, it is converted to `widen(typeof(x))`.
936

937
# Examples
938
```jldoctest
939
julia> widen(Int32)
940
Int64
941

942
julia> widen(1.5f0)
943
1.5
944
```
945
"""
946
widen(x::T) where {T} = convert(widen(T), x)
×
947
widen(x::Type{T}) where {T} = throw(MethodError(widen, (T,)))
×
948
widen(x::Type{Union{}}, slurp...) = throw(MethodError(widen, (Union{},)))
×
949

950
# function pipelining
951

952
"""
953
    |>(x, f)
954

955
Infix operator which applies function `f` to the argument `x`.
956
This allows `f(g(x))` to be written `x |> g |> f`.
957
When used with anonymous functions, parentheses are typically required around
958
the definition to get the intended chain.
959

960
# Examples
961
```jldoctest
962
julia> 4 |> inv
963
0.25
964

965
julia> [2, 3, 5] |> sum |> inv
966
0.1
967

968
julia> [0 1; 2 3] .|> (x -> x^2) |> sum
969
14
970
```
971
"""
972
|>(x, f) = f(x)
×
973

974
_stable_typeof(x) = typeof(x)
6✔
975
_stable_typeof(::Type{T}) where {T} = @isdefined(T) ? Type{T} : DataType
×
976

977
"""
978
    f = Returns(value)
979

980
Create a callable `f` such that `f(args...; kw...) === value` holds.
981

982
# Examples
983

984
```jldoctest
985
julia> f = Returns(42);
986

987
julia> f(1)
988
42
989

990
julia> f("hello", x=32)
991
42
992

993
julia> f.value
994
42
995
```
996

997
!!! compat "Julia 1.7"
998
    `Returns` requires at least Julia 1.7.
999
"""
1000
struct Returns{V} <: Function
1001
    value::V
1002
    Returns{V}(value) where {V} = new{V}(value)
×
1003
    Returns(value) = new{_stable_typeof(value)}(value)
727✔
1004
end
1005

1006
(obj::Returns)(@nospecialize(args...); @nospecialize(kw...)) = obj.value
80✔
1007

1008
# function composition
1009

1010
"""
1011
    f ∘ g
1012

1013
Compose functions: i.e. `(f ∘ g)(args...; kwargs...)` means `f(g(args...; kwargs...))`. The `∘` symbol can be
1014
entered in the Julia REPL (and most editors, appropriately configured) by typing `\\circ<tab>`.
1015

1016
Function composition also works in prefix form: `∘(f, g)` is the same as `f ∘ g`.
1017
The prefix form supports composition of multiple functions: `∘(f, g, h) = f ∘ g ∘ h`
1018
and splatting `∘(fs...)` for composing an iterable collection of functions.
1019
The last argument to `∘` execute first.
1020

1021
!!! compat "Julia 1.4"
1022
    Multiple function composition requires at least Julia 1.4.
1023

1024
!!! compat "Julia 1.5"
1025
    Composition of one function ∘(f) requires at least Julia 1.5.
1026

1027
!!! compat "Julia 1.7"
1028
    Using keyword arguments requires at least Julia 1.7.
1029

1030
# Examples
1031
```jldoctest
1032
julia> map(uppercase∘first, ["apple", "banana", "carrot"])
1033
3-element Vector{Char}:
1034
 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
1035
 'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
1036
 'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)
1037

1038
julia> (==(6)∘length).(["apple", "banana", "carrot"])
1039
3-element BitVector:
1040
 0
1041
 1
1042
 1
1043

1044
julia> fs = [
1045
           x -> 2x
1046
           x -> x-1
1047
           x -> x/2
1048
           x -> x+1
1049
       ];
1050

1051
julia> ∘(fs...)(3)
1052
2.0
1053
```
1054
See also [`ComposedFunction`](@ref), [`!f::Function`](@ref).
1055
"""
1056
function ∘ end
1057

1058
"""
1059
    ComposedFunction{Outer,Inner} <: Function
1060

1061
Represents the composition of two callable objects `outer::Outer` and `inner::Inner`. That is
1062
```julia
1063
ComposedFunction(outer, inner)(args...; kw...) === outer(inner(args...; kw...))
1064
```
1065
The preferred way to construct an instance of `ComposedFunction` is to use the composition operator [`∘`](@ref):
1066
```jldoctest
1067
julia> sin ∘ cos === ComposedFunction(sin, cos)
1068
true
1069

1070
julia> typeof(sin∘cos)
1071
ComposedFunction{typeof(sin), typeof(cos)}
1072
```
1073
The composed pieces are stored in the fields of `ComposedFunction` and can be retrieved as follows:
1074
```jldoctest
1075
julia> composition = sin ∘ cos
1076
sin ∘ cos
1077

1078
julia> composition.outer === sin
1079
true
1080

1081
julia> composition.inner === cos
1082
true
1083
```
1084
!!! compat "Julia 1.6"
1085
    ComposedFunction requires at least Julia 1.6. In earlier versions `∘` returns an anonymous function instead.
1086

1087
See also [`∘`](@ref).
1088
"""
1089
struct ComposedFunction{O,I} <: Function
1090
    outer::O
1091
    inner::I
1092
    ComposedFunction{O, I}(outer, inner) where {O, I} = new{O, I}(outer, inner)
×
1093
    ComposedFunction(outer, inner) = new{Core.Typeof(outer),Core.Typeof(inner)}(outer, inner)
85✔
1094
end
1095

1096
(c::ComposedFunction)(x...; kw...) = call_composed(unwrap_composed(c), x, kw)
18,006✔
1097
unwrap_composed(c::ComposedFunction) = (unwrap_composed(c.outer)..., unwrap_composed(c.inner)...)
230✔
1098
unwrap_composed(c) = (maybeconstructor(c),)
5✔
1099
call_composed(fs, x, kw) = (@inline; fs[1](call_composed(tail(fs), x, kw)))
9,003✔
1100
call_composed(fs::Tuple{Any}, x, kw) = fs[1](x...; kw...)
8,988✔
1101

1102
struct Constructor{F} <: Function end
1103
(::Constructor{F})(args...; kw...) where {F} = (@inline; F(args...; kw...))
30✔
1104
maybeconstructor(::Type{F}) where {F} = Constructor{F}()
×
1105
maybeconstructor(f) = f
5✔
1106

1107
∘(f) = f
×
1108
∘(f, g) = ComposedFunction(f, g)
85✔
1109
∘(f, g, h...) = ∘(f ∘ g, h...)
×
1110

1111
function show(io::IO, c::ComposedFunction)
×
1112
    c.outer isa ComposedFunction ? show(io, c.outer) : _showcomposed(io, c.outer)
×
1113
    print(io, " ∘ ")
×
1114
    _showcomposed(io, c.inner)
×
1115
end
1116

1117
#shows !f instead of (!) ∘ f when ! is the outermost function
1118
function show(io::IO, c::ComposedFunction{typeof(!)})
×
1119
    print(io, '!')
×
1120
    _showcomposed(io, c.inner)
×
1121
end
1122

1123
_showcomposed(io::IO, x) = show(io, x)
×
1124
#display operators like + and - inside parens
1125
_showcomposed(io::IO, f::Function) = isoperator(Symbol(f)) ? (print(io, '('); show(io, f); print(io, ')')) : show(io, f)
×
1126
#nesting for chained composition
1127
_showcomposed(io::IO, f::ComposedFunction) = (print(io, '('); show(io, f); print(io, ')'))
×
1128
#no nesting when ! is the outer function in a composition chain
1129
_showcomposed(io::IO, f::ComposedFunction{typeof(!)}) = show(io, f)
×
1130

1131
"""
1132
    !f::Function
1133

1134
Predicate function negation: when the argument of `!` is a function, it returns a composed function which computes the boolean negation of `f`.
1135

1136
See also [`∘`](@ref).
1137

1138
# Examples
1139
```jldoctest
1140
julia> str = "∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε"
1141
"∀ ε > 0, ∃ δ > 0: |x-y| < δ ⇒ |f(x)-f(y)| < ε"
1142

1143
julia> filter(isletter, str)
1144
"εδxyδfxfyε"
1145

1146
julia> filter(!isletter, str)
1147
"∀  > 0, ∃  > 0: |-| <  ⇒ |()-()| < "
1148
```
1149

1150
!!! compat "Julia 1.9"
1151
    Starting with Julia 1.9, `!f` returns a [`ComposedFunction`](@ref) instead of an anonymous function.
1152
"""
1153
!(f::Function) = (!) ∘ f
84✔
1154
!(f::ComposedFunction{typeof(!)}) = f.inner #allows !!f === f
2✔
1155

1156
"""
1157
    Fix{N}(f, x)
1158

1159
A type representing a partially-applied version of a function `f`, with the argument
1160
`x` fixed at position `N::Int`. In other words, `Fix{3}(f, x)` behaves similarly to
1161
`(y1, y2, y3...; kws...) -> f(y1, y2, x, y3...; kws...)`.
1162

1163
!!! compat "Julia 1.12"
1164
    This general functionality requires at least Julia 1.12, while `Fix1` and `Fix2`
1165
    are available earlier.
1166

1167
!!! note
1168
    When nesting multiple `Fix`, note that the `N` in `Fix{N}` is _relative_ to the current
1169
    available arguments, rather than an absolute ordering on the target function. For example,
1170
    `Fix{1}(Fix{2}(f, 4), 4)` fixes the first and second arg, while `Fix{2}(Fix{1}(f, 4), 4)`
1171
    fixes the first and third arg.
1172
"""
1173
struct Fix{N,F,T} <: Function
1174
    f::F
1175
    x::T
1176

1177
    function Fix{N}(f::F, x) where {N,F}
1178
        if !(N isa Int)
6✔
1179
            throw(ArgumentError(LazyString("expected type parameter in `Fix` to be `Int`, but got `", N, "::", typeof(N), "`")))
×
1180
        elseif N < 1
6✔
1181
            throw(ArgumentError(LazyString("expected `N` in `Fix{N}` to be integer greater than 0, but got ", N)))
×
1182
        end
1183
        new{N,_stable_typeof(f),_stable_typeof(x)}(f, x)
271✔
1184
    end
1185
end
1186

1187
function (f::Fix{N})(args::Vararg{Any,M}; kws...) where {N,M}
×
1188
    M < N-1 && throw(ArgumentError(LazyString("expected at least ", N-1, " arguments to `Fix{", N, "}`, but got ", M)))
×
1189
    return f.f(args[begin:begin+(N-2)]..., f.x, args[begin+(N-1):end]...; kws...)
×
1190
end
1191

1192
# Special cases for improved constant propagation
1193
(f::Fix{1})(arg; kws...) = f.f(f.x, arg; kws...)
10✔
1194
(f::Fix{2})(arg; kws...) = f.f(arg, f.x; kws...)
5,602✔
1195

1196
"""
1197
Alias for `Fix{1}`. See [`Fix`](@ref Base.Fix).
1198
"""
1199
const Fix1{F,T} = Fix{1,F,T}
1200

1201
"""
1202
Alias for `Fix{2}`. See [`Fix`](@ref Base.Fix).
1203
"""
1204
const Fix2{F,T} = Fix{2,F,T}
1205

1206

1207
"""
1208
    isequal(x)
1209

1210
Create a function that compares its argument to `x` using [`isequal`](@ref), i.e.
1211
a function equivalent to `y -> isequal(y, x)`.
1212

1213
The returned function is of type `Base.Fix2{typeof(isequal)}`, which can be
1214
used to implement specialized methods.
1215
"""
1216
isequal(x) = Fix2(isequal, x)
95✔
1217

1218
"""
1219
    ==(x)
1220

1221
Create a function that compares its argument to `x` using [`==`](@ref), i.e.
1222
a function equivalent to `y -> y == x`.
1223

1224
The returned function is of type `Base.Fix2{typeof(==)}`, which can be
1225
used to implement specialized methods.
1226
"""
1227
==(x) = Fix2(==, x)
10✔
1228

1229
"""
1230
    !=(x)
1231

1232
Create a function that compares its argument to `x` using [`!=`](@ref), i.e.
1233
a function equivalent to `y -> y != x`.
1234
The returned function is of type `Base.Fix2{typeof(!=)}`, which can be
1235
used to implement specialized methods.
1236

1237
!!! compat "Julia 1.2"
1238
    This functionality requires at least Julia 1.2.
1239
"""
1240
!=(x) = Fix2(!=, x)
29✔
1241

1242
"""
1243
    >=(x)
1244

1245
Create a function that compares its argument to `x` using [`>=`](@ref), i.e.
1246
a function equivalent to `y -> y >= x`.
1247
The returned function is of type `Base.Fix2{typeof(>=)}`, which can be
1248
used to implement specialized methods.
1249

1250
!!! compat "Julia 1.2"
1251
    This functionality requires at least Julia 1.2.
1252
"""
1253
>=(x) = Fix2(>=, x)
×
1254

1255
"""
1256
    <=(x)
1257

1258
Create a function that compares its argument to `x` using [`<=`](@ref), i.e.
1259
a function equivalent to `y -> y <= x`.
1260
The returned function is of type `Base.Fix2{typeof(<=)}`, which can be
1261
used to implement specialized methods.
1262

1263
!!! compat "Julia 1.2"
1264
    This functionality requires at least Julia 1.2.
1265
"""
1266
<=(x) = Fix2(<=, x)
×
1267

1268
"""
1269
    >(x)
1270

1271
Create a function that compares its argument to `x` using [`>`](@ref), i.e.
1272
a function equivalent to `y -> y > x`.
1273
The returned function is of type `Base.Fix2{typeof(>)}`, which can be
1274
used to implement specialized methods.
1275

1276
!!! compat "Julia 1.2"
1277
    This functionality requires at least Julia 1.2.
1278
"""
1279
>(x) = Fix2(>, x)
1✔
1280

1281
"""
1282
    <(x)
1283

1284
Create a function that compares its argument to `x` using [`<`](@ref), i.e.
1285
a function equivalent to `y -> y < x`.
1286
The returned function is of type `Base.Fix2{typeof(<)}`, which can be
1287
used to implement specialized methods.
1288

1289
!!! compat "Julia 1.2"
1290
    This functionality requires at least Julia 1.2.
1291
"""
1292
<(x) = Fix2(<, x)
×
1293

1294
"""
1295
    splat(f)
1296

1297
Equivalent to
1298
```julia
1299
    my_splat(f) = args->f(args...)
1300
```
1301
i.e. given a function returns a new function that takes one argument and splats
1302
it into the original function. This is useful as an adaptor to pass a
1303
multi-argument function in a context that expects a single argument, but passes
1304
a tuple as that single argument.
1305

1306
# Examples
1307
```jldoctest
1308
julia> map(splat(+), zip(1:3,4:6))
1309
3-element Vector{Int64}:
1310
 5
1311
 7
1312
 9
1313

1314
julia> my_add = splat(+)
1315
splat(+)
1316

1317
julia> my_add((1,2,3))
1318
6
1319
```
1320
"""
1321
splat(f) = Splat(f)
×
1322

1323
"""
1324
    Base.Splat{F} <: Function
1325

1326
Represents a splatted function. That is
1327
```julia
1328
Base.Splat(f)(args) === f(args...)
1329
```
1330
The preferred way to construct an instance of `Base.Splat` is to use the [`splat`](@ref) function.
1331

1332
!!! compat "Julia 1.9"
1333
    Splat requires at least Julia 1.9. In earlier versions `splat` returns an anonymous function instead.
1334

1335
See also [`splat`](@ref).
1336
"""
1337
struct Splat{F} <: Function
1338
    f::F
1339
    Splat(f) = new{Core.Typeof(f)}(f)
×
1340
end
1341
(s::Splat)(args) = s.f(args...)
×
1342
show(io::IO, s::Splat) = (print(io, "splat("); show(io, s.f); print(io, ")"))
×
1343

1344
## in and related operators
1345

1346
"""
1347
    in(collection)
1348
    ∈(collection)
1349

1350
Create a function that checks whether its argument is [`in`](@ref) `collection`, i.e.
1351
a function equivalent to `y -> y in collection`. See also [`insorted`](@ref) for use
1352
with sorted collections.
1353

1354
The returned function is of type `Base.Fix2{typeof(in)}`, which can be
1355
used to implement specialized methods.
1356
"""
1357
in(x) = Fix2(in, x)
124✔
1358

1359
function in(x, itr::Any)
252,462✔
1360
    anymissing = false
252,461✔
1361
    for y in itr
383,242✔
1362
        v = (y == x)
3,759,542✔
1363
        if ismissing(v)
3,201,605✔
1364
            anymissing = true
×
1365
        elseif v
3,722,825✔
1366
            return true
17,471✔
1367
        end
1368
    end
3,725,524✔
1369
    return anymissing ? missing : false
365,694✔
1370
end
1371

1372
# Specialized variant of in for Tuple, which can generate typed comparisons for each element
1373
# of the tuple, skipping values that are statically known to be != at compile time.
1374
in(x, itr::Tuple) = _in_tuple(x, itr, false)
6,451,089✔
1375
# This recursive function will be unrolled at compiletime, and will not generate separate
1376
# llvm-compiled specializations for each step of the recursion.
1377
function _in_tuple(x, @nospecialize(itr::Tuple), anymissing::Bool)
1378
    @inline
6,436,973✔
1379
    # Base case
1380
    if isempty(itr)
6,436,973✔
1381
        return anymissing ? missing : false
×
1382
    end
1383
    # Recursive case
1384
    v = (itr[1] == x)
6,457,900✔
1385
    if ismissing(v)
6,436,973✔
1386
        anymissing = true
×
1387
    elseif v
6,457,900✔
1388
        return true
384,064✔
1389
    end
1390
    return _in_tuple(x, tail(itr), anymissing)
6,073,780✔
1391
end
1392

1393
# fallback to the loop implementation after some number of arguments to avoid inference blowup
1394
in(x, itr::Any32) = invoke(in, Tuple{Any,Any}, x, itr)
×
1395

1396
const ∈ = in
1397
∉(x, itr) = !∈(x, itr)
139,954✔
1398
∉(itr) = Fix2(∉, itr)
×
1399

1400
"""
1401
    ∋(collection, item) -> Bool
1402

1403
Like [`in`](@ref), but with arguments in reverse order.
1404
Avoid adding methods to this function; define `in` instead.
1405
"""
1406
∋(itr, x) = in(x, itr)
×
1407

1408
"""
1409
    ∋(item)
1410

1411
Create a function that checks whether its argument contains the given `item`, i.e.
1412
a function equivalent to `y -> item in y`.
1413

1414
!!! compat "Julia 1.6"
1415
    This method requires Julia 1.6 or later.
1416
"""
1417
∋(x) = Fix2(∋, x)
×
1418

1419
∌(itr, x) = !∋(itr, x)
×
1420
∌(x) = Fix2(∌, x)
×
1421

1422
"""
1423
    in(item, collection) -> Bool
1424
    ∈(item, collection) -> Bool
1425

1426
Determine whether an item is in the given collection, in the sense that it is
1427
[`==`](@ref) to one of the values generated by iterating over the collection.
1428
Can equivalently be used with infix syntax:
1429

1430
    item in collection
1431
    item ∈ collection
1432

1433
Return a `Bool` value, except if `item` is [`missing`](@ref) or `collection`
1434
contains `missing` but not `item`, in which case `missing` is returned
1435
([three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic),
1436
matching the behavior of [`any`](@ref) and [`==`](@ref)).
1437
Some collections follow a slightly different definition. For example,
1438
[`Set`](@ref)s check whether the item [`isequal`](@ref) to one of the elements;
1439
[`Dict`](@ref)s look for `key=>value` pairs, and the `key` is compared using
1440
[`isequal`](@ref).
1441

1442
To test for the presence of a key in a dictionary, use [`haskey`](@ref)
1443
or `k in keys(dict)`. For the collections mentioned above,
1444
the result is always a `Bool`.
1445

1446
When broadcasting with `in.(items, collection)` or `items .∈ collection`, both
1447
`items` and `collection` are broadcasted over, which is often not what is intended.
1448
For example, if both arguments are vectors (and the dimensions match), the result is
1449
a vector indicating whether each value in collection `items` is `in` the value at the
1450
corresponding position in `collection`. To get a vector indicating whether each value
1451
in `items` is in `collection`, wrap `collection` in a tuple or a `Ref` like this:
1452
`in.(items, Ref(collection))` or `items .∈ Ref(collection)`.
1453

1454
See also: [`∉`](@ref), [`insorted`](@ref), [`contains`](@ref), [`occursin`](@ref), [`issubset`](@ref).
1455

1456
# Examples
1457
```jldoctest
1458
julia> a = 1:3:20
1459
1:3:19
1460

1461
julia> 4 in a
1462
true
1463

1464
julia> 5 in a
1465
false
1466

1467
julia> missing in [1, 2]
1468
missing
1469

1470
julia> 1 in [2, missing]
1471
missing
1472

1473
julia> 1 in [1, missing]
1474
true
1475

1476
julia> missing in Set([1, 2])
1477
false
1478

1479
julia> (1=>missing) in Dict(1=>10, 2=>20)
1480
missing
1481

1482
julia> [1, 2] .∈ [2, 3]
1483
2-element BitVector:
1484
 0
1485
 0
1486

1487
julia> [1, 2] .∈ ([2, 3],)
1488
2-element BitVector:
1489
 0
1490
 1
1491
```
1492
"""
1493
in
1494

1495
"""
1496
    ∉(item, collection) -> Bool
1497
    ∌(collection, item) -> Bool
1498

1499
Negation of `∈` and `∋`, i.e. checks that `item` is not in `collection`.
1500

1501
When broadcasting with `items .∉ collection`, both `items` and `collection` are
1502
broadcasted over, which is often not what is intended. For example, if both arguments
1503
are vectors (and the dimensions match), the result is a vector indicating whether
1504
each value in collection `items` is not in the value at the corresponding position
1505
in `collection`. To get a vector indicating whether each value in `items` is not in
1506
`collection`, wrap `collection` in a tuple or a `Ref` like this:
1507
`items .∉ Ref(collection)`.
1508

1509
# Examples
1510
```jldoctest
1511
julia> 1 ∉ 2:4
1512
true
1513

1514
julia> 1 ∉ 1:3
1515
false
1516

1517
julia> [1, 2] .∉ [2, 3]
1518
2-element BitVector:
1519
 1
1520
 1
1521

1522
julia> [1, 2] .∉ ([2, 3],)
1523
2-element BitVector:
1524
 1
1525
 0
1526
```
1527
"""
1528
∉, ∌
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc