Line | Exclusive | Inclusive | Code |
---|---|---|---|
1 | # This file is a part of Julia. License is MIT: https://julialang.org/license | ||
2 | |||
3 | import Core: CodeInfo, SimpleVector, donotdelete, compilerbarrier, arrayref | ||
4 | |||
5 | const Callable = Union{Function,Type} | ||
6 | |||
7 | const Bottom = Union{} | ||
8 | |||
9 | # Define minimal array interface here to help code used in macros: | ||
10 | length(a::Array) = arraylen(a) | ||
11 | |||
12 | # This is more complicated than it needs to be in order to get Win64 through bootstrap | ||
13 | 42 (15 %) | 42 (15 %) |
42 (15 %)
samples spent in getindex
eval(:(getindex(A::Array, i1::Int) = arrayref($(Expr(:boundscheck)), A, i1)))
42 (100 %) (ex.), 42 (100 %) (incl.) when called from getindex line 696 |
14 | 1 (0 %) | 1 (0 %) |
1 (0 %)
samples spent in getindex
eval(:(getindex(A::Array, i1::Int, i2::Int, I::Int...) = (@inline; arrayref($(Expr(:boundscheck)), A, i1, i2, I...))))
1 (100 %) (ex.), 1 (100 %) (incl.) when called from brusselator_2d_loop line 49 |
15 | |||
16 | ==(a::GlobalRef, b::GlobalRef) = a.mod === b.mod && a.name === b.name | ||
17 | |||
18 | """ | ||
19 | AbstractSet{T} | ||
20 | |||
21 | Supertype for set-like types whose elements are of type `T`. | ||
22 | [`Set`](@ref), [`BitSet`](@ref) and other types are subtypes of this. | ||
23 | """ | ||
24 | abstract type AbstractSet{T} end | ||
25 | |||
26 | """ | ||
27 | AbstractDict{K, V} | ||
28 | |||
29 | Supertype for dictionary-like types with keys of type `K` and values of type `V`. | ||
30 | [`Dict`](@ref), [`IdDict`](@ref) and other types are subtypes of this. | ||
31 | An `AbstractDict{K, V}` should be an iterator of `Pair{K, V}`. | ||
32 | """ | ||
33 | abstract type AbstractDict{K,V} end | ||
34 | |||
35 | ## optional pretty printer: | ||
36 | #const NamedTuplePair{N, V, names, T<:NTuple{N, Any}} = Pairs{Symbol, V, NTuple{N, Symbol}, NamedTuple{names, T}} | ||
37 | #export NamedTuplePair | ||
38 | |||
39 | macro _gc_preserve_begin(arg1) | ||
40 | Expr(:gc_preserve_begin, esc(arg1)) | ||
41 | end | ||
42 | |||
43 | macro _gc_preserve_end(token) | ||
44 | Expr(:gc_preserve_end, esc(token)) | ||
45 | end | ||
46 | |||
47 | """ | ||
48 | @nospecialize | ||
49 | |||
50 | Applied to a function argument name, hints to the compiler that the method | ||
51 | implementation should not be specialized for different types of that argument, | ||
52 | but instead use the declared type for that argument. | ||
53 | It can be applied to an argument within a formal argument list, | ||
54 | or in the function body. | ||
55 | When applied to an argument, the macro must wrap the entire argument expression, e.g., | ||
56 | `@nospecialize(x::Real)` or `@nospecialize(i::Integer...)` rather than wrapping just the argument name. | ||
57 | When used in a function body, the macro must occur in statement position and | ||
58 | before any code. | ||
59 | |||
60 | When used without arguments, it applies to all arguments of the parent scope. | ||
61 | In local scope, this means all arguments of the containing function. | ||
62 | In global (top-level) scope, this means all methods subsequently defined in the current module. | ||
63 | |||
64 | Specialization can reset back to the default by using [`@specialize`](@ref). | ||
65 | |||
66 | ```julia | ||
67 | function example_function(@nospecialize x) | ||
68 | ... | ||
69 | end | ||
70 | |||
71 | function example_function(x, @nospecialize(y = 1)) | ||
72 | ... | ||
73 | end | ||
74 | |||
75 | function example_function(x, y, z) | ||
76 | @nospecialize x y | ||
77 | ... | ||
78 | end | ||
79 | |||
80 | @nospecialize | ||
81 | f(y) = [x for x in y] | ||
82 | @specialize | ||
83 | ``` | ||
84 | |||
85 | !!! note | ||
86 | `@nospecialize` affects code generation but not inference: it limits the diversity | ||
87 | of the resulting native code, but it does not impose any limitations (beyond the | ||
88 | standard ones) on type-inference. Use [`Base.@nospecializeinfer`](@ref) together with | ||
89 | `@nospecialize` to additionally suppress inference. | ||
90 | |||
91 | # Example | ||
92 | |||
93 | ```julia | ||
94 | julia> f(A::AbstractArray) = g(A) | ||
95 | f (generic function with 1 method) | ||
96 | |||
97 | julia> @noinline g(@nospecialize(A::AbstractArray)) = A[1] | ||
98 | g (generic function with 1 method) | ||
99 | |||
100 | julia> @code_typed f([1.0]) | ||
101 | CodeInfo( | ||
102 | 1 ─ %1 = invoke Main.g(_2::AbstractArray)::Float64 | ||
103 | └── return %1 | ||
104 | ) => Float64 | ||
105 | ``` | ||
106 | |||
107 | Here, the `@nospecialize` annotation results in the equivalent of | ||
108 | |||
109 | ```julia | ||
110 | f(A::AbstractArray) = invoke(g, Tuple{AbstractArray}, A) | ||
111 | ``` | ||
112 | |||
113 | ensuring that only one version of native code will be generated for `g`, | ||
114 | one that is generic for any `AbstractArray`. | ||
115 | However, the specific return type is still inferred for both `g` and `f`, | ||
116 | and this is still used in optimizing the callers of `f` and `g`. | ||
117 | """ | ||
118 | macro nospecialize(vars...) | ||
119 | if nfields(vars) === 1 | ||
120 | # in argument position, need to fix `@nospecialize x=v` to `@nospecialize (kw x v)` | ||
121 | var = getfield(vars, 1) | ||
122 | if isa(var, Expr) && var.head === :(=) | ||
123 | var.head = :kw | ||
124 | end | ||
125 | end | ||
126 | return Expr(:meta, :nospecialize, vars...) | ||
127 | end | ||
128 | |||
129 | """ | ||
130 | @specialize | ||
131 | |||
132 | Reset the specialization hint for an argument back to the default. | ||
133 | For details, see [`@nospecialize`](@ref). | ||
134 | """ | ||
135 | macro specialize(vars...) | ||
136 | if nfields(vars) === 1 | ||
137 | # in argument position, need to fix `@specialize x=v` to `@specialize (kw x v)` | ||
138 | var = getfield(vars, 1) | ||
139 | if isa(var, Expr) && var.head === :(=) | ||
140 | var.head = :kw | ||
141 | end | ||
142 | end | ||
143 | return Expr(:meta, :specialize, vars...) | ||
144 | end | ||
145 | |||
146 | """ | ||
147 | @isdefined s -> Bool | ||
148 | |||
149 | Tests whether variable `s` is defined in the current scope. | ||
150 | |||
151 | See also [`isdefined`](@ref) for field properties and [`isassigned`](@ref) for | ||
152 | array indexes or [`haskey`](@ref) for other mappings. | ||
153 | |||
154 | # Examples | ||
155 | ```jldoctest | ||
156 | julia> @isdefined newvar | ||
157 | false | ||
158 | |||
159 | julia> newvar = 1 | ||
160 | 1 | ||
161 | |||
162 | julia> @isdefined newvar | ||
163 | true | ||
164 | |||
165 | julia> function f() | ||
166 | println(@isdefined x) | ||
167 | x = 3 | ||
168 | println(@isdefined x) | ||
169 | end | ||
170 | f (generic function with 1 method) | ||
171 | |||
172 | julia> f() | ||
173 | false | ||
174 | true | ||
175 | ``` | ||
176 | """ | ||
177 | macro isdefined(s::Symbol) | ||
178 | return Expr(:escape, Expr(:isdefined, s)) | ||
179 | end | ||
180 | |||
181 | """ | ||
182 | nameof(m::Module) -> Symbol | ||
183 | |||
184 | Get the name of a `Module` as a [`Symbol`](@ref). | ||
185 | |||
186 | # Examples | ||
187 | ```jldoctest | ||
188 | julia> nameof(Base.Broadcast) | ||
189 | :Broadcast | ||
190 | ``` | ||
191 | """ | ||
192 | nameof(m::Module) = ccall(:jl_module_name, Ref{Symbol}, (Any,), m) | ||
193 | |||
194 | function _is_internal(__module__) | ||
195 | if ccall(:jl_base_relative_to, Any, (Any,), __module__)::Module === Core.Compiler || | ||
196 | nameof(__module__) === :Base | ||
197 | return true | ||
198 | end | ||
199 | return false | ||
200 | end | ||
201 | |||
202 | # can be used in place of `@assume_effects :total` (supposed to be used for bootstrapping) | ||
203 | macro _total_meta() | ||
204 | return _is_internal(__module__) && Expr(:meta, Expr(:purity, | ||
205 | #=:consistent=#true, | ||
206 | #=:effect_free=#true, | ||
207 | #=:nothrow=#true, | ||
208 | #=:terminates_globally=#true, | ||
209 | #=:terminates_locally=#false, | ||
210 | #=:notaskstate=#true, | ||
211 | #=:inaccessiblememonly=#true)) | ||
212 | end | ||
213 | # can be used in place of `@assume_effects :foldable` (supposed to be used for bootstrapping) | ||
214 | macro _foldable_meta() | ||
215 | return _is_internal(__module__) && Expr(:meta, Expr(:purity, | ||
216 | #=:consistent=#true, | ||
217 | #=:effect_free=#true, | ||
218 | #=:nothrow=#false, | ||
219 | #=:terminates_globally=#true, | ||
220 | #=:terminates_locally=#false, | ||
221 | #=:notaskstate=#false, | ||
222 | #=:inaccessiblememonly=#true)) | ||
223 | end | ||
224 | # can be used in place of `@assume_effects :nothrow` (supposed to be used for bootstrapping) | ||
225 | macro _nothrow_meta() | ||
226 | return _is_internal(__module__) && Expr(:meta, Expr(:purity, | ||
227 | #=:consistent=#false, | ||
228 | #=:effect_free=#false, | ||
229 | #=:nothrow=#true, | ||
230 | #=:terminates_globally=#false, | ||
231 | #=:terminates_locally=#false, | ||
232 | #=:notaskstate=#false, | ||
233 | #=:inaccessiblememonly=#false)) | ||
234 | end | ||
235 | # can be used in place of `@assume_effects :terminates_locally` (supposed to be used for bootstrapping) | ||
236 | macro _terminates_locally_meta() | ||
237 | return _is_internal(__module__) && Expr(:meta, Expr(:purity, | ||
238 | #=:consistent=#false, | ||
239 | #=:effect_free=#false, | ||
240 | #=:nothrow=#false, | ||
241 | #=:terminates_globally=#false, | ||
242 | #=:terminates_locally=#true, | ||
243 | #=:notaskstate=#false, | ||
244 | #=:inaccessiblememonly=#false)) | ||
245 | end | ||
246 | # can be used in place of `@assume_effects :effect_free :terminates_locally` (supposed to be used for bootstrapping) | ||
247 | macro _effect_free_terminates_locally_meta() | ||
248 | return _is_internal(__module__) && Expr(:meta, Expr(:purity, | ||
249 | #=:consistent=#false, | ||
250 | #=:effect_free=#true, | ||
251 | #=:nothrow=#false, | ||
252 | #=:terminates_globally=#false, | ||
253 | #=:terminates_locally=#true, | ||
254 | #=:notaskstate=#false, | ||
255 | #=:inaccessiblememonly=#false)) | ||
256 | end | ||
257 | |||
258 | # another version of inlining that propagates an inbounds context | ||
259 | macro _propagate_inbounds_meta() | ||
260 | return Expr(:meta, :inline, :propagate_inbounds) | ||
261 | end | ||
262 | |||
263 | function iterate end | ||
264 | |||
265 | """ | ||
266 | convert(T, x) | ||
267 | |||
268 | Convert `x` to a value of type `T`. | ||
269 | |||
270 | If `T` is an [`Integer`](@ref) type, an [`InexactError`](@ref) will be raised if `x` | ||
271 | is not representable by `T`, for example if `x` is not integer-valued, or is outside the | ||
272 | range supported by `T`. | ||
273 | |||
274 | # Examples | ||
275 | ```jldoctest | ||
276 | julia> convert(Int, 3.0) | ||
277 | 3 | ||
278 | |||
279 | julia> convert(Int, 3.5) | ||
280 | ERROR: InexactError: Int64(3.5) | ||
281 | Stacktrace: | ||
282 | [...] | ||
283 | ``` | ||
284 | |||
285 | If `T` is a [`AbstractFloat`](@ref) type, | ||
286 | then it will return the closest value to `x` representable by `T`. | ||
287 | |||
288 | ```jldoctest | ||
289 | julia> x = 1/3 | ||
290 | 0.3333333333333333 | ||
291 | |||
292 | julia> convert(Float32, x) | ||
293 | 0.33333334f0 | ||
294 | |||
295 | julia> convert(BigFloat, x) | ||
296 | 0.333333333333333314829616256247390992939472198486328125 | ||
297 | ``` | ||
298 | |||
299 | If `T` is a collection type and `x` a collection, the result of | ||
300 | `convert(T, x)` may alias all or part of `x`. | ||
301 | ```jldoctest | ||
302 | julia> x = Int[1, 2, 3]; | ||
303 | |||
304 | julia> y = convert(Vector{Int}, x); | ||
305 | |||
306 | julia> y === x | ||
307 | true | ||
308 | ``` | ||
309 | |||
310 | See also: [`round`](@ref), [`trunc`](@ref), [`oftype`](@ref), [`reinterpret`](@ref). | ||
311 | """ | ||
312 | function convert end | ||
313 | |||
314 | # ensure this is never ambiguous, and therefore fast for lookup | ||
315 | convert(T::Type{Union{}}, x...) = throw(ArgumentError("cannot convert a value to Union{} for assignment")) | ||
316 | |||
317 | convert(::Type{Type}, x::Type) = x # the ssair optimizer is strongly dependent on this method existing to avoid over-specialization | ||
318 | # in the absence of inlining-enabled | ||
319 | # (due to fields typed as `Type`, which is generally a bad idea) | ||
320 | # These end up being called during bootstrap and then would be invalidated if not for the following: | ||
321 | convert(::Type{String}, x::String) = x | ||
322 | |||
323 | """ | ||
324 | @eval [mod,] ex | ||
325 | |||
326 | Evaluate an expression with values interpolated into it using `eval`. | ||
327 | If two arguments are provided, the first is the module to evaluate in. | ||
328 | """ | ||
329 | macro eval(ex) | ||
330 | return Expr(:escape, Expr(:call, GlobalRef(Core, :eval), __module__, Expr(:quote, ex))) | ||
331 | end | ||
332 | macro eval(mod, ex) | ||
333 | return Expr(:escape, Expr(:call, GlobalRef(Core, :eval), mod, Expr(:quote, ex))) | ||
334 | end | ||
335 | |||
336 | # use `@eval` here to directly form `:new` expressions avoid implicit `convert`s | ||
337 | # in order to achieve better effects inference | ||
338 | @eval struct Pairs{K, V, I, A} <: AbstractDict{K, V} | ||
339 | data::A | ||
340 | itr::I | ||
341 | Pairs{K, V, I, A}(data, itr) where {K, V, I, A} = $(Expr(:new, :(Pairs{K, V, I, A}), :(data isa A ? data : convert(A, data)), :(itr isa I ? itr : convert(I, itr)))) | ||
342 | Pairs{K, V}(data::A, itr::I) where {K, V, I, A} = $(Expr(:new, :(Pairs{K, V, I, A}), :data, :itr)) | ||
343 | Pairs{K}(data::A, itr::I) where {K, I, A} = $(Expr(:new, :(Pairs{K, eltype(A), I, A}), :data, :itr)) | ||
344 | Pairs(data::A, itr::I) where {I, A} = $(Expr(:new, :(Pairs{eltype(I), eltype(A), I, A}), :data, :itr)) | ||
345 | end | ||
346 | pairs(::Type{NamedTuple}) = Pairs{Symbol, V, NTuple{N, Symbol}, NamedTuple{names, T}} where {V, N, names, T<:NTuple{N, Any}} | ||
347 | |||
348 | """ | ||
349 | Iterators.Pairs(values, keys) <: AbstractDict{eltype(keys), eltype(values)} | ||
350 | |||
351 | Transforms an indexable container into a Dictionary-view of the same data. | ||
352 | Modifying the key-space of the underlying data may invalidate this object. | ||
353 | """ | ||
354 | Pairs | ||
355 | |||
356 | argtail(x, rest...) = rest | ||
357 | |||
358 | """ | ||
359 | tail(x::Tuple)::Tuple | ||
360 | |||
361 | Return a `Tuple` consisting of all but the first component of `x`. | ||
362 | |||
363 | See also: [`front`](@ref Base.front), [`rest`](@ref Base.rest), [`first`](@ref), [`Iterators.peel`](@ref). | ||
364 | |||
365 | # Examples | ||
366 | ```jldoctest | ||
367 | julia> Base.tail((1,2,3)) | ||
368 | (2, 3) | ||
369 | |||
370 | julia> Base.tail(()) | ||
371 | ERROR: ArgumentError: Cannot call tail on an empty tuple. | ||
372 | ``` | ||
373 | """ | ||
374 | tail(x::Tuple) = argtail(x...) | ||
375 | tail(::Tuple{}) = throw(ArgumentError("Cannot call tail on an empty tuple.")) | ||
376 | |||
377 | function unwrap_unionall(@nospecialize(a)) | ||
378 | while isa(a,UnionAll) | ||
379 | a = a.body | ||
380 | end | ||
381 | return a | ||
382 | end | ||
383 | |||
384 | function rewrap_unionall(@nospecialize(t), @nospecialize(u)) | ||
385 | if !isa(u, UnionAll) | ||
386 | return t | ||
387 | end | ||
388 | return UnionAll(u.var, rewrap_unionall(t, u.body)) | ||
389 | end | ||
390 | |||
391 | function rewrap_unionall(t::Core.TypeofVararg, @nospecialize(u)) | ||
392 | isdefined(t, :T) || return t | ||
393 | if !isa(u, UnionAll) | ||
394 | return t | ||
395 | end | ||
396 | T = rewrap_unionall(t.T, u) | ||
397 | if !isdefined(t, :N) || t.N === u.var | ||
398 | return Vararg{T} | ||
399 | end | ||
400 | return Vararg{T, t.N} | ||
401 | end | ||
402 | |||
403 | # replace TypeVars in all enclosing UnionAlls with fresh TypeVars | ||
404 | function rename_unionall(@nospecialize(u)) | ||
405 | if !isa(u, UnionAll) | ||
406 | return u | ||
407 | end | ||
408 | var = u.var::TypeVar | ||
409 | body = UnionAll(var, rename_unionall(u.body)) | ||
410 | nv = TypeVar(var.name, var.lb, var.ub) | ||
411 | return UnionAll(nv, body{nv}) | ||
412 | end | ||
413 | |||
414 | function isvarargtype(@nospecialize(t)) | ||
415 | return isa(t, Core.TypeofVararg) | ||
416 | end | ||
417 | |||
418 | function isvatuple(@nospecialize(t)) | ||
419 | t = unwrap_unionall(t) | ||
420 | if isa(t, DataType) | ||
421 | n = length(t.parameters) | ||
422 | return n > 0 && isvarargtype(t.parameters[n]) | ||
423 | end | ||
424 | return false | ||
425 | end | ||
426 | |||
427 | function unwrapva(@nospecialize(t)) | ||
428 | isa(t, Core.TypeofVararg) || return t | ||
429 | return isdefined(t, :T) ? t.T : Any | ||
430 | end | ||
431 | |||
432 | function unconstrain_vararg_length(va::Core.TypeofVararg) | ||
433 | # construct a new Vararg type where its length is unconstrained, | ||
434 | # but its element type still captures any dependencies the input | ||
435 | # element type may have had on the input length | ||
436 | return Vararg{unwrapva(va)} | ||
437 | end | ||
438 | |||
439 | typename(a) = error("typename does not apply to this type") | ||
440 | typename(a::DataType) = a.name | ||
441 | function typename(a::Union) | ||
442 | ta = typename(a.a) | ||
443 | tb = typename(a.b) | ||
444 | ta === tb || error("typename does not apply to unions whose components have different typenames") | ||
445 | return tb | ||
446 | end | ||
447 | typename(union::UnionAll) = typename(union.body) | ||
448 | |||
449 | _tuple_error(T::Type, x) = (@noinline; throw(MethodError(convert, (T, x)))) | ||
450 | |||
451 | convert(::Type{T}, x::T) where {T<:Tuple} = x | ||
452 | function convert(::Type{T}, x::NTuple{N,Any}) where {N, T<:Tuple} | ||
453 | # First see if there could be any conversion of the input type that'd be a subtype of the output. | ||
454 | # If not, we'll throw an explicit MethodError (otherwise, it might throw a typeassert). | ||
455 | if typeintersect(NTuple{N,Any}, T) === Union{} | ||
456 | _tuple_error(T, x) | ||
457 | end | ||
458 | function cvt1(n) | ||
459 | @inline | ||
460 | Tn = fieldtype(T, n) | ||
461 | xn = getfield(x, n, #=boundscheck=#false) | ||
462 | xn isa Tn && return xn | ||
463 | return convert(Tn, xn) | ||
464 | end | ||
465 | return ntuple(cvt1, Val(N))::NTuple{N,Any} | ||
466 | end | ||
467 | |||
468 | # optimizations? | ||
469 | # converting to tuple types of fixed length | ||
470 | #convert(::Type{T}, x::T) where {N, T<:NTuple{N,Any}} = x | ||
471 | #convert(::Type{T}, x::NTuple{N,Any}) where {N, T<:NTuple{N,Any}} = | ||
472 | # ntuple(n -> convert(fieldtype(T, n), x[n]), Val(N)) | ||
473 | #convert(::Type{T}, x::Tuple{Vararg{Any}}) where {N, T<:NTuple{N,Any}} = | ||
474 | # throw(MethodError(convert, (T, x))) | ||
475 | # converting to tuple types of indefinite length | ||
476 | #convert(::Type{Tuple{Vararg{V}}}, x::Tuple{Vararg{V}}) where {V} = x | ||
477 | #convert(::Type{NTuple{N, V}}, x::NTuple{N, V}) where {N, V} = x | ||
478 | #function convert(T::Type{Tuple{Vararg{V}}}, x::Tuple) where {V} | ||
479 | # @isdefined(V) || (V = fieldtype(T, 1)) | ||
480 | # return map(t -> convert(V, t), x) | ||
481 | #end | ||
482 | #function convert(T::Type{NTuple{N, V}}, x::NTuple{N, Any}) where {N, V} | ||
483 | # @isdefined(V) || (V = fieldtype(T, 1)) | ||
484 | # return map(t -> convert(V, t), x) | ||
485 | #end | ||
486 | # short tuples | ||
487 | #convert(::Type{Tuple{}}, ::Tuple{}) = () | ||
488 | #convert(::Type{Tuple{S}}, x::Tuple{S}) where {S} = x | ||
489 | #convert(::Type{Tuple{S, T}}, x::Tuple{S, T}) where {S, T} = x | ||
490 | #convert(::Type{Tuple{S, T, U}}, x::Tuple{S, T, U}) where {S, T, U} = x | ||
491 | #convert(::Type{Tuple{S}}, x::Tuple{Any}) where {S} = (convert(S, x[1]),) | ||
492 | #convert(::Type{Tuple{S, T}}, x::Tuple{Any, Any}) where {S, T} = (convert(S, x[1]), convert(T, x[2]),) | ||
493 | #convert(::Type{Tuple{S, T, U}}, x::Tuple{Any, Any, Any}) where {S, T, U} = (convert(S, x[1]), convert(T, x[2]), convert(U, x[3])) | ||
494 | #convert(::Type{Tuple{}}, x::Tuple) = _tuple_error(Tuple{}, x) | ||
495 | #convert(::Type{Tuple{S}}, x::Tuple) = _tuple_error(Tuple{S}, x) | ||
496 | #convert(::Type{Tuple{S, T}}, x::Tuple{Any, Any}) where {S, T} =_tuple_error(Tuple{S, T}, x) | ||
497 | #convert(::Type{Tuple{S, T, U}}, x::Tuple{Any, Any, Any}) where {S, T, U} = _tuple_error(Tuple{S, T, U}, x) | ||
498 | |||
499 | """ | ||
500 | oftype(x, y) | ||
501 | |||
502 | Convert `y` to the type of `x` i.e. `convert(typeof(x), y)`. | ||
503 | |||
504 | # Examples | ||
505 | ```jldoctest | ||
506 | julia> x = 4; | ||
507 | |||
508 | julia> y = 3.; | ||
509 | |||
510 | julia> oftype(x, y) | ||
511 | 3 | ||
512 | |||
513 | julia> oftype(y, x) | ||
514 | 4.0 | ||
515 | ``` | ||
516 | """ | ||
517 | oftype(x, y) = y isa typeof(x) ? y : convert(typeof(x), y)::typeof(x) | ||
518 | |||
519 | unsigned(x::Int) = reinterpret(UInt, x) | ||
520 | signed(x::UInt) = reinterpret(Int, x) | ||
521 | |||
522 | """ | ||
523 | cconvert(T,x) | ||
524 | |||
525 | Convert `x` to a value to be passed to C code as type `T`, typically by calling `convert(T, x)`. | ||
526 | |||
527 | In cases where `x` cannot be safely converted to `T`, unlike [`convert`](@ref), `cconvert` may | ||
528 | return an object of a type different from `T`, which however is suitable for | ||
529 | [`unsafe_convert`](@ref) to handle. The result of this function should be kept valid (for the GC) | ||
530 | until the result of [`unsafe_convert`](@ref) is not needed anymore. | ||
531 | This can be used to allocate memory that will be accessed by the `ccall`. | ||
532 | If multiple objects need to be allocated, a tuple of the objects can be used as return value. | ||
533 | |||
534 | Neither `convert` nor `cconvert` should take a Julia object and turn it into a `Ptr`. | ||
535 | """ | ||
536 | function cconvert end | ||
537 | |||
538 | cconvert(T::Type, x) = x isa T ? x : convert(T, x) # do the conversion eagerly in most cases | ||
539 | cconvert(::Type{Union{}}, x...) = convert(Union{}, x...) | ||
540 | cconvert(::Type{<:Ptr}, x) = x # but defer the conversion to Ptr to unsafe_convert | ||
541 | unsafe_convert(::Type{T}, x::T) where {T} = x # unsafe_convert (like convert) defaults to assuming the convert occurred | ||
542 | unsafe_convert(::Type{T}, x::T) where {T<:Ptr} = x # to resolve ambiguity with the next method | ||
543 | unsafe_convert(::Type{P}, x::Ptr) where {P<:Ptr} = convert(P, x) | ||
544 | |||
545 | """ | ||
546 | reinterpret(::Type{Out}, x::In) | ||
547 | |||
548 | Change the type-interpretation of the binary data in the isbits value `x` | ||
549 | to that of the isbits type `Out`. | ||
550 | The size (ignoring padding) of `Out` has to be the same as that of the type of `x`. | ||
551 | For example, `reinterpret(Float32, UInt32(7))` interprets the 4 bytes corresponding to `UInt32(7)` as a | ||
552 | [`Float32`](@ref). | ||
553 | |||
554 | ```jldoctest | ||
555 | julia> reinterpret(Float32, UInt32(7)) | ||
556 | 1.0f-44 | ||
557 | |||
558 | julia> reinterpret(NTuple{2, UInt8}, 0x1234) | ||
559 | (0x34, 0x12) | ||
560 | |||
561 | julia> reinterpret(UInt16, (0x34, 0x12)) | ||
562 | 0x1234 | ||
563 | |||
564 | julia> reinterpret(Tuple{UInt16, UInt8}, (0x01, 0x0203)) | ||
565 | (0x0301, 0x02) | ||
566 | ``` | ||
567 | |||
568 | !!! warning | ||
569 | |||
570 | Use caution if some combinations of bits in `Out` are not considered valid and would | ||
571 | otherwise be prevented by the type's constructors and methods. Unexpected behavior | ||
572 | may result without additional validation. | ||
573 | """ | ||
574 | function reinterpret(::Type{Out}, x) where {Out} | ||
575 | if isprimitivetype(Out) && isprimitivetype(typeof(x)) | ||
576 | return bitcast(Out, x) | ||
577 | end | ||
578 | # only available when Base is fully loaded. | ||
579 | return _reinterpret(Out, x) | ||
580 | end | ||
581 | |||
582 | """ | ||
583 | sizeof(T::DataType) | ||
584 | sizeof(obj) | ||
585 | |||
586 | Size, in bytes, of the canonical binary representation of the given `DataType` `T`, if any. | ||
587 | Or the size, in bytes, of object `obj` if it is not a `DataType`. | ||
588 | |||
589 | See also [`Base.summarysize`](@ref). | ||
590 | |||
591 | # Examples | ||
592 | ```jldoctest | ||
593 | julia> sizeof(Float32) | ||
594 | 4 | ||
595 | |||
596 | julia> sizeof(ComplexF64) | ||
597 | 16 | ||
598 | |||
599 | julia> sizeof(1.0) | ||
600 | 8 | ||
601 | |||
602 | julia> sizeof(collect(1.0:10.0)) | ||
603 | 80 | ||
604 | |||
605 | julia> struct StructWithPadding | ||
606 | x::Int64 | ||
607 | flag::Bool | ||
608 | end | ||
609 | |||
610 | julia> sizeof(StructWithPadding) # not the sum of `sizeof` of fields due to padding | ||
611 | 16 | ||
612 | |||
613 | julia> sizeof(Int64) + sizeof(Bool) # different from above | ||
614 | 9 | ||
615 | ``` | ||
616 | |||
617 | If `DataType` `T` does not have a specific size, an error is thrown. | ||
618 | |||
619 | ```jldoctest | ||
620 | julia> sizeof(AbstractArray) | ||
621 | ERROR: Abstract type AbstractArray does not have a definite size. | ||
622 | Stacktrace: | ||
623 | [...] | ||
624 | ``` | ||
625 | """ | ||
626 | sizeof(x) = Core.sizeof(x) | ||
627 | |||
628 | """ | ||
629 | ifelse(condition::Bool, x, y) | ||
630 | |||
631 | Return `x` if `condition` is `true`, otherwise return `y`. This differs from `?` or `if` in | ||
632 | that it is an ordinary function, so all the arguments are evaluated first. In some cases, | ||
633 | using `ifelse` instead of an `if` statement can eliminate the branch in generated code and | ||
634 | provide higher performance in tight loops. | ||
635 | |||
636 | # Examples | ||
637 | ```jldoctest | ||
638 | julia> ifelse(1 > 2, 1, 2) | ||
639 | 2 | ||
640 | ``` | ||
641 | """ | ||
642 | ifelse(condition::Bool, x, y) = Core.ifelse(condition, x, y) | ||
643 | |||
644 | # simple Array{Any} operations needed for bootstrap | ||
645 | @eval setindex!(A::Array{Any}, @nospecialize(x), i::Int) = arrayset($(Expr(:boundscheck)), A, x, i) | ||
646 | |||
647 | """ | ||
648 | esc(e) | ||
649 | |||
650 | Only valid in the context of an [`Expr`](@ref) returned from a macro. Prevents the macro hygiene | ||
651 | pass from turning embedded variables into gensym variables. See the [Macros](@ref man-macros) | ||
652 | section of the Metaprogramming chapter of the manual for more details and examples. | ||
653 | """ | ||
654 | esc(@nospecialize(e)) = Expr(:escape, e) | ||
655 | |||
656 | """ | ||
657 | @boundscheck(blk) | ||
658 | |||
659 | Annotates the expression `blk` as a bounds checking block, allowing it to be elided by [`@inbounds`](@ref). | ||
660 | |||
661 | !!! note | ||
662 | The function in which `@boundscheck` is written must be inlined into | ||
663 | its caller in order for `@inbounds` to have effect. | ||
664 | |||
665 | # Examples | ||
666 | ```jldoctest; filter = r"Stacktrace:(\\n \\[[0-9]+\\].*)*" | ||
667 | julia> @inline function g(A, i) | ||
668 | @boundscheck checkbounds(A, i) | ||
669 | return "accessing (\$A)[\$i]" | ||
670 | end; | ||
671 | |||
672 | julia> f1() = return g(1:2, -1); | ||
673 | |||
674 | julia> f2() = @inbounds return g(1:2, -1); | ||
675 | |||
676 | julia> f1() | ||
677 | ERROR: BoundsError: attempt to access 2-element UnitRange{Int64} at index [-1] | ||
678 | Stacktrace: | ||
679 | [1] throw_boundserror(::UnitRange{Int64}, ::Tuple{Int64}) at ./abstractarray.jl:455 | ||
680 | [2] checkbounds at ./abstractarray.jl:420 [inlined] | ||
681 | [3] g at ./none:2 [inlined] | ||
682 | [4] f1() at ./none:1 | ||
683 | [5] top-level scope | ||
684 | |||
685 | julia> f2() | ||
686 | "accessing (1:2)[-1]" | ||
687 | ``` | ||
688 | |||
689 | !!! warning | ||
690 | |||
691 | The `@boundscheck` annotation allows you, as a library writer, to opt-in to | ||
692 | allowing *other code* to remove your bounds checks with [`@inbounds`](@ref). | ||
693 | As noted there, the caller must verify—using information they can access—that | ||
694 | their accesses are valid before using `@inbounds`. For indexing into your | ||
695 | [`AbstractArray`](@ref) subclasses, for example, this involves checking the | ||
696 | indices against its [`axes`](@ref). Therefore, `@boundscheck` annotations | ||
697 | should only be added to a [`getindex`](@ref) or [`setindex!`](@ref) | ||
698 | implementation after you are certain its behavior is correct. | ||
699 | """ | ||
700 | macro boundscheck(blk) | ||
701 | return Expr(:if, Expr(:boundscheck), esc(blk)) | ||
702 | end | ||
703 | |||
704 | """ | ||
705 | @inbounds(blk) | ||
706 | |||
707 | Eliminates array bounds checking within expressions. | ||
708 | |||
709 | In the example below the in-range check for referencing | ||
710 | element `i` of array `A` is skipped to improve performance. | ||
711 | |||
712 | ```julia | ||
713 | function sum(A::AbstractArray) | ||
714 | r = zero(eltype(A)) | ||
715 | for i in eachindex(A) | ||
716 | @inbounds r += A[i] | ||
717 | end | ||
718 | return r | ||
719 | end | ||
720 | ``` | ||
721 | |||
722 | !!! warning | ||
723 | |||
724 | Using `@inbounds` may return incorrect results/crashes/corruption | ||
725 | for out-of-bounds indices. The user is responsible for checking it manually. | ||
726 | Only use `@inbounds` when it is certain from the information locally available | ||
727 | that all accesses are in bounds. In particular, using `1:length(A)` instead of | ||
728 | `eachindex(A)` in a function like the one above is _not_ safely inbounds because | ||
729 | the first index of `A` may not be `1` for all user defined types that subtype | ||
730 | `AbstractArray`. | ||
731 | """ | ||
732 | macro inbounds(blk) | ||
733 | return Expr(:block, | ||
734 | Expr(:inbounds, true), | ||
735 | Expr(:local, Expr(:(=), :val, esc(blk))), | ||
736 | Expr(:inbounds, :pop), | ||
737 | :val) | ||
738 | end | ||
739 | |||
740 | """ | ||
741 | @label name | ||
742 | |||
743 | Labels a statement with the symbolic label `name`. The label marks the end-point | ||
744 | of an unconditional jump with [`@goto name`](@ref). | ||
745 | """ | ||
746 | macro label(name::Symbol) | ||
747 | return esc(Expr(:symboliclabel, name)) | ||
748 | end | ||
749 | |||
750 | """ | ||
751 | @goto name | ||
752 | |||
753 | `@goto name` unconditionally jumps to the statement at the location [`@label name`](@ref). | ||
754 | |||
755 | `@label` and `@goto` cannot create jumps to different top-level statements. Attempts cause an | ||
756 | error. To still use `@goto`, enclose the `@label` and `@goto` in a block. | ||
757 | """ | ||
758 | macro goto(name::Symbol) | ||
759 | return esc(Expr(:symbolicgoto, name)) | ||
760 | end | ||
761 | |||
762 | # SimpleVector | ||
763 | |||
764 | getindex(v::SimpleVector, i::Int) = (@_foldable_meta; Core._svec_ref(v, i)) | ||
765 | function length(v::SimpleVector) | ||
766 | @_total_meta | ||
767 | t = @_gc_preserve_begin v | ||
768 | len = unsafe_load(Ptr{Int}(pointer_from_objref(v))) | ||
769 | @_gc_preserve_end t | ||
770 | return len | ||
771 | end | ||
772 | firstindex(v::SimpleVector) = 1 | ||
773 | lastindex(v::SimpleVector) = length(v) | ||
774 | iterate(v::SimpleVector, i=1) = (length(v) < i ? nothing : (v[i], i + 1)) | ||
775 | eltype(::Type{SimpleVector}) = Any | ||
776 | keys(v::SimpleVector) = OneTo(length(v)) | ||
777 | isempty(v::SimpleVector) = (length(v) == 0) | ||
778 | axes(v::SimpleVector) = (OneTo(length(v)),) | ||
779 | axes(v::SimpleVector, d::Integer) = d <= 1 ? axes(v)[d] : OneTo(1) | ||
780 | |||
781 | function ==(v1::SimpleVector, v2::SimpleVector) | ||
782 | length(v1)==length(v2) || return false | ||
783 | for i = 1:length(v1) | ||
784 | v1[i] == v2[i] || return false | ||
785 | end | ||
786 | return true | ||
787 | end | ||
788 | |||
789 | map(f, v::SimpleVector) = Any[ f(v[i]) for i = 1:length(v) ] | ||
790 | |||
791 | getindex(v::SimpleVector, I::AbstractArray) = Core.svec(Any[ v[i] for i in I ]...) | ||
792 | |||
793 | unsafe_convert(::Type{Ptr{Any}}, sv::SimpleVector) = convert(Ptr{Any},pointer_from_objref(sv)) + sizeof(Ptr) | ||
794 | |||
795 | """ | ||
796 | isassigned(array, i) -> Bool | ||
797 | |||
798 | Test whether the given array has a value associated with index `i`. Return `false` | ||
799 | if the index is out of bounds, or has an undefined reference. | ||
800 | |||
801 | # Examples | ||
802 | ```jldoctest | ||
803 | julia> isassigned(rand(3, 3), 5) | ||
804 | true | ||
805 | |||
806 | julia> isassigned(rand(3, 3), 3 * 3 + 1) | ||
807 | false | ||
808 | |||
809 | julia> mutable struct Foo end | ||
810 | |||
811 | julia> v = similar(rand(3), Foo) | ||
812 | 3-element Vector{Foo}: | ||
813 | #undef | ||
814 | #undef | ||
815 | #undef | ||
816 | |||
817 | julia> isassigned(v, 1) | ||
818 | false | ||
819 | ``` | ||
820 | """ | ||
821 | function isassigned end | ||
822 | |||
823 | function isassigned(v::SimpleVector, i::Int) | ||
824 | @boundscheck 1 <= i <= length(v) || return false | ||
825 | return true | ||
826 | end | ||
827 | |||
828 | |||
829 | """ | ||
830 | Colon() | ||
831 | |||
832 | Colons (:) are used to signify indexing entire objects or dimensions at once. | ||
833 | |||
834 | Very few operations are defined on Colons directly; instead they are converted | ||
835 | by [`to_indices`](@ref) to an internal vector type (`Base.Slice`) to represent the | ||
836 | collection of indices they span before being used. | ||
837 | |||
838 | The singleton instance of `Colon` is also a function used to construct ranges; | ||
839 | see [`:`](@ref). | ||
840 | """ | ||
841 | struct Colon <: Function | ||
842 | end | ||
843 | const (:) = Colon() | ||
844 | |||
845 | |||
846 | """ | ||
847 | Val(c) | ||
848 | |||
849 | Return `Val{c}()`, which contains no run-time data. Types like this can be used to | ||
850 | pass the information between functions through the value `c`, which must be an `isbits` | ||
851 | value or a `Symbol`. The intent of this construct is to be able to dispatch on constants | ||
852 | directly (at compile time) without having to test the value of the constant at run time. | ||
853 | |||
854 | # Examples | ||
855 | ```jldoctest | ||
856 | julia> f(::Val{true}) = "Good" | ||
857 | f (generic function with 1 method) | ||
858 | |||
859 | julia> f(::Val{false}) = "Bad" | ||
860 | f (generic function with 2 methods) | ||
861 | |||
862 | julia> f(Val(true)) | ||
863 | "Good" | ||
864 | ``` | ||
865 | """ | ||
866 | struct Val{x} | ||
867 | end | ||
868 | |||
869 | Val(x) = Val{x}() | ||
870 | |||
871 | """ | ||
872 | invokelatest(f, args...; kwargs...) | ||
873 | |||
874 | Calls `f(args...; kwargs...)`, but guarantees that the most recent method of `f` | ||
875 | will be executed. This is useful in specialized circumstances, | ||
876 | e.g. long-running event loops or callback functions that may | ||
877 | call obsolete versions of a function `f`. | ||
878 | (The drawback is that `invokelatest` is somewhat slower than calling | ||
879 | `f` directly, and the type of the result cannot be inferred by the compiler.) | ||
880 | |||
881 | !!! compat "Julia 1.9" | ||
882 | Prior to Julia 1.9, this function was not exported, and was called as `Base.invokelatest`. | ||
883 | """ | ||
884 | 544 (200 %) |
816 (300 %)
samples spent in invokelatest
function invokelatest(@nospecialize(f), @nospecialize args...; kwargs...)
272 (33 %) (incl.) when called from #inlineeval#74 line 263 272 (33 %) (incl.) when called from #62 line 34 272 (33 %) (incl.) when called from invokelatest line 884 |
|
885 | kwargs = merge(NamedTuple(), kwargs) | ||
886 | if isempty(kwargs) | ||
887 | 544 (200 %) |
272 (100 %)
samples spent in #invokelatest#2
return Core._call_latest(f, args...)
272 (100 %) (incl.) when called from invokelatest line 884 |
|
888 | end | ||
889 | return Core._call_latest(Core.kwcall, kwargs, f, args...) | ||
890 | end | ||
891 | |||
892 | """ | ||
893 | invoke_in_world(world, f, args...; kwargs...) | ||
894 | |||
895 | Call `f(args...; kwargs...)` in a fixed world age, `world`. | ||
896 | |||
897 | This is useful for infrastructure running in the user's Julia session which is | ||
898 | not part of the user's program. For example, things related to the REPL, editor | ||
899 | support libraries, etc. In these cases it can be useful to prevent unwanted | ||
900 | method invalidation and recompilation latency, and to prevent the user from | ||
901 | breaking supporting infrastructure by mistake. | ||
902 | |||
903 | The current world age can be queried using [`Base.get_world_counter()`](@ref) | ||
904 | and stored for later use within the lifetime of the current Julia session, or | ||
905 | when serializing and reloading the system image. | ||
906 | |||
907 | Technically, `invoke_in_world` will prevent any function called by `f` from | ||
908 | being extended by the user during their Julia session. That is, generic | ||
909 | function method tables seen by `f` (and any functions it calls) will be frozen | ||
910 | as they existed at the given `world` age. In a sense, this is like the opposite | ||
911 | of [`invokelatest`](@ref). | ||
912 | |||
913 | !!! note | ||
914 | It is not valid to store world ages obtained in precompilation for later use. | ||
915 | This is because precompilation generates a "parallel universe" where the | ||
916 | world age refers to system state unrelated to the main Julia session. | ||
917 | """ | ||
918 | function invoke_in_world(world::UInt, @nospecialize(f), @nospecialize args...; kwargs...) | ||
919 | kwargs = Base.merge(NamedTuple(), kwargs) | ||
920 | if isempty(kwargs) | ||
921 | return Core._call_in_world(world, f, args...) | ||
922 | end | ||
923 | return Core._call_in_world(world, Core.kwcall, kwargs, f, args...) | ||
924 | end | ||
925 | |||
926 | inferencebarrier(@nospecialize(x)) = compilerbarrier(:type, x) | ||
927 | |||
928 | """ | ||
929 | isempty(collection) -> Bool | ||
930 | |||
931 | Determine whether a collection is empty (has no elements). | ||
932 | |||
933 | !!! warning | ||
934 | |||
935 | `isempty(itr)` may consume the next element of a stateful iterator `itr` | ||
936 | unless an appropriate `Base.isdone(itr)` or `isempty` method is defined. | ||
937 | Use of `isempty` should therefore be avoided when writing generic | ||
938 | code which should support any iterator type. | ||
939 | |||
940 | # Examples | ||
941 | ```jldoctest | ||
942 | julia> isempty([]) | ||
943 | true | ||
944 | |||
945 | julia> isempty([1 2 3]) | ||
946 | false | ||
947 | ``` | ||
948 | """ | ||
949 | function isempty(itr) | ||
950 | d = isdone(itr) | ||
951 | d !== missing && return d | ||
952 | iterate(itr) === nothing | ||
953 | end | ||
954 | |||
955 | """ | ||
956 | values(iterator) | ||
957 | |||
958 | For an iterator or collection that has keys and values, return an iterator | ||
959 | over the values. | ||
960 | This function simply returns its argument by default, since the elements | ||
961 | of a general iterator are normally considered its "values". | ||
962 | |||
963 | # Examples | ||
964 | ```jldoctest | ||
965 | julia> d = Dict("a"=>1, "b"=>2); | ||
966 | |||
967 | julia> values(d) | ||
968 | ValueIterator for a Dict{String, Int64} with 2 entries. Values: | ||
969 | 2 | ||
970 | 1 | ||
971 | |||
972 | julia> values([2]) | ||
973 | 1-element Vector{Int64}: | ||
974 | 2 | ||
975 | ``` | ||
976 | """ | ||
977 | values(itr) = itr | ||
978 | |||
979 | """ | ||
980 | Missing | ||
981 | |||
982 | A type with no fields whose singleton instance [`missing`](@ref) is used | ||
983 | to represent missing values. | ||
984 | |||
985 | See also: [`skipmissing`](@ref), [`nonmissingtype`](@ref), [`Nothing`](@ref). | ||
986 | """ | ||
987 | struct Missing end | ||
988 | |||
989 | """ | ||
990 | missing | ||
991 | |||
992 | The singleton instance of type [`Missing`](@ref) representing a missing value. | ||
993 | |||
994 | See also: [`NaN`](@ref), [`skipmissing`](@ref), [`nonmissingtype`](@ref). | ||
995 | """ | ||
996 | const missing = Missing() | ||
997 | |||
998 | """ | ||
999 | ismissing(x) | ||
1000 | |||
1001 | Indicate whether `x` is [`missing`](@ref). | ||
1002 | |||
1003 | See also: [`skipmissing`](@ref), [`isnothing`](@ref), [`isnan`](@ref). | ||
1004 | """ | ||
1005 | ismissing(x) = x === missing | ||
1006 | |||
1007 | function popfirst! end | ||
1008 | |||
1009 | """ | ||
1010 | peek(stream[, T=UInt8]) | ||
1011 | |||
1012 | Read and return a value of type `T` from a stream without advancing the current position | ||
1013 | in the stream. See also [`startswith(stream, char_or_string)`](@ref). | ||
1014 | |||
1015 | # Examples | ||
1016 | |||
1017 | ```jldoctest | ||
1018 | julia> b = IOBuffer("julia"); | ||
1019 | |||
1020 | julia> peek(b) | ||
1021 | 0x6a | ||
1022 | |||
1023 | julia> position(b) | ||
1024 | 0 | ||
1025 | |||
1026 | julia> peek(b, Char) | ||
1027 | 'j': ASCII/Unicode U+006A (category Ll: Letter, lowercase) | ||
1028 | ``` | ||
1029 | |||
1030 | !!! compat "Julia 1.5" | ||
1031 | The method which accepts a type requires Julia 1.5 or later. | ||
1032 | """ | ||
1033 | function peek end | ||
1034 | |||
1035 | """ | ||
1036 | @__LINE__ -> Int | ||
1037 | |||
1038 | Expand to the line number of the location of the macrocall. | ||
1039 | Return `0` if the line number could not be determined. | ||
1040 | """ | ||
1041 | macro __LINE__() | ||
1042 | return __source__.line | ||
1043 | end | ||
1044 | |||
1045 | # Iteration | ||
1046 | """ | ||
1047 | isdone(itr, state...) -> Union{Bool, Missing} | ||
1048 | |||
1049 | This function provides a fast-path hint for iterator completion. | ||
1050 | This is useful for mutable iterators that want to avoid having elements | ||
1051 | consumed, if they are not going to be exposed to the user (e.g. to check | ||
1052 | for done-ness in `isempty` or `zip`). Mutable iterators that want to | ||
1053 | opt into this feature should define an isdone method that returns | ||
1054 | true/false depending on whether the iterator is done or not. Stateless | ||
1055 | iterators need not implement this function. If the result is `missing`, | ||
1056 | callers may go ahead and compute `iterate(x, state...) === nothing` to | ||
1057 | compute a definite answer. | ||
1058 | """ | ||
1059 | isdone(itr, state...) = missing | ||
1060 | |||
1061 | """ | ||
1062 | iterate(iter [, state]) -> Union{Nothing, Tuple{Any, Any}} | ||
1063 | |||
1064 | Advance the iterator to obtain the next element. If no elements | ||
1065 | remain, `nothing` should be returned. Otherwise, a 2-tuple of the | ||
1066 | next element and the new iteration state should be returned. | ||
1067 | """ | ||
1068 | function iterate end | ||
1069 | |||
1070 | """ | ||
1071 | isiterable(T) -> Bool | ||
1072 | |||
1073 | Test if type `T` is an iterable collection type or not, | ||
1074 | that is whether it has an `iterate` method or not. | ||
1075 | """ | ||
1076 | function isiterable(T)::Bool | ||
1077 | return hasmethod(iterate, Tuple{T}) | ||
1078 | end |