## [Reference](#Reference)
"Exports" profiling results in a portable format, returning the set of all backtraces (`data`) and a dictionary that maps the (session-specific) instruction pointers in `data` to `LineInfo` values that store the file name, function name, and line number. This function allows you to save profiling results for future analysis.
```julia
callers(funcname, [data, lidict], [filename=<filename>], [linerange=<start:stop>]) -> Vector{Tuple{count, lineinfo}}
```
Given a previous profiling run, determine who called a particular function. Supplying the filename (and optionally, range of line numbers over which the function is defined) allows you to disambiguate an overloaded method. The returned value is a vector containing a count of the number of calls and line information about the caller. One can optionally supply backtrace `data` obtained from [`retrieve`](#Profile.retrieve); otherwise, the current internal profile buffer is used.
```julia
clear_malloc_data()
```
Clears any stored memory allocation data when running julia with `--track-allocation`. Execute the command(s) you want to test (to force JIT-compilation), then call [`clear_malloc_data`](#Profile.clear_malloc_data). Then execute your command(s) again, quit Julia, and examine the resulting `*.mem` files.
```julia
get_peek_duration()
```
Get the duration in seconds of the profile "peek" that is triggered via `SIGINFO` or `SIGUSR1`, depending on platform.
```julia
set_peek_duration(t::Float64)
```


## [Reference](#Reference)
Set the duration in seconds of the profile "peek" that is triggered via `SIGINFO` or `SIGUSR1`, depending on platform.


## [Memory profiling](#Memory-profiling)
```julia
Profile.Allocs.@profile [sample_rate=0.1] expr
```
Profile allocations that happen during `expr`, returning both the result and and AllocResults struct.
A sample rate of 1.0 will record everything; 0.0 will record nothing.
```julia
julia> Profile.Allocs.@profile sample_rate=0.01 peakflops()
1.03733270279065e11

julia> results = Profile.Allocs.fetch()

julia> last(sort(results.allocs, by=x->x.size))
Profile.Allocs.Alloc(Vector{Any}, Base.StackTraces.StackFrame[_new_array_ at array.c:127, ...], 5576)
```
See the profiling tutorial in the Julia documentation for more information.
Older versions of Julia could not capture types in all cases. In older versions of Julia, if you see an allocation of type `Profile.Allocs.UnknownType`, it means that the profiler doesn't know what type of object was allocated. This mainly happened when the allocation was coming from generated code produced by the compiler. See [issue #43688](https://github.com/JuliaLang/julia/issues/43688) for more info.
Since Julia 1.11, all allocations should have a type reported.
The allocation profiler was added in Julia 1.8.
The methods in `Profile.Allocs` are not exported and need to be called e.g. as `Profile.Allocs.fetch()`.
```julia
Profile.Allocs.clear()
```
Clear all previously profiled allocation information from memory.
```julia
Profile.Allocs.print([io::IO = stdout,] [data::AllocResults = fetch()]; kwargs...)
```


## [Memory profiling](#Memory-profiling)
Prints profiling results to `io` (by default, `stdout`). If you do not supply a `data` vector, the internal buffer of accumulated backtraces will be used.
See `Profile.print` for an explanation of the valid keyword arguments.
```julia
Profile.Allocs.fetch()
```
Retrieve the recorded allocations, and decode them into Julia objects which can be analyzed.
```julia
Profile.Allocs.start(sample_rate::Real)
```
Begin recording allocations with the given sample rate A sample rate of 1.0 will record everything; 0.0 will record nothing.
```julia
Profile.Allocs.stop()
```
Stop recording allocations.


## [Heap Snapshots](#Heap-Snapshots)
```julia
Profile.take_heap_snapshot(filepath::String, all_one::Bool=false, streaming=false)
Profile.take_heap_snapshot(all_one::Bool=false; dir::String, streaming=false)
```
Write a snapshot of the heap, in the JSON format expected by the Chrome Devtools Heap Snapshot viewer (.heapsnapshot extension) to a file (`$pid_$timestamp.heapsnapshot`) in the current directory by default (or tempdir if the current directory is unwritable), or in `dir` if given, or the given full file path, or IO stream.
If `all_one` is true, then report the size of every object as one so they can be easily counted. Otherwise, report the actual size.
If `streaming` is true, we will stream the snapshot data out into four files, using filepath as the prefix, to avoid having to hold the entire snapshot in memory. This option should be used for any setting where your memory is constrained. These files can then be reassembled by calling Profile.HeapSnapshot.assemble_snapshot(), which can be done offline.


## [Heap Snapshots](#Heap-Snapshots)
NOTE: We strongly recommend setting streaming=true for performance reasons. Reconstructing the snapshot from the parts requires holding the entire snapshot in memory, so if the snapshot is large, you can run out of memory while processing it. Streaming allows you to reconstruct the snapshot offline, after your workload is done running. If you do attempt to collect a snapshot with streaming=false (the default, for backwards-compatibility) and your process is killed, note that this will always save the parts in the same directory as your provided filepath, so you can still reconstruct the snapshot after the fact, via `assemble_snapshot()`.
The methods in `Profile` are not exported and need to be called e.g. as `Profile.take_heap_snapshot()`.
```julia-repl
julia> using Profile

julia> Profile.take_heap_snapshot("snapshot.heapsnapshot")
```
Traces and records julia objects on the heap. This only records objects known to the Julia garbage collector. Memory allocated by external libraries not managed by the garbage collector will not show up in the snapshot.
To avoid OOMing while recording the snapshot, we added a streaming option to stream out the heap snapshot into four files,
```julia-repl
julia> using Profile

julia> Profile.take_heap_snapshot("snapshot"; streaming=true)
```
where "snapshot" is the filepath as the prefix for the generated files.
Once the snapshot files are generated, they could be assembled offline with the following command:


## [Heap Snapshots](#Heap-Snapshots)
```julia-repl
julia> using Profile

julia> Profile.HeapSnapshot.assemble_snapshot("snapshot", "snapshot.heapsnapshot")
```
The resulting heap snapshot file can be uploaded to chrome devtools to be viewed. For more information, see the [chrome devtools docs](https://developer.chrome.com/docs/devtools/memory-problems/heap-snapshots/#view_snapshots). An alternative for analyzing Chromium heap snapshots is with the VS Code extension `ms-vscode.vscode-js-profile-flame`.
The Firefox heap snapshots are of a different format, and Firefox currently may *not* be used for viewing the heap snapshots generated by Julia.
------------------------------------------------------------------------


# The Julia REPL · The Julia Language
Source: https://docs.julialang.org/en/v1/stdlib/REPL/


# [The Julia REPL](#The-Julia-REPL)
Julia comes with a full-featured interactive command-line REPL (read-eval-print loop) built into the `julia` executable. In addition to allowing quick and easy evaluation of Julia statements, it has a searchable history, tab-completion, many helpful keybindings, and dedicated help and shell modes. The REPL can be started by simply calling `julia` with no arguments or double-clicking on the executable:
```julia
$ julia

               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.11.6 (2025-07-09)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia>
```
To exit the interactive session, type `^D` – the control key together with the `d` key on a blank line – or type `exit()` followed by the return or enter key. The REPL greets you with a banner and a `julia>` prompt.


## [The different prompt modes](#The-different-prompt-modes)


### [The Julian mode](#The-Julian-mode)
The REPL has five main modes of operation. The first and most common is the Julian prompt. It is the default mode of operation; each new line initially starts with `julia>`. It is here that you can enter Julia expressions. Hitting return or enter after a complete expression has been entered will evaluate the entry and show the result of the last expression.
```julia-repl
julia> string(1 + 2)
"3"
```
There are a number of useful features unique to interactive work. In addition to showing the result, the REPL also binds the result to the variable `ans`. A trailing semicolon on the line can be used as a flag to suppress showing the result.
```julia-repl
julia> string(3 * 4);

julia> ans
"12"
```
In Julia mode, the REPL supports something called *prompt pasting*. This activates when pasting text that starts with `julia>` into the REPL. In that case, only expressions starting with `julia>` (as well as the other REPL mode prompts: `shell>`, `help?>`, `pkg>` ) are parsed, but others are removed. This makes it possible to paste a chunk of text that has been copied from a REPL session without having to scrub away prompts and outputs. This feature is enabled by default but can be disabled or enabled at will with `REPL.enable_promptpaste(::Bool)`. If it is enabled, you can try it out by pasting the code block above this paragraph straight into the REPL. This feature does not work on the standard Windows command prompt due to its limitation at detecting when a paste occurs.


### [The Julian mode](#The-Julian-mode)
Objects are printed at the REPL using the [`show`](../../base/io-network/#Base.show-Tuple%7BIO,%20Any%7D) function with a specific [`IOContext`](../../base/io-network/#Base.IOContext). In particular, the `:limit` attribute is set to `true`. Other attributes can receive in certain `show` methods a default value if it's not already set, like `:compact`. It's possible, as an experimental feature, to specify the attributes used by the REPL via the `Base.active_repl.options.iocontext` dictionary (associating values to attributes). For example:
```julia-repl
julia> rand(2, 2)
2×2 Array{Float64,2}:
 0.8833    0.329197
 0.719708  0.59114

julia> show(IOContext(stdout, :compact => false), "text/plain", rand(2, 2))
 0.43540323669187075  0.15759787870609387
 0.2540832269192739   0.4597637838786053
julia> Base.active_repl.options.iocontext[:compact] = false;

julia> rand(2, 2)
2×2 Array{Float64,2}:
 0.2083967319174056  0.13330606013126012
 0.6244375177790158  0.9777957560761545
```
In order to define automatically the values of this dictionary at startup time, one can use the [`atreplinit`](#Base.atreplinit) function in the `~/.julia/config/startup.jl` file, for example:
```julia
atreplinit() do repl
    repl.options.iocontext[:compact] = false
end
```


### [Help mode](#Help-mode)
When the cursor is at the beginning of the line, the prompt can be changed to a help mode by typing `?`. Julia will attempt to print help or documentation for anything entered in help mode:
```julia-repl
julia> ? # upon typing ?, the prompt changes (in place) to: help?>

help?> string
search: string String Cstring Cwstring RevString randstring bytestring SubString

  string(xs...)

  Create a string from any values using the print function.
```
Macros, types and variables can also be queried:
```julia
help?> @time
  @time

  A macro to execute an expression, printing the time it took to execute, the number of allocations,
  and the total number of bytes its execution caused to be allocated, before returning the value of the
  expression.

  See also @timev, @timed, @elapsed, and @allocated.

help?> Int32
search: Int32 UInt32

  Int32 <: Signed

  32-bit signed integer type.
```
A string or regex literal searches all docstrings using [`apropos`](../InteractiveUtils/#Base.Docs.apropos):
```julia
help?> "aprop"
REPL.stripmd
Base.Docs.apropos

help?> r"ap..p"
Base.:∘
Base.shell_escape_posixly
Distributed.CachingPool
REPL.stripmd
Base.Docs.apropos
```
Another feature of help mode is the ability to access extended docstrings. You can do this by typing something like `??Print` rather than `?Print` which will display the `# Extended help` section from the source codes documentation.
Help mode can be exited by pressing backspace at the beginning of the line.


### [Shell mode](#man-shell-mode)
Just as help mode is useful for quick access to documentation, another common task is to use the system shell to execute system commands. Just as `?` entered help mode when at the beginning of the line, a semicolon (`;`) will enter the shell mode. And it can be exited by pressing backspace at the beginning of the line.
```julia-repl
julia> ; # upon typing ;, the prompt changes (in place) to: shell>

shell> echo hello
hello
```
For Windows users, Julia's shell mode does not expose windows shell commands. Hence, this will fail:
```julia-repl
julia> ; # upon typing ;, the prompt changes (in place) to: shell>

shell> dir
ERROR: IOError: could not spawn `dir`: no such file or directory (ENOENT)
Stacktrace!
.......
```
However, you can get access to `PowerShell` like this:
```julia-repl
julia> ; # upon typing ;, the prompt changes (in place) to: shell>

shell> powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
PS C:\Users\elm>
```
... and to `cmd.exe` like that (see the `dir` command):
```julia-repl
julia> ; # upon typing ;, the prompt changes (in place) to: shell>

shell> cmd
Microsoft Windows [version 10.0.17763.973]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Users\elm>dir
 Volume in drive C has no label
 Volume Serial Number is 1643-0CD7
  Directory of C:\Users\elm

29/01/2020  22:15    <DIR>          .
29/01/2020  22:15    <DIR>          ..
02/02/2020  08:06    <DIR>          .atom
```


### [Pkg mode](#Pkg-mode)
The Package manager mode accepts specialized commands for loading and updating packages. It is entered by pressing the `]` key at the Julian REPL prompt and exited by pressing CTRL-C or pressing the backspace key at the beginning of the line. The prompt for this mode is `pkg>`. It supports its own help-mode, which is entered by pressing `?` at the beginning of the line of the `pkg>` prompt. The Package manager mode is documented in the Pkg manual, available at <https://julialang.github.io/Pkg.jl/v1/>.


### [Search modes](#Search-modes)
In all of the above modes, the executed lines get saved to a history file, which can be searched. To initiate an incremental search through the previous history, type `^R` – the control key together with the `r` key. The prompt will change to `` (reverse-i-search)`': ``, and as you type the search query will appear in the quotes. The most recent result that matches the query will dynamically update to the right of the colon as more is typed. To find an older result using the same query, simply type `^R` again.
Just as `^R` is a reverse search, `^S` is a forward search, with the prompt `` (i-search)`': ``. The two may be used in conjunction with each other to move through the previous or next matching results, respectively.
All executed commands in the Julia REPL are logged into `~/.julia/logs/repl_history.jl` along with a timestamp of when it was executed and the current REPL mode you were in. Search mode queries this log file in order to find the commands which you previously ran. This can be disabled at startup by passing the `--history-file=no` flag to Julia.


## [Key bindings](#Key-bindings)
The Julia REPL makes great use of key bindings. Several control-key bindings were already introduced above (`^D` to exit, `^R` and `^S` for searching), but there are many more. In addition to the control-key, there are also meta-key bindings. These vary more by platform, but most terminals default to using alt- or option- held down with a key to send the meta-key (or can be configured to do so), or pressing Esc and then the key.
| Keybinding           | Description                                                                                |
|:---------------------|:-----------------------------------------------------------------------------------------------------------|
| **Program control**  |                                                                                |
| `^D`                 | Exit (when buffer is empty)                                                                                |
| `^C`                 | Interrupt or cancel                                                                                |
| `^L`                 | Clear console screen                                                                                |
| Return/Enter, `^J`   | New line, executing if it is complete                                                                      |
| meta-Return/Enter    | Insert new line without executing it                                                                       |
| `?` or `;`           | Enter help or shell mode (when at start of a line)                                                         |
| `^R`, `^S`           | Incremental history search, described above                                                                |
| **Cursor movement**  |                                                                                |
| Right arrow, `^F`    | Move right one character                                                                                |
| Left arrow, `^B`     | Move left one character                                                                                |
| ctrl-Right, `meta-F` | Move right one word                                                                                |
| ctrl-Left, `meta-B`  | Move left one word                                                                                |
| Home, `^A`           | Move to beginning of line                                                                                |
| End, `^E`            | Move to end of line                                                                                |
| Up arrow, `^P`       | Move up one line (or change to the previous history entry that matches the text before the cursor)         |
| Down arrow, `^N`     | Move down one line (or change to the next history entry that matches the text before the cursor)           |
| Shift-Arrow Key      | Move cursor according to the direction of the Arrow key, while activating the region ("shift selection")   |
| Page-up, `meta-P`    | Change to the previous history entry                                                                       |
| Page-down, `meta-N`  | Change to the next history entry                                                                           |
| `meta-<`             | Change to the first history entry (of the current session if it is before the current position in history) |
| `meta->`             | Change to the last history entry                                                                           |
| `^-Space`            | Set the "mark" in the editing region (and de-activate the region if it's active)                           |
| `^-Space ^-Space`    | Set the "mark" in the editing region and make the region "active", i.e. highlighted                        |
| `^G`                 | De-activate the region (i.e. make it not highlighted)                                                      |
| `^X^X`               | Exchange the current position with the mark                                                                |
| **Editing**          |                                                                                |
| Backspace, `^H`      | Delete the previous character, or the whole region when it's active                                        |
| Delete, `^D`         | Forward delete one character (when buffer has text)                                                        |
| meta-Backspace       | Delete the previous word                                                                                |
| `meta-d`             | Forward delete the next word                                                                               |
| `^W`                 | Delete previous text up to the nearest whitespace                                                          |
| `meta-w`             | Copy the current region in the kill ring                                                                   |
| `meta-W`             | "Kill" the current region, placing the text in the kill ring                                               |
| `^U`                 | "Kill" to beginning of line, placing the text in the kill ring                                             |
| `^K`                 | "Kill" to end of line, placing the text in the kill ring                                                   |
| `^Y`                 | "Yank" insert the text from the kill ring                                                                  |
| `meta-y`             | Replace a previously yanked text with an older entry from the kill ring                                    |
| `^T`                 | Transpose the characters about the cursor                                                                  |
| `meta-Up arrow`      | Transpose current line with line above                                                                     |
| `meta-Down arrow`    | Transpose current line with line below                                                                     |
| `meta-u`             | Change the next word to uppercase                                                                          |
| `meta-c`             | Change the next word to titlecase                                                                          |
| `meta-l`             | Change the next word to lowercase                                                                          |
| `^/`, `^_`           | Undo previous editing action                                                                               |
| `^Q`                 | Write a number in REPL and press `^Q` to open editor at corresponding stackframe or method                 |
| `meta-Left Arrow`    | Indent the current line on the left                                                                        |
| `meta-Right Arrow`   | Indent the current line on the right                                                                       |
| `meta-.`             | Insert last word from previous history entry                                                               |
| `meta-e`             | Edit the current input in an editor                                                                        |


### [Customizing keybindings](#Customizing-keybindings)
Julia's REPL keybindings may be fully customized to a user's preferences by passing a dictionary to `REPL.setup_interface`. The keys of this dictionary may be characters or strings. The key `'*'` refers to the default action. Control plus character `x` bindings are indicated with `"^x"`. Meta plus `x` can be written `"\\M-x"` or `"\ex"`, and Control plus `x` can be written `"\\C-x"` or `"^x"`. The values of the custom keymap must be `nothing` (indicating that the input should be ignored) or functions that accept the signature `(PromptState, AbstractREPL, Char)`. The `REPL.setup_interface` function must be called before the REPL is initialized, by registering the operation with [`atreplinit`](#Base.atreplinit) . For example, to bind the up and down arrow keys to move through history without prefix search, one could put the following code in `~/.julia/config/startup.jl`:
```julia
import REPL
import REPL.LineEdit

const mykeys = Dict{Any,Any}(
    # Up Arrow
    "\e[A" => (s,o...)->(LineEdit.edit_move_up(s) || LineEdit.history_prev(s, LineEdit.mode(s).hist)),
    # Down Arrow
    "\e[B" => (s,o...)->(LineEdit.edit_move_down(s) || LineEdit.history_next(s, LineEdit.mode(s).hist))
)

function customize_keys(repl)
    repl.interface = REPL.setup_interface(repl; extra_repl_keymap = mykeys)
end

atreplinit(customize_keys)
```
Users should refer to `LineEdit.jl` to discover the available actions on key input.


## [Tab completion](#Tab-completion)
In the Julian, pkg and help modes of the REPL, one can enter the first few characters of a function or type and then press the tab key to get a list all matches:
```julia-repl
julia> x[TAB]
julia> xor
```
In some cases it only completes part of the name, up to the next ambiguity:
```julia-repl
julia> mapf[TAB]
julia> mapfold
```
If you hit tab again, then you get the list of things that might complete this:
```julia-repl
julia> mapfold[TAB]
mapfoldl mapfoldr
```
When a single complete tab-complete result is available at the end of an input line and 2 or more characters have been typed, a hint of the completion will show in a lighter color. This can be disabled via `Base.active_repl.options.hint_tab_completes = false` or by adding
```julia
atreplinit() do repl
    if VERSION >= v"1.11.0-0"
        repl.options.hint_tab_completes = false
    end
end
```
to your `~/.julia/config/startup.jl`.
Tab-complete hinting was added in Julia 1.11
Like other components of the REPL, the search is case-sensitive:
```julia-repl
julia> stri[TAB]
stride     strides     string      strip

julia> Stri[TAB]
StridedArray    StridedMatrix    StridedVecOrMat  StridedVector    String
```
The tab key can also be used to substitute LaTeX math symbols with their Unicode equivalents, and get a list of LaTeX matches as well:


## [Tab completion](#Tab-completion)
```julia-repl
julia> \pi[TAB]
julia> π
π = 3.1415926535897...

julia> e\_1[TAB] = [1,0]
julia> e₁ = [1,0]
2-element Array{Int64,1}:
 1
 0

julia> e\^1[TAB] = [1 0]
julia> e¹ = [1 0]
1×2 Array{Int64,2}:
 1  0

julia> \sqrt[TAB]2     # √ is equivalent to the sqrt function
julia> √2
1.4142135623730951

julia> \hbar[TAB](h) = h / 2\pi[TAB]
julia> ħ(h) = h / 2π
ħ (generic function with 1 method)

julia> \h[TAB]
\hat              \hermitconjmatrix  \hkswarow          \hrectangle
\hatapprox        \hexagon           \hookleftarrow     \hrectangleblack
\hbar             \hexagonblack      \hookrightarrow    \hslash
\heartsuit        \hksearow          \house             \hspace

julia> α="\alpha[TAB]"   # LaTeX completion also works in strings
julia> α="α"
```
A full list of tab-completions can be found in the [Unicode Input](../../manual/unicode-input/#Unicode-Input) section of the manual.
Completion of paths works for strings and julia's shell mode:
```julia-repl
julia> path="/[TAB]"
.dockerenv  .juliabox/   boot/        etc/         lib/         media/       opt/         root/        sbin/        sys/         usr/
.dockerinit bin/         dev/         home/        lib64/       mnt/         proc/        run/         srv/         tmp/         var/
shell> /[TAB]
.dockerenv  .juliabox/   boot/        etc/         lib/         media/       opt/         root/        sbin/        sys/         usr/
.dockerinit bin/         dev/         home/        lib64/       mnt/         proc/        run/         srv/         tmp/         var/
```


## [Tab completion](#Tab-completion)
Dictionary keys can also be tab completed:
```julia-repl
julia> foo = Dict("qwer1"=>1, "qwer2"=>2, "asdf"=>3)
Dict{String,Int64} with 3 entries:
  "qwer2" => 2
  "asdf"  => 3
  "qwer1" => 1

julia> foo["q[TAB]

"qwer1" "qwer2"
julia> foo["qwer
```
Tab completion can also help completing fields:
```julia-repl
julia> x = 3 + 4im;

julia> x.[TAB][TAB]
im re

julia> import UUIDs

julia> UUIDs.uuid[TAB][TAB]
uuid1        uuid4         uuid5        uuid_version
```
Fields for output from functions can also be completed:
```julia-repl
julia> split("","")[1].[TAB]
lastindex  offset  string
```
The completion of fields for output from functions uses type inference, and it can only suggest fields if the function is type stable.
Tab completion can help with investigation of the available methods matching the input arguments:
```julia-repl
julia> max([TAB] # All methods are displayed, not shown here due to size of the list

julia> max([1, 2], [TAB] # All methods where `Vector{Int}` matches as first argument
max(x, y) in Base at operators.jl:215
max(a, b, c, xs...) in Base at operators.jl:281

julia> max([1, 2], max(1, 2), [TAB] # All methods matching the arguments.
max(x, y) in Base at operators.jl:215
max(a, b, c, xs...) in Base at operators.jl:281
```
Keywords are also displayed in the suggested methods after `;`, see below line where `limit` and `keepempty` are keyword arguments:


## [Tab completion](#Tab-completion)
```julia-repl
julia> split("1 1 1", [TAB]
split(str::AbstractString; limit, keepempty) in Base at strings/util.jl:302
split(str::T, splitter; limit, keepempty) where T<:AbstractString in Base at strings/util.jl:277
```
The completion of the methods uses type inference and can therefore see if the arguments match even if the arguments are output from functions. The function needs to be type stable for the completion to be able to remove non-matching methods.
If you wonder which methods can be used with particular argument types, use `?` as the function name. This shows an example of looking for functions in InteractiveUtils that accept a single string:
```julia-repl
julia> InteractiveUtils.?("somefile")[TAB]
edit(path::AbstractString) in InteractiveUtils at InteractiveUtils/src/editless.jl:197
less(file::AbstractString) in InteractiveUtils at InteractiveUtils/src/editless.jl:266
```
This listed methods in the `InteractiveUtils` module that can be called on a string. By default, this excludes methods where all arguments are typed as `Any`, but you can see those too by holding down SHIFT-TAB instead of TAB:


## [Tab completion](#Tab-completion)
```julia-repl
julia> InteractiveUtils.?("somefile")[SHIFT-TAB]
apropos(string) in REPL at REPL/src/docview.jl:796
clipboard(x) in InteractiveUtils at InteractiveUtils/src/clipboard.jl:64
code_llvm(f) in InteractiveUtils at InteractiveUtils/src/codeview.jl:221
code_native(f) in InteractiveUtils at InteractiveUtils/src/codeview.jl:243
edit(path::AbstractString) in InteractiveUtils at InteractiveUtils/src/editless.jl:197
edit(f) in InteractiveUtils at InteractiveUtils/src/editless.jl:225
eval(x) in InteractiveUtils at InteractiveUtils/src/InteractiveUtils.jl:3
include(x) in InteractiveUtils at InteractiveUtils/src/InteractiveUtils.jl:3
less(file::AbstractString) in InteractiveUtils at InteractiveUtils/src/editless.jl:266
less(f) in InteractiveUtils at InteractiveUtils/src/editless.jl:274
report_bug(kind) in InteractiveUtils at InteractiveUtils/src/InteractiveUtils.jl:391
separate_kwargs(args...; kwargs...) in InteractiveUtils at InteractiveUtils/src/macros.jl:7
```
You can also use `?("somefile")[TAB]` and look across all modules, but the method lists can be long.
By omitting the closing parenthesis, you can include functions that might require additional arguments:


## [Tab completion](#Tab-completion)
```julia-repl
julia> using Mmap

help?> Mmap.?("file",[TAB]
Mmap.Anonymous(name::String, readonly::Bool, create::Bool) in Mmap at Mmap/src/Mmap.jl:16
mmap(file::AbstractString) in Mmap at Mmap/src/Mmap.jl:245
mmap(file::AbstractString, ::Type{T}) where T<:Array in Mmap at Mmap/src/Mmap.jl:245
mmap(file::AbstractString, ::Type{T}, dims::Tuple{Vararg{Integer, N}}) where {T<:Array, N} in Mmap at Mmap/src/Mmap.jl:245
mmap(file::AbstractString, ::Type{T}, dims::Tuple{Vararg{Integer, N}}, offset::Integer; grow, shared) where {T<:Array, N} in Mmap at Mmap/src/Mmap.jl:245
mmap(file::AbstractString, ::Type{T}, len::Integer) where T<:Array in Mmap at Mmap/src/Mmap.jl:251
mmap(file::AbstractString, ::Type{T}, len::Integer, offset::Integer; grow, shared) where T<:Array in Mmap at Mmap/src/Mmap.jl:251
mmap(file::AbstractString, ::Type{T}, dims::Tuple{Vararg{Integer, N}}) where {T<:BitArray, N} in Mmap at Mmap/src/Mmap.jl:316
mmap(file::AbstractString, ::Type{T}, dims::Tuple{Vararg{Integer, N}}, offset::Integer; grow, shared) where {T<:BitArray, N} in Mmap at Mmap/src/Mmap.jl:316
mmap(file::AbstractString, ::Type{T}, len::Integer) where T<:BitArray in Mmap at Mmap/src/Mmap.jl:322
mmap(file::AbstractString, ::Type{T}, len::Integer, offset::Integer; grow, shared) where T<:BitArray in Mmap at Mmap/src/Mmap.jl:322
```


## [Customizing Colors](#Customizing-Colors)
The colors used by Julia and the REPL can be customized, as well. To change the color of the Julia prompt you can add something like the following to your `~/.julia/config/startup.jl` file, which is to be placed inside your home directory:
```julia
function customize_colors(repl)
    repl.prompt_color = Base.text_colors[:cyan]
end

atreplinit(customize_colors)
```
The available color keys can be seen by typing `Base.text_colors` in the help mode of the REPL. In addition, the integers 0 to 255 can be used as color keys for terminals with 256 color support.
You can also change the colors for the help and shell prompts and input and answer text by setting the appropriate field of `repl` in the `customize_colors` function above (respectively, `help_color`, `shell_color`, `input_color`, and `answer_color`). For the latter two, be sure that the `envcolors` field is also set to false.
It is also possible to apply boldface formatting by using `Base.text_colors[:bold]` as a color. For instance, to print answers in boldface font, one can use the following as a `~/.julia/config/startup.jl`:
```julia
function customize_colors(repl)
    repl.envcolors = false
    repl.answer_color = Base.text_colors[:bold]
end

atreplinit(customize_colors)
```


## [Customizing Colors](#Customizing-Colors)
You can also customize the color used to render warning and informational messages by setting the appropriate environment variables. For instance, to render error, warning, and informational messages respectively in magenta, yellow, and cyan you can add the following to your `~/.julia/config/startup.jl` file:
```julia
ENV["JULIA_ERROR_COLOR"] = :magenta
ENV["JULIA_WARN_COLOR"] = :yellow
ENV["JULIA_INFO_COLOR"] = :cyan
```


## [Changing the contextual module which is active at the REPL](#Changing-the-contextual-module-which-is-active-at-the-REPL)
When entering expressions at the REPL, they are by default evaluated in the `Main` module;
```julia-repl
julia> @__MODULE__
Main
```
It is possible to change this contextual module via the function `REPL.activate(m)` where `m` is a `Module` or by typing the module in the REPL and pressing the keybinding Alt-m with the cursor on the module name (Esc-m on MacOS). Pressing the keybinding on an empty prompt toggles the context between the previously active non-`Main` module and `Main`. The active module is shown in the prompt (unless it is `Main`):
```julia-repl
julia> using REPL

julia> REPL.activate(Base)

(Base) julia> @__MODULE__
Base

(Base) julia> using REPL # Need to load REPL into Base module to use it

(Base) julia> REPL.activate(Main)

julia>

julia> Core<Alt-m> # using the keybinding to change module

(Core) julia>

(Core) julia> <Alt-m> # going back to Main via keybinding

julia>

julia> <Alt-m> # going back to previously-active Core via keybinding

(Core) julia>
```
Functions that take an optional module argument often defaults to the REPL context module. As an example, calling `varinfo()` will show the variables of the current active module:


## [Changing the contextual module which is active at the REPL](#Changing-the-contextual-module-which-is-active-at-the-REPL)
```julia-repl
julia> module CustomMod
           export var, f
           var = 1
           f(x) = x^2
       end;

julia> REPL.activate(CustomMod)

(Main.CustomMod) julia> varinfo()
  name         size summary
  ––––––––– ––––––– ––––––––––––––––––––––––––––––––––
  CustomMod         Module
  f         0 bytes f (generic function with 1 method)
  var       8 bytes Int64
```


## [Numbered prompt](#Numbered-prompt)
It is possible to get an interface which is similar to the IPython REPL and the Mathematica notebook with numbered input prompts and output prefixes. This is done by calling `REPL.numbered_prompt!()`. If you want to have this enabled on startup, add
```julia
atreplinit() do repl
    @eval import REPL
    if !isdefined(repl, :interface)
        repl.interface = REPL.setup_interface(repl)
    end
    REPL.numbered_prompt!(repl)
end
```
to your `startup.jl` file. In numbered prompt the variable `Out[n]` (where `n` is an integer) can be used to refer to earlier results:
```julia-repl
In [1]: 5 + 3
Out[1]: 8

In [2]: Out[1] + 5
Out[2]: 13

In [3]: Out
Out[3]: Dict{Int64, Any} with 2 entries:
  2 => 13
  1 => 8
```
Since all outputs from previous REPL evaluations are saved in the `Out` variable, one should be careful if they are returning many large in-memory objects like arrays, since they will be protected from garbage collection so long as a reference to them remains in `Out`. If you need to remove references to objects in `Out`, you can clear the entire history it stores with `empty!(Out)`, or clear an individual entry with `Out[n] = nothing`.


## [TerminalMenus](#TerminalMenus)
TerminalMenus is a submodule of the Julia REPL and enables small, low-profile interactive menus in the terminal.


### [Examples](#Examples)
```julia
import REPL
using REPL.TerminalMenus

options = ["apple", "orange", "grape", "strawberry",
            "blueberry", "peach", "lemon", "lime"]
```


#### [RadioMenu](#RadioMenu)
The RadioMenu allows the user to select one option from the list. The `request` function displays the interactive menu and returns the index of the selected choice. If a user presses 'q' or `ctrl-c`, `request` will return a `-1`.
```julia
# `pagesize` is the number of items to be displayed at a time.
#  The UI will scroll if the number of options is greater
#   than the `pagesize`
menu = RadioMenu(options, pagesize=4)

# `request` displays the menu and returns the index after the
#   user has selected a choice
choice = request("Choose your favorite fruit:", menu)

if choice != -1
    println("Your favorite fruit is ", options[choice], "!")
else
    println("Menu canceled.")
end
```
Output:
```julia
Choose your favorite fruit:
^  grape
   strawberry
 > blueberry
v  peach
Your favorite fruit is blueberry!
```


#### [MultiSelectMenu](#MultiSelectMenu)
The MultiSelectMenu allows users to select many choices from a list.
```julia
# here we use the default `pagesize` 10
menu = MultiSelectMenu(options)

# `request` returns a `Set` of selected indices
# if the menu us canceled (ctrl-c or q), return an empty set
choices = request("Select the fruits you like:", menu)

if length(choices) > 0
    println("You like the following fruits:")
    for i in choices
        println("  - ", options[i])
    end
else
    println("Menu canceled.")
end
```
Output:
```julia
Select the fruits you like:
[press: Enter=toggle, a=all, n=none, d=done, q=abort]
   [ ] apple
 > [X] orange
   [X] grape
   [ ] strawberry
   [ ] blueberry
   [X] peach
   [ ] lemon
   [ ] lime
You like the following fruits:
  - orange
  - grape
  - peach
```


### [Customization / Configuration](#Customization-/-Configuration)


#### [ConfiguredMenu subtypes](#ConfiguredMenu-subtypes)
Starting with Julia 1.6, the recommended way to configure menus is via the constructor. For instance, the default multiple-selection menu
```julia
julia> menu = MultiSelectMenu(options, pagesize=5);

julia> request(menu) # ASCII is used by default
[press: Enter=toggle, a=all, n=none, d=done, q=abort]
   [ ] apple
   [X] orange
   [ ] grape
 > [X] strawberry
v  [ ] blueberry
```
can instead be rendered with Unicode selection and navigation characters with
```julia-repl
julia> menu = MultiSelectMenu(options, pagesize=5, charset=:unicode);

julia> request(menu)
[press: Enter=toggle, a=all, n=none, d=done, q=abort]
   ⬚ apple
   ✓ orange
   ⬚ grape
 → ✓ strawberry
↓  ⬚ blueberry
```
More fine-grained configuration is also possible:
```julia-repl
julia> menu = MultiSelectMenu(options, pagesize=5, charset=:unicode, checked="YEP!", unchecked="NOPE", cursor='⧐');

julia> request(menu)
julia> request(menu)
[press: Enter=toggle, a=all, n=none, d=done, q=abort]
   NOPE apple
   YEP! orange
   NOPE grape
 ⧐ YEP! strawberry
↓  NOPE blueberry
```
Aside from the overall `charset` option, for `RadioMenu` the configurable options are:
-   `cursor::Char='>'|'→'`: character to use for cursor
-   `up_arrow::Char='^'|'↑'`: character to use for up arrow
-   `down_arrow::Char='v'|'↓'`: character to use for down arrow
-   `updown_arrow::Char='I'|'↕'`: character to use for up/down arrow in one-line page
-   `scroll_wrap::Bool=false`: optionally wrap-around at the beginning/end of a menu


### [Customization / Configuration](#Customization-/-Configuration)
-   `ctrl_c_interrupt::Bool=true`: If `false`, return empty on ^C, if `true` throw InterruptException() on ^C
`MultiSelectMenu` adds:
-   `checked::String="[X]"|"✓"`: string to use for checked
-   `unchecked::String="[ ]"|"⬚")`: string to use for unchecked
You can create new menu types of your own. Types that are derived from `TerminalMenus.ConfiguredMenu` configure the menu options at construction time.


#### [Legacy interface](#Legacy-interface)
Prior to Julia 1.6, and still supported throughout Julia 1.x, one can also configure menus by calling `TerminalMenus.config()`.


## [References](#References)


### [REPL](#REPL)
```julia
atreplinit(f)
```
Register a one-argument function to be called before the REPL interface is initialized in interactive sessions; this is useful to customize the interface. The argument of `f` is the REPL object. This function should be called from within the `.julia/config/startup.jl` initialization file.
[source](https://github.com/JuliaLang/julia/blob/9615af0f269df4d371b8010e9507ed5bae86103b/base/client.jl#L368-L375)


### [TerminalMenus](#TerminalMenus-2)


### [Menus](#Menus)
```julia
RadioMenu
```
A menu that allows a user to select a single option from a list.
**Sample Output**
```julia-repl
julia> request(RadioMenu(options, pagesize=4))
Choose your favorite fruit:
^  grape
   strawberry
 > blueberry
v  peach
Your favorite fruit is blueberry!
```
```julia
MultiSelectMenu
```
A menu that allows a user to select a multiple options from a list.
**Sample Output**
```julia-repl
julia> request(MultiSelectMenu(options))
Select the fruits you like:
[press: Enter=toggle, a=all, n=none, d=done, q=abort]
   [ ] apple
 > [X] orange
   [X] grape
   [ ] strawberry
   [ ] blueberry
   [X] peach
   [ ] lemon
   [ ] lime
You like the following fruits:
  - orange
  - grape
  - peach
```


#### [Configuration](#Configuration)
```julia
Config(; scroll_wrap=false, ctrl_c_interrupt=true, charset=:ascii, cursor::Char, up_arrow::Char, down_arrow::Char)
```
Configure behavior for selection menus via keyword arguments:
-   `scroll_wrap`, if `true`, causes the menu to wrap around when scrolling above the first or below the last entry
-   `ctrl_c_interrupt`, if `true`, throws an `InterruptException` if the user hits Ctrl-C during menu selection. If `false`, [`TerminalMenus.request`](#REPL.TerminalMenus.request) will return the default result from [`TerminalMenus.selected`](#REPL.TerminalMenus.selected).
-   `charset` affects the default values for `cursor`, `up_arrow`, and `down_arrow`, and can be `:ascii` or `:unicode`
-   `cursor` is the character printed to indicate the option that will be chosen by hitting "Enter." Defaults are '>' or '→', depending on `charset`.
-   `up_arrow` is the character printed when the display does not include the first entry. Defaults are '^' or '↑', depending on `charset`.
-   `down_arrow` is the character printed when the display does not include the last entry. Defaults are 'v' or '↓', depending on `charset`.
Subtypes of `ConfiguredMenu` will print `cursor`, `up_arrow`, and `down_arrow` automatically as needed, your `writeline` method should not print them.
`Config` is available as of Julia 1.6. On older releases use the global `CONFIG`.
```julia
MultiSelectConfig(; charset=:ascii, checked::String, unchecked::String, kwargs...)
```
Configure behavior for a multiple-selection menu via keyword arguments:


### [Menus](#Menus)
-   `checked` is the string to print when an option has been selected. Defaults are "\[X\]" or "✓", depending on `charset`.
-   `unchecked` is the string to print when an option has not been selected. Defaults are "\[ \]" or "⬚", depending on `charset`.
All other keyword arguments are as described for [`TerminalMenus.Config`](#REPL.TerminalMenus.Config). `checked` and `unchecked` are not printed automatically, and should be printed by your `writeline` method.
`MultiSelectConfig` is available as of Julia 1.6. On older releases use the global `CONFIG`.
```julia
config( <see arguments> )
```
Keyword-only function to configure global menu parameters
**Arguments**
-   `charset::Symbol=:na`: ui characters to use (`:ascii` or `:unicode`); overridden by other arguments
-   `cursor::Char='>'|'→'`: character to use for cursor
-   `up_arrow::Char='^'|'↑'`: character to use for up arrow
-   `down_arrow::Char='v'|'↓'`: character to use for down arrow
-   `checked::String="[X]"|"✓"`: string to use for checked
-   `unchecked::String="[ ]"|"⬚")`: string to use for unchecked
-   `scroll::Symbol=:nowrap`: If `:wrap` wrap cursor around top and bottom, if :`nowrap` do not wrap cursor
-   `supress_output::Bool=false`: Ignored legacy argument, pass `suppress_output` as a keyword argument to `request` instead.
-   `ctrl_c_interrupt::Bool=true`: If `false`, return empty on ^C, if `true` throw InterruptException() on ^C
As of Julia 1.6, `config` is deprecated. Use `Config` or `MultiSelectConfig` instead.


#### [User interaction](#User-interaction)
```julia
request(m::AbstractMenu; cursor=1)
```
Display the menu and enter interactive mode. `cursor` indicates the item number used for the initial cursor position. `cursor` can be either an `Int` or a `RefValue{Int}`. The latter is useful for observation and control of the cursor position from the outside.
Returns `selected(m)`.
The `cursor` argument requires Julia 1.6 or later.
```julia
request([term,] msg::AbstractString, m::AbstractMenu)
```
Shorthand for `println(msg); request(m)`.


#### [AbstractMenu extension interface](#AbstractMenu-extension-interface)
Any subtype of `AbstractMenu` must be mutable, and must contain the fields `pagesize::Int` and `pageoffset::Int`. Any subtype must also implement the following functions:
```julia
pick(m::AbstractMenu, cursor::Int)
```
Defines what happens when a user presses the Enter key while the menu is open. If `true` is returned, `request()` will exit. `cursor` indexes the position of the selection.
```julia
cancel(m::AbstractMenu)
```
Define what happens when a user cancels ('q' or ctrl-c) a menu. `request()` will always exit after calling this function.
```julia
writeline(buf::IO, m::AbstractMenu, idx::Int, iscursor::Bool)
```
Write the option at index `idx` to `buf`. `iscursor`, if `true`, indicates that this item is at the current cursor position (the one that will be selected by hitting "Enter").
If `m` is a `ConfiguredMenu`, `TerminalMenus` will print the cursor indicator. Otherwise the callee is expected to handle such printing.
`writeline` requires Julia 1.6 or higher.
On older versions of Julia, this was `writeLine(buf::IO, m::AbstractMenu, idx, iscursor::Bool)` and `m` is assumed to be unconfigured. The selection and cursor indicators can be obtained from `TerminalMenus.CONFIG`.
This older function is supported on all Julia 1.x versions but will be dropped in Julia 2.0.
It must also implement either `options` or `numoptions`:
```julia
options(m::AbstractMenu)
```
Return a list of strings to be displayed as options in the current page.


### [Menus](#Menus)
Alternatively, implement `numoptions`, in which case `options` is not needed.
```julia
numoptions(m::AbstractMenu) -> Int
```
Return the number of options in menu `m`. Defaults to `length(options(m))`.
This function requires Julia 1.6 or later.
If the subtype does not have a field named `selected`, it must also implement
```julia
selected(m::AbstractMenu)
```
Return information about the user-selected option. By default it returns `m.selected`.
The following are optional but can allow additional customization:
```julia
header(m::AbstractMenu) -> String
```
Return a header string to be printed above the menu. Defaults to "".
```julia
keypress(m::AbstractMenu, i::UInt32) -> Bool
```
Handle any non-standard keypress event. If `true` is returned, [`TerminalMenus.request`](#REPL.TerminalMenus.request) will exit. Defaults to `false`.
------------------------------------------------------------------------


# Random Numbers · The Julia Language
Source: https://docs.julialang.org/en/v1/stdlib/Random/


# [Random Numbers](#Random-Numbers)
Random number generation in Julia uses the [Xoshiro256++](https://prng.di.unimi.it/) algorithm by default, with per-`Task` state. Other RNG types can be plugged in by inheriting the `AbstractRNG` type; they can then be used to obtain multiple streams of random numbers.
The PRNGs (pseudorandom number generators) exported by the `Random` package are:
-   `TaskLocalRNG`: a token that represents use of the currently active Task-local stream, deterministically seeded from the parent task, or by `RandomDevice` (with system randomness) at program start
-   `Xoshiro`: generates a high-quality stream of random numbers with a small state vector and high performance using the Xoshiro256++ algorithm
-   `RandomDevice`: for OS-provided entropy. This may be used for cryptographically secure random numbers (CS(P)RNG).
-   `MersenneTwister`: an alternate high-quality PRNG which was the default in older versions of Julia, and is also quite fast, but requires much more space to store the state vector and generate a random sequence.
Most functions related to random generation accept an optional `AbstractRNG` object as first argument. Some also accept dimension specifications `dims...` (which can also be given as a tuple) to generate arrays of random values. In a multi-threaded program, you should generally use different RNG objects from different threads or tasks in order to be thread-safe. However, the default RNG is thread-safe as of Julia 1.3 (using a per-thread RNG up to version 1.6, and per-task thereafter).


# [Random Numbers](#Random-Numbers)
The provided RNGs can generate uniform random numbers of the following types: [`Float16`](../../base/numbers/#Core.Float16), [`Float32`](../../base/numbers/#Core.Float32), [`Float64`](../../base/numbers/#Core.Float64), [`BigFloat`](../../base/numbers/#Base.MPFR.BigFloat), [`Bool`](../../base/numbers/#Core.Bool), [`Int8`](../../base/numbers/#Core.Int8), [`UInt8`](../../base/numbers/#Core.UInt8), [`Int16`](../../base/numbers/#Core.Int16), [`UInt16`](../../base/numbers/#Core.UInt16), [`Int32`](../../base/numbers/#Core.Int32), [`UInt32`](../../base/numbers/#Core.UInt32), [`Int64`](../../base/numbers/#Core.Int64), [`UInt64`](../../base/numbers/#Core.UInt64), [`Int128`](../../base/numbers/#Core.Int128), [`UInt128`](../../base/numbers/#Core.UInt128), [`BigInt`](../../base/numbers/#Base.GMP.BigInt) (or complex numbers of those types). Random floating point numbers are generated uniformly in $\[0, 1)$. As `BigInt` represents unbounded integers, the interval must be specified (e.g. `rand(big.(1:6))`).
Additionally, normal and exponential distributions are implemented for some `AbstractFloat` and `Complex` types, see [`randn`](#Base.randn) and [`randexp`](#Random.randexp) for details.
To generate random numbers from other distributions, see the [Distributions.jl](https://juliastats.org/Distributions.jl/stable/) package.


# [Random Numbers](#Random-Numbers)
Because the precise way in which random numbers are generated is considered an implementation detail, bug fixes and speed improvements may change the stream of numbers that are generated after a version change. Relying on a specific seed or generated stream of numbers during unit testing is thus discouraged - consider testing properties of the methods in question instead.


## [Random numbers module](#Random-numbers-module)
```julia
Random
```
Support for generating random numbers. Provides [`rand`](#Base.rand), [`randn`](#Base.randn), [`AbstractRNG`](#Random.AbstractRNG), [`MersenneTwister`](#Random.MersenneTwister), and [`RandomDevice`](#Random.RandomDevice).


## [Random generation functions](#Random-generation-functions)
```julia
rand([rng=default_rng()], [S], [dims...])
```
Pick a random element or array of random elements from the set of values specified by `S`; `S` can be
-   an indexable collection (for example `1:9` or `('x', "y", :z)`)
-   an `AbstractDict` or `AbstractSet` object
-   a string (considered as a collection of characters), or
-   a type from the list below, corresponding to the specified set of values
    -   concrete integer types sample from `typemin(S):typemax(S)` (excepting [`BigInt`](../../base/numbers/#Base.GMP.BigInt) which is not supported)
    -   concrete floating point types sample from `[0, 1)`
    -   concrete complex types `Complex{T}` if `T` is a sampleable type take their real and imaginary components independently from the set of values corresponding to `T`, but are not supported if `T` is not sampleable.
    -   all `<:AbstractChar` types sample from the set of valid Unicode scalars
    -   a user-defined type and set of values; for implementation guidance please see [Hooking into the `Random` API](#rand-api-hook)
    -   a tuple type of known size and where each parameter of `S` is itself a sampleable type; return a value of type `S`. Note that tuple types such as `Tuple{Vararg{T}}` (unknown size) and `Tuple{1:2}` (parameterized with a value) are not supported
    -   a `Pair` type, e.g. `Pair{X, Y}` such that `rand` is defined for `X` and `Y`, in which case random pairs are produced.


## [Random generation functions](#Random-generation-functions)
`S` defaults to [`Float64`](../../base/numbers/#Core.Float64). When only one argument is passed besides the optional `rng` and is a `Tuple`, it is interpreted as a collection of values (`S`) and not as `dims`.
See also [`randn`](#Base.randn) for normally distributed numbers, and [`rand!`](#Random.rand!) and [`randn!`](#Random.randn!) for the in-place equivalents.
Support for `S` as a tuple requires at least Julia 1.1.
Support for `S` as a `Tuple` type requires at least Julia 1.11.
**Examples**
```julia-repl
julia> rand(Int, 2)
2-element Array{Int64,1}:
 1339893410598768192
 1575814717733606317

julia> using Random

julia> rand(Xoshiro(0), Dict(1=>2, 3=>4))
3 => 4

julia> rand((2, 3))
3

julia> rand(Float64, (2, 3))
2×3 Array{Float64,2}:
 0.999717  0.0143835  0.540787
 0.696556  0.783855   0.938235
```
The complexity of `rand(rng, s::Union{AbstractDict,AbstractSet})` is linear in the length of `s`, unless an optimized method with constant complexity is available, which is the case for `Dict`, `Set` and dense `BitSet`s. For more than a few calls, use `rand(rng, collect(s))` instead, or either `rand(rng, Dict(s))` or `rand(rng, Set(s))` as appropriate.
```julia
rand!([rng=default_rng()], A, [S=eltype(A)])
```
Populate the array `A` with random values. If `S` is specified (`S` can be a type or a collection, cf. [`rand`](#Base.rand) for details), the values are picked randomly from `S`. This is equivalent to `copyto!(A, rand(rng, S, size(A)))` but without allocating a new array.
**Examples**


## [Random generation functions](#Random-generation-functions)
```julia-repl
julia> rand!(Xoshiro(123), zeros(5))
5-element Vector{Float64}:
 0.521213795535383
 0.5868067574533484
 0.8908786980927811
 0.19090669902576285
 0.5256623915420473
```
```julia
bitrand([rng=default_rng()], [dims...])
```
Generate a `BitArray` of random boolean values.
**Examples**
```julia-repl
julia> bitrand(Xoshiro(123), 10)
10-element BitVector:
 0
 1
 0
 1
 0
 1
 0
 0
 1
 1
```
```julia
randn([rng=default_rng()], [T=Float64], [dims...])
```
Generate a normally-distributed random number of type `T` with mean 0 and standard deviation 1. Given the optional `dims` argument(s), generate an array of size `dims` of such numbers. Julia's standard library supports `randn` for any floating-point type that implements [`rand`](#Base.rand), e.g. the `Base` types [`Float16`](../../base/numbers/#Core.Float16), [`Float32`](../../base/numbers/#Core.Float32), [`Float64`](../../base/numbers/#Core.Float64) (the default), and [`BigFloat`](../../base/numbers/#Base.MPFR.BigFloat), along with their [`Complex`](../../base/numbers/#Base.Complex) counterparts.
(When `T` is complex, the values are drawn from the circularly symmetric complex normal distribution of variance 1, corresponding to real and imaginary parts having independent normal distribution with mean zero and variance `1/2`).
See also [`randn!`](#Random.randn!) to act in-place.
**Examples**
Generating a single random number (with the default `Float64` type):
```julia-repl
julia> randn()
-0.942481877315864
```


## [Random generation functions](#Random-generation-functions)
Generating a matrix of normal random numbers (with the default `Float64` type):
```julia-repl
julia> randn(2,3)
2×3 Matrix{Float64}:
  1.18786   -0.678616   1.49463
 -0.342792  -0.134299  -1.45005
```
Setting up of the random number generator `rng` with a user-defined seed (for reproducible numbers) and using it to generate a random `Float32` number or a matrix of `ComplexF32` random numbers:
```julia-repl
julia> using Random

julia> rng = Xoshiro(123);

julia> randn(rng, Float32)
-0.6457307f0

julia> randn(rng, ComplexF32, (2, 3))
2×3 Matrix{ComplexF32}:
  -1.03467-1.14806im  0.693657+0.056538im   0.291442+0.419454im
 -0.153912+0.34807im    1.0954-0.948661im  -0.543347-0.0538589im
```
```julia
randn!([rng=default_rng()], A::AbstractArray) -> A
```
Fill the array `A` with normally-distributed (mean 0, standard deviation 1) random numbers. Also see the [`rand`](#Base.rand) function.
**Examples**
```julia-repl
julia> randn!(Xoshiro(123), zeros(5))
5-element Vector{Float64}:
 -0.6457306721039767
 -1.4632513788889214
 -1.6236037455860806
 -0.21766510678354617
  0.4922456865251828
```
```julia
randexp([rng=default_rng()], [T=Float64], [dims...])
```
Generate a random number of type `T` according to the exponential distribution with scale 1. Optionally generate an array of such random numbers. The `Base` module currently provides an implementation for the types [`Float16`](../../base/numbers/#Core.Float16), [`Float32`](../../base/numbers/#Core.Float32), and [`Float64`](../../base/numbers/#Core.Float64) (the default).


## [Random generation functions](#Random-generation-functions)
**Examples**
```julia-repl
julia> rng = Xoshiro(123);

julia> randexp(rng, Float32)
1.1757717f0

julia> randexp(rng, 3, 3)
3×3 Matrix{Float64}:
 1.37766  0.456653  0.236418
 3.40007  0.229917  0.0684921
 0.48096  0.577481  0.71835
```
```julia
randexp!([rng=default_rng()], A::AbstractArray) -> A
```
Fill the array `A` with random numbers following the exponential distribution (with scale 1).
**Examples**
```julia-repl
julia> randexp!(Xoshiro(123), zeros(5))
5-element Vector{Float64}:
 1.1757716836348473
 1.758884569451514
 1.0083623637301151
 0.3510644315565272
 0.6348266443720407
```
```julia
randstring([rng=default_rng()], [chars], [len=8])
```
Create a random string of length `len`, consisting of characters from `chars`, which defaults to the set of upper- and lower-case letters and the digits 0-9. The optional `rng` argument specifies a random number generator, see [Random Numbers](#Random-Numbers).
**Examples**
```julia-repl
julia> Random.seed!(3); randstring()
"Lxz5hUwn"

julia> randstring(Xoshiro(3), 'a':'z', 6)
"iyzcsm"

julia> randstring("ACGT")
"TGCTCCTC"
```
`chars` can be any collection of characters, of type `Char` or `UInt8` (more efficient), provided [`rand`](#Base.rand) can randomly pick characters from it.


## [Subsequences, permutations and shuffling](#Subsequences,-permutations-and-shuffling)
```julia
randsubseq([rng=default_rng(),] A, p) -> Vector
```
Return a vector consisting of a random subsequence of the given array `A`, where each element of `A` is included (in order) with independent probability `p`. (Complexity is linear in `p*length(A)`, so this function is efficient even if `p` is small and `A` is large.) Technically, this process is known as "Bernoulli sampling" of `A`.
**Examples**
```julia-repl
julia> randsubseq(Xoshiro(123), 1:8, 0.3)
2-element Vector{Int64}:
 4
 7
```
```julia
randsubseq!([rng=default_rng(),] S, A, p)
```
Like [`randsubseq`](#Random.randsubseq), but the results are stored in `S` (which is resized as needed).
**Examples**
```julia-repl
julia> S = Int64[];

julia> randsubseq!(Xoshiro(123), S, 1:8, 0.3)
2-element Vector{Int64}:
 4
 7

julia> S
2-element Vector{Int64}:
 4
 7
```
```julia
randperm([rng=default_rng(),] n::Integer)
```
Construct a random permutation of length `n`. The optional `rng` argument specifies a random number generator (see [Random Numbers](#Random-Numbers)). The element type of the result is the same as the type of `n`.
To randomly permute an arbitrary vector, see [`shuffle`](#Random.shuffle) or [`shuffle!`](#Random.shuffle!).
In Julia 1.1 `randperm` returns a vector `v` with `eltype(v) == typeof(n)` while in Julia 1.0 `eltype(v) == Int`.
**Examples**
```julia-repl
julia> randperm(Xoshiro(123), 4)
4-element Vector{Int64}:
 1
 4
 2
 3
```
```julia
randperm!([rng=default_rng(),] A::Array{<:Integer})
```


## [Subsequences, permutations and shuffling](#Subsequences,-permutations-and-shuffling)
Construct in `A` a random permutation of length `length(A)`. The optional `rng` argument specifies a random number generator (see [Random Numbers](#Random-Numbers)). To randomly permute an arbitrary vector, see [`shuffle`](#Random.shuffle) or [`shuffle!`](#Random.shuffle!).
**Examples**
```julia-repl
julia> randperm!(Xoshiro(123), Vector{Int}(undef, 4))
4-element Vector{Int64}:
 1
 4
 2
 3
```
```julia
randcycle([rng=default_rng(),] n::Integer)
```
Construct a random cyclic permutation of length `n`. The optional `rng` argument specifies a random number generator, see [Random Numbers](#Random-Numbers). The element type of the result is the same as the type of `n`.
Here, a "cyclic permutation" means that all of the elements lie within a single cycle. If `n > 0`, there are $(n-1)!$ possible cyclic permutations, which are sampled uniformly. If `n == 0`, `randcycle` returns an empty vector.
[`randcycle!`](#Random.randcycle!) is an in-place variant of this function.
In Julia 1.1 and above, `randcycle` returns a vector `v` with `eltype(v) == typeof(n)` while in Julia 1.0 `eltype(v) == Int`.
**Examples**
```julia-repl
julia> randcycle(Xoshiro(123), 6)
6-element Vector{Int64}:
 5
 4
 2
 6
 3
 1
```
```julia
randcycle!([rng=default_rng(),] A::Array{<:Integer})
```
Construct in `A` a random cyclic permutation of length `n = length(A)`. The optional `rng` argument specifies a random number generator, see [Random Numbers](#Random-Numbers).


## [Subsequences, permutations and shuffling](#Subsequences,-permutations-and-shuffling)
Here, a "cyclic permutation" means that all of the elements lie within a single cycle. If `A` is nonempty (`n > 0`), there are $(n-1)!$ possible cyclic permutations, which are sampled uniformly. If `A` is empty, `randcycle!` leaves it unchanged.
[`randcycle`](#Random.randcycle) is a variant of this function that allocates a new vector.
**Examples**
```julia-repl
julia> randcycle!(Xoshiro(123), Vector{Int}(undef, 6))
6-element Vector{Int64}:
 5
 4
 2
 6
 3
 1
```
```julia
shuffle([rng=default_rng(),] v::AbstractArray)
```
Return a randomly permuted copy of `v`. The optional `rng` argument specifies a random number generator (see [Random Numbers](#Random-Numbers)). To permute `v` in-place, see [`shuffle!`](#Random.shuffle!). To obtain randomly permuted indices, see [`randperm`](#Random.randperm).
**Examples**
```julia-repl
julia> shuffle(Xoshiro(123), Vector(1:10))
10-element Vector{Int64}:
  5
  4
  2
  3
  6
 10
  8
  1
  9
  7
```
```julia
shuffle!([rng=default_rng(),] v::AbstractArray)
```
In-place version of [`shuffle`](#Random.shuffle): randomly permute `v` in-place, optionally supplying the random-number generator `rng`.
**Examples**
```julia-repl
julia> shuffle!(Xoshiro(123), Vector(1:10))
10-element Vector{Int64}:
  5
  4
  2
  3
  6
 10
  8
  1
  9
  7
```


## [Generators (creation and seeding)](#Generators-(creation-and-seeding))
```julia
Random.default_rng() -> rng
```
Return the default global random number generator (RNG), which is used by `rand`-related functions when no explicit RNG is provided.
When the `Random` module is loaded, the default RNG is *randomly* seeded, via [`Random.seed!()`](#Random.seed!): this means that each time a new julia session is started, the first call to `rand()` produces a different result, unless `seed!(seed)` is called first.
It is thread-safe: distinct threads can safely call `rand`-related functions on `default_rng()` concurrently, e.g. `rand(default_rng())`.
The type of the default RNG is an implementation detail. Across different versions of Julia, you should not expect the default RNG to always have the same type, nor that it will produce the same stream of random numbers for a given seed.
This function was introduced in Julia 1.3.
```julia
seed!([rng=default_rng()], seed) -> rng
seed!([rng=default_rng()]) -> rng
```
Reseed the random number generator: `rng` will give a reproducible sequence of numbers if and only if a `seed` is provided. Some RNGs don't accept a seed, like `RandomDevice`. After the call to `seed!`, `rng` is equivalent to a newly created object initialized with the same seed. The types of accepted seeds depend on the type of `rng`, but in general, integer seeds should work.
If `rng` is not specified, it defaults to seeding the state of the shared task-local generator.
**Examples**


## [Generators (creation and seeding)](#Generators-(creation-and-seeding))
```julia-repl
julia> Random.seed!(1234);

julia> x1 = rand(2)
2-element Vector{Float64}:
 0.32597672886359486
 0.5490511363155669

julia> Random.seed!(1234);

julia> x2 = rand(2)
2-element Vector{Float64}:
 0.32597672886359486
 0.5490511363155669

julia> x1 == x2
true

julia> rng = Xoshiro(1234); rand(rng, 2) == x1
true

julia> Xoshiro(1) == Random.seed!(rng, 1)
true

julia> rand(Random.seed!(rng), Bool) # not reproducible
true

julia> rand(Random.seed!(rng), Bool) # not reproducible either
false

julia> rand(Xoshiro(), Bool) # not reproducible either
true
```
```julia
AbstractRNG
```
Supertype for random number generators such as [`MersenneTwister`](#Random.MersenneTwister) and [`RandomDevice`](#Random.RandomDevice).
```julia
TaskLocalRNG
```
The `TaskLocalRNG` has state that is local to its task, not its thread. It is seeded upon task creation, from the state of its parent task, but without advancing the state of the parent's RNG.
As an upside, the `TaskLocalRNG` is pretty fast, and permits reproducible multithreaded simulations (barring race conditions), independent of scheduler decisions. As long as the number of threads is not used to make decisions on task creation, simulation results are also independent of the number of available threads / CPUs. The random stream should not depend on hardware specifics, up to endianness and possibly word size.


## [Generators (creation and seeding)](#Generators-(creation-and-seeding))
Using or seeding the RNG of any other task than the one returned by `current_task()` is undefined behavior: it will work most of the time, and may sometimes fail silently.
When seeding `TaskLocalRNG()` with [`seed!`](#Random.seed!), the passed seed, if any, may be any integer.
Seeding `TaskLocalRNG()` with a negative integer seed requires at least Julia 1.11.
Task creation no longer advances the parent task's RNG state as of Julia 1.10.
```julia
Xoshiro(seed::Union{Integer, AbstractString})
Xoshiro()
```
Xoshiro256++ is a fast pseudorandom number generator described by David Blackman and Sebastiano Vigna in "Scrambled Linear Pseudorandom Number Generators", ACM Trans. Math. Softw., 2021. Reference implementation is available at https://prng.di.unimi.it
Apart from the high speed, Xoshiro has a small memory footprint, making it suitable for applications where many different random states need to be held for long time.
Julia's Xoshiro implementation has a bulk-generation mode; this seeds new virtual PRNGs from the parent, and uses SIMD to generate in parallel (i.e. the bulk stream consists of multiple interleaved xoshiro instances). The virtual PRNGs are discarded once the bulk request has been serviced (and should cause no heap allocations).
If no seed is provided, a randomly generated one is created (using entropy from the system). See the [`seed!`](#Random.seed!) function for reseeding an already existing `Xoshiro` object.
Passing a negative integer seed requires at least Julia 1.11.
**Examples**


## [Generators (creation and seeding)](#Generators-(creation-and-seeding))
```julia-repl
julia> using Random

julia> rng = Xoshiro(1234);

julia> x1 = rand(rng, 2)
2-element Vector{Float64}:
 0.32597672886359486
 0.5490511363155669

julia> rng = Xoshiro(1234);

julia> x2 = rand(rng, 2)
2-element Vector{Float64}:
 0.32597672886359486
 0.5490511363155669

julia> x1 == x2
true
```
```julia
MersenneTwister(seed)
MersenneTwister()
```
Create a `MersenneTwister` RNG object. Different RNG objects can have their own seeds, which may be useful for generating different streams of random numbers. The `seed` may be an integer, a string, or a vector of `UInt32` integers. If no seed is provided, a randomly generated one is created (using entropy from the system). See the [`seed!`](#Random.seed!) function for reseeding an already existing `MersenneTwister` object.
Passing a negative integer seed requires at least Julia 1.11.
**Examples**
```julia-repl
julia> rng = MersenneTwister(123);

julia> x1 = rand(rng, 2)
2-element Vector{Float64}:
 0.37453777969575874
 0.8735343642013971

julia> x2 = rand(MersenneTwister(123), 2)
2-element Vector{Float64}:
 0.37453777969575874
 0.8735343642013971

julia> x1 == x2
true
```
```julia
RandomDevice()
```
Create a `RandomDevice` RNG object. Two such objects will always generate different streams of random numbers. The entropy is obtained from the operating system.


## [Hooking into the Random API](#rand-api-hook)
There are two mostly orthogonal ways to extend `Random` functionalities:
1.  generating random values of custom types
2.  creating new generators
The API for 1) is quite functional, but is relatively recent so it may still have to evolve in subsequent releases of the `Random` module. For example, it's typically sufficient to implement one `rand` method in order to have all other usual methods work automatically.
The API for 2) is still rudimentary, and may require more work than strictly necessary from the implementor, in order to support usual types of generated values.


### [Generating random values of custom types](#Generating-random-values-of-custom-types)
Generating random values for some distributions may involve various trade-offs. *Pre-computed* values, such as an [alias table](https://en.wikipedia.org/wiki/Alias_method) for discrete distributions, or [“squeezing” functions](https://en.wikipedia.org/wiki/Rejection_sampling) for univariate distributions, can speed up sampling considerably. How much information should be pre-computed can depend on the number of values we plan to draw from a distribution. Also, some random number generators can have certain properties that various algorithms may want to exploit.
The `Random` module defines a customizable framework for obtaining random values that can address these issues. Each invocation of `rand` generates a *sampler* which can be customized with the above trade-offs in mind, by adding methods to `Sampler`, which in turn can dispatch on the random number generator, the object that characterizes the distribution, and a suggestion for the number of repetitions. Currently, for the latter, `Val{1}` (for a single sample) and `Val{Inf}` (for an arbitrary number) are used, with `Random.Repetition` an alias for both.
The object returned by `Sampler` is then used to generate the random values. When implementing the random generation interface for a value `X` that can be sampled from, the implementor should define the method
```julia
rand(rng, sampler)
```
for the particular `sampler` returned by `Sampler(rng, X, repetition)`.


### [Generating random values of custom types](#Generating-random-values-of-custom-types)
Samplers can be arbitrary values that implement `rand(rng, sampler)`, but for most applications the following predefined samplers may be sufficient:
1.  `SamplerType{T}()` can be used for implementing samplers that draw from type `T` (e.g. `rand(Int)`). This is the default returned by `Sampler` for *types*.
2.  `SamplerTrivial(self)` is a simple wrapper for `self`, which can be accessed with `[]`. This is the recommended sampler when no pre-computed information is needed (e.g. `rand(1:3)`), and is the default returned by `Sampler` for *values*.
3.  `SamplerSimple(self, data)` also contains the additional `data` field, which can be used to store arbitrary pre-computed values, which should be computed in a *custom method* of `Sampler`.
We provide examples for each of these. We assume here that the choice of algorithm is independent of the RNG, so we use `AbstractRNG` in our signatures.
```julia
Sampler(rng, x, repetition = Val(Inf))
```
Return a sampler object that can be used to generate random values from `rng` for `x`.
When `sp = Sampler(rng, x, repetition)`, `rand(rng, sp)` will be used to draw random values, and should be defined accordingly.
`repetition` can be `Val(1)` or `Val(Inf)`, and should be used as a suggestion for deciding the amount of precomputation, if applicable.


### [Generating random values of custom types](#Generating-random-values-of-custom-types)
[`Random.SamplerType`](#Random.SamplerType) and [`Random.SamplerTrivial`](#Random.SamplerTrivial) are default fallbacks for *types* and *values*, respectively. [`Random.SamplerSimple`](#Random.SamplerSimple) can be used to store pre-computed values without defining extra types for only this purpose.
```julia
SamplerType{T}()
```
A sampler for types, containing no other information. The default fallback for `Sampler` when called with types.
```julia
SamplerTrivial(x)
```
Create a sampler that just wraps the given value `x`. This is the default fall-back for values. The `eltype` of this sampler is equal to `eltype(x)`.
The recommended use case is sampling from values without precomputed data.
```julia
SamplerSimple(x, data)
```
Create a sampler that wraps the given value `x` and the `data`. The `eltype` of this sampler is equal to `eltype(x)`.
The recommended use case is sampling from values with precomputed data.
Decoupling pre-computation from actually generating the values is part of the API, and is also available to the user. As an example, assume that `rand(rng, 1:20)` has to be called repeatedly in a loop: the way to take advantage of this decoupling is as follows:
```julia
rng = Xoshiro()
sp = Random.Sampler(rng, 1:20) # or Random.Sampler(Xoshiro, 1:20)
for x in X
    n = rand(rng, sp) # similar to n = rand(rng, 1:20)
    # use n
end
```


### [Generating random values of custom types](#Generating-random-values-of-custom-types)
This is the mechanism that is also used in the standard library, e.g. by the default implementation of random array generation (like in `rand(1:20, 10)`).


#### [Generating values from a type](#Generating-values-from-a-type)
Given a type `T`, it's currently assumed that if `rand(T)` is defined, an object of type `T` will be produced. `SamplerType` is the *default sampler for types*. In order to define random generation of values of type `T`, the `rand(rng::AbstractRNG, ::Random.SamplerType{T})` method should be defined, and should return values what `rand(rng, T)` is expected to return.
Let's take the following example: we implement a `Die` type, with a variable number `n` of sides, numbered from `1` to `n`. We want `rand(Die)` to produce a `Die` with a random number of up to 20 sides (and at least 4):
```julia
struct Die
    nsides::Int # number of sides
end

Random.rand(rng::AbstractRNG, ::Random.SamplerType{Die}) = Die(rand(rng, 4:20))

# output
```
Scalar and array methods for `Die` now work as expected:
```julia-repl
julia> rand(Die)
Die(5)

julia> rand(Xoshiro(0), Die)
Die(10)

julia> rand(Die, 3)
3-element Vector{Die}:
 Die(9)
 Die(15)
 Die(14)

julia> a = Vector{Die}(undef, 3); rand!(a)
3-element Vector{Die}:
 Die(19)
 Die(7)
 Die(17)
```


#### [A simple sampler without pre-computed data](#A-simple-sampler-without-pre-computed-data)
Here we define a sampler for a collection. If no pre-computed data is required, it can be implemented with a `SamplerTrivial` sampler, which is in fact the *default fallback for values*.
In order to define random generation out of objects of type `S`, the following method should be defined: `rand(rng::AbstractRNG, sp::Random.SamplerTrivial{S})`. Here, `sp` simply wraps an object of type `S`, which can be accessed via `sp[]`. Continuing the `Die` example, we want now to define `rand(d::Die)` to produce an `Int` corresponding to one of `d`'s sides:
```julia-repl
julia> Random.rand(rng::AbstractRNG, d::Random.SamplerTrivial{Die}) = rand(rng, 1:d[].nsides);

julia> rand(Die(4))
1

julia> rand(Die(4), 3)
3-element Vector{Any}:
 2
 3
 3
```
Given a collection type `S`, it's currently assumed that if `rand(::S)` is defined, an object of type `eltype(S)` will be produced. In the last example, a `Vector{Any}` is produced; the reason is that `eltype(Die) == Any`. The remedy is to define `Base.eltype(::Type{Die}) = Int`.


#### [Generating values for an AbstractFloat type](#Generating-values-for-an-AbstractFloat-type)
`AbstractFloat` types are special-cased, because by default random values are not produced in the whole type domain, but rather in `[0,1)`. The following method should be implemented for `T <: AbstractFloat`: `Random.rand(::AbstractRNG, ::Random.SamplerTrivial{Random.CloseOpen01{T}})`


#### [An optimized sampler with pre-computed data](#An-optimized-sampler-with-pre-computed-data)
Consider a discrete distribution, where numbers `1:n` are drawn with given probabilities that sum to one. When many values are needed from this distribution, the fastest method is using an [alias table](https://en.wikipedia.org/wiki/Alias_method). We don't provide the algorithm for building such a table here, but suppose it is available in `make_alias_table(probabilities)` instead, and `draw_number(rng, alias_table)` can be used to draw a random number from it.
Suppose that the distribution is described by
```julia
struct DiscreteDistribution{V <: AbstractVector}
    probabilities::V
end
```
and that we *always* want to build an alias table, regardless of the number of values needed (we learn how to customize this below). The methods
```julia
Random.eltype(::Type{<:DiscreteDistribution}) = Int

function Random.Sampler(::Type{<:AbstractRNG}, distribution::DiscreteDistribution, ::Repetition)
    SamplerSimple(distribution, make_alias_table(distribution.probabilities))
end
```
should be defined to return a sampler with pre-computed data, then
```julia
function rand(rng::AbstractRNG, sp::SamplerSimple{<:DiscreteDistribution})
    draw_number(rng, sp.data)
end
```
will be used to draw the values.


#### [Custom sampler types](#Custom-sampler-types)
The `SamplerSimple` type is sufficient for most use cases with precomputed data. However, in order to demonstrate how to use custom sampler types, here we implement something similar to `SamplerSimple`.
Going back to our `Die` example: `rand(::Die)` uses random generation from a range, so there is an opportunity for this optimization. We call our custom sampler `SamplerDie`.
```julia
import Random: Sampler, rand

struct SamplerDie <: Sampler{Int} # generates values of type Int
    die::Die
    sp::Sampler{Int} # this is an abstract type, so this could be improved
end

Sampler(RNG::Type{<:AbstractRNG}, die::Die, r::Random.Repetition) =
    SamplerDie(die, Sampler(RNG, 1:die.nsides, r))
# the `r` parameter will be explained later on

rand(rng::AbstractRNG, sp::SamplerDie) = rand(rng, sp.sp)
```
It's now possible to get a sampler with `sp = Sampler(rng, die)`, and use `sp` instead of `die` in any `rand` call involving `rng`. In the simplistic example above, `die` doesn't need to be stored in `SamplerDie` but this is often the case in practice.
Of course, this pattern is so frequent that the helper type used above, namely `Random.SamplerSimple`, is available, saving us the definition of `SamplerDie`: we could have implemented our decoupling with:
```julia
Sampler(RNG::Type{<:AbstractRNG}, die::Die, r::Random.Repetition) =
    SamplerSimple(die, Sampler(RNG, 1:die.nsides, r))

rand(rng::AbstractRNG, sp::SamplerSimple{Die}) = rand(rng, sp.data)
```


### [Generating random values of custom types](#Generating-random-values-of-custom-types)
Here, `sp.data` refers to the second parameter in the call to the `SamplerSimple` constructor (in this case equal to `Sampler(rng, 1:die.nsides, r)`), while the `Die` object can be accessed via `sp[]`.
Like `SamplerDie`, any custom sampler must be a subtype of `Sampler{T}` where `T` is the type of the generated values. Note that `SamplerSimple(x, data) isa Sampler{eltype(x)}`, so this constrains what the first argument to `SamplerSimple` can be (it's recommended to use `SamplerSimple` like in the `Die` example, where `x` is simply forwarded while defining a `Sampler` method). Similarly, `SamplerTrivial(x) isa Sampler{eltype(x)}`.
Another helper type is currently available for other cases, `Random.SamplerTag`, but is considered as internal API, and can break at any time without proper deprecations.


#### [Using distinct algorithms for scalar or array generation](#Using-distinct-algorithms-for-scalar-or-array-generation)
In some cases, whether one wants to generate only a handful of values or a large number of values will have an impact on the choice of algorithm. This is handled with the third parameter of the `Sampler` constructor. Let's assume we defined two helper types for `Die`, say `SamplerDie1` which should be used to generate only few random values, and `SamplerDieMany` for many values. We can use those types as follows:
```julia
Sampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{1}) = SamplerDie1(...)
Sampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{Inf}) = SamplerDieMany(...)
```
Of course, `rand` must also be defined on those types (i.e. `rand(::AbstractRNG, ::SamplerDie1)` and `rand(::AbstractRNG, ::SamplerDieMany)`). Note that, as usual, `SamplerTrivial` and `SamplerSimple` can be used if custom types are not necessary.
Note: `Sampler(rng, x)` is simply a shorthand for `Sampler(rng, x, Val(Inf))`, and `Random.Repetition` is an alias for `Union{Val{1}, Val{Inf}}`.


### [Creating new generators](#Creating-new-generators)
The API is not clearly defined yet, but as a rule of thumb:
1.  any `rand` method producing "basic" types (`isbitstype` integer and floating types in `Base`) should be defined for this specific RNG, if they are needed;
2.  other documented `rand` methods accepting an `AbstractRNG` should work out of the box, (provided the methods from 1) what are relied on are implemented), but can of course be specialized for this RNG if there is room for optimization;
3.  `copy` for pseudo-RNGs should return an independent copy that generates the exact same random sequence as the original from that point when called in the same way. When this is not feasible (e.g. hardware-based RNGs), `copy` must not be implemented.
Concerning 1), a `rand` method may happen to work automatically, but it's not officially supported and may break without warnings in a subsequent release.
To define a new `rand` method for an hypothetical `MyRNG` generator, and a value specification `s` (e.g. `s == Int`, or `s == 1:10`) of type `S==typeof(s)` or `S==Type{s}` if `s` is a type, the same two methods as we saw before must be defined:
1.  `Sampler(::Type{MyRNG}, ::S, ::Repetition)`, which returns an object of type say `SamplerS`
2.  `rand(rng::MyRNG, sp::SamplerS)`


### [Creating new generators](#Creating-new-generators)
It can happen that `Sampler(rng::AbstractRNG, ::S, ::Repetition)` is already defined in the `Random` module. It would then be possible to skip step 1) in practice (if one wants to specialize generation for this particular RNG type), but the corresponding `SamplerS` type is considered as internal detail, and may be changed without warning.


#### [Specializing array generation](#Specializing-array-generation)
In some cases, for a given RNG type, generating an array of random values can be more efficient with a specialized method than by merely using the decoupling technique explained before. This is for example the case for `MersenneTwister`, which natively writes random values in an array.
To implement this specialization for `MyRNG` and for a specification `s`, producing elements of type `S`, the following method can be defined: `rand!(rng::MyRNG, a::AbstractArray{S}, ::SamplerS)`, where `SamplerS` is the type of the sampler returned by `Sampler(MyRNG, s, Val(Inf))`. Instead of `AbstractArray`, it's possible to implement the functionality only for a subtype, e.g. `Array{S}`. The non-mutating array method of `rand` will automatically call this specialization internally.


# [Reproducibility](#Reproducibility)
By using an RNG parameter initialized with a given seed, you can reproduce the same pseudorandom number sequence when running your program multiple times. However, a minor release of Julia (e.g. 1.3 to 1.4) *may change* the sequence of pseudorandom numbers generated from a specific seed, in particular if `MersenneTwister` is used. (Even if the sequence produced by a low-level function like [`rand`](#Base.rand) does not change, the output of higher-level functions like [`randsubseq`](#Random.randsubseq) may change due to algorithm updates.) Rationale: guaranteeing that pseudorandom streams never change prohibits many algorithmic improvements.
If you need to guarantee exact reproducibility of random data, it is advisable to simply *save the data* (e.g. as a supplementary attachment in a scientific publication). (You can also, of course, specify a particular Julia version and package manifest, especially if you require bit reproducibility.)
Software tests that rely on *specific* "random" data should also generally either save the data, embed it into the test code, or use third-party packages like [StableRNGs.jl](https://github.com/JuliaRandom/StableRNGs.jl). On the other hand, tests that should pass for *most* random data (e.g. testing `A \ (A*x) ≈ x` for a random matrix `A = randn(n,n)`) can use an RNG with a fixed seed to ensure that simply running the test many times does not encounter a failure due to very improbable data (e.g. an extremely ill-conditioned matrix).


# [Reproducibility](#Reproducibility)
The statistical *distribution* from which random samples are drawn *is* guaranteed to be the same across any minor Julia releases.
------------------------------------------------------------------------


# SHA · The Julia Language
Source: https://docs.julialang.org/en/v1/stdlib/SHA/


# [SHA](#SHA)


## [SHA functions](#SHA-functions)
Usage is very straightforward:
```julia-repl
julia> using SHA

julia> bytes2hex(sha256("test"))
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
```
Each exported function (at the time of this writing, SHA-1, SHA-2 224, 256, 384 and 512, and SHA-3 224, 256, 384 and 512 functions are implemented) takes in either an `AbstractVector{UInt8}`, an `AbstractString` or an `IO` object. This makes it trivial to checksum a file:
```julia
shell> cat /tmp/test.txt
test
julia> using SHA

julia> open("/tmp/test.txt") do f
           sha2_256(f)
       end
32-element Array{UInt8,1}:
 0x9f
 0x86
 0xd0
 0x81
 0x88
 0x4c
 0x7d
 0x65
    ⋮
 0x5d
 0x6c
 0x15
 0xb0
 0xf0
 0x0a
 0x08
```


### [All SHA functions](#All-SHA-functions)
Due to the colloquial usage of `sha256` to refer to `sha2_256`, convenience functions are provided, mapping `shaxxx()` function calls to `sha2_xxx()`. For SHA-3, no such colloquialisms exist and the user must use the full `sha3_xxx()` names.
`shaxxx()` takes `AbstractString` and array-like objects (`NTuple` and `Array`) with elements of type `UInt8`.
**SHA-1**
```julia
sha1(data)
```
Hash data using the `sha1` algorithm and return the resulting digest. See also [`SHA1_CTX`](#SHA.SHA1_CTX).
```julia
sha1(io::IO)
```
Hash data from io using `sha1` algorithm.
**SHA-2**
```julia
sha224(data)
```
Hash data using the `sha224` algorithm and return the resulting digest. See also [`SHA2_224_CTX`](#SHA.SHA2_224_CTX).
```julia
sha224(io::IO)
```
Hash data from io using `sha224` algorithm.
```julia
sha256(data)
```
Hash data using the `sha256` algorithm and return the resulting digest. See also [`SHA2_256_CTX`](#SHA.SHA2_256_CTX).
```julia
sha256(io::IO)
```
Hash data from io using `sha256` algorithm.
```julia
sha384(data)
```
Hash data using the `sha384` algorithm and return the resulting digest. See also [`SHA2_384_CTX`](#SHA.SHA2_384_CTX).
```julia
sha384(io::IO)
```
Hash data from io using `sha384` algorithm.
```julia
sha512(data)
```
Hash data using the `sha512` algorithm and return the resulting digest. See also [`SHA2_512_CTX`](#SHA.SHA2_512_CTX).
```julia
sha512(io::IO)
```
Hash data from io using `sha512` algorithm.
```julia
sha2_224(data)
```


### [All SHA functions](#All-SHA-functions)
Hash data using the `sha2_224` algorithm and return the resulting digest. See also [`SHA2_224_CTX`](#SHA.SHA2_224_CTX).
```julia
sha2_224(io::IO)
```
Hash data from io using `sha2_224` algorithm.
```julia
sha2_256(data)
```
Hash data using the `sha2_256` algorithm and return the resulting digest. See also [`SHA2_256_CTX`](#SHA.SHA2_256_CTX).
```julia
sha2_256(io::IO)
```
Hash data from io using `sha2_256` algorithm.
```julia
sha2_384(data)
```
Hash data using the `sha2_384` algorithm and return the resulting digest. See also [`SHA2_384_CTX`](#SHA.SHA2_384_CTX).
```julia
sha2_384(io::IO)
```
Hash data from io using `sha2_384` algorithm.
```julia
sha2_512(data)
```
Hash data using the `sha2_512` algorithm and return the resulting digest. See also [`SHA2_512_CTX`](#SHA.SHA2_512_CTX).
```julia
sha2_512(io::IO)
```
Hash data from io using `sha2_512` algorithm.
**SHA-3**
```julia
sha3_224(data)
```
Hash data using the `sha3_224` algorithm and return the resulting digest. See also [`SHA3_224_CTX`](#SHA.SHA3_224_CTX).
```julia
sha3_224(io::IO)
```
Hash data from io using `sha3_224` algorithm.
```julia
sha3_256(data)
```
Hash data using the `sha3_256` algorithm and return the resulting digest. See also [`SHA3_256_CTX`](#SHA.SHA3_256_CTX).
```julia
sha3_256(io::IO)
```
Hash data from io using `sha3_256` algorithm.
```julia
sha3_384(data)
```
Hash data using the `sha3_384` algorithm and return the resulting digest. See also [`SHA3_384_CTX`](#SHA.SHA3_384_CTX).
```julia
sha3_384(io::IO)
```
Hash data from io using `sha3_384` algorithm.


### [All SHA functions](#All-SHA-functions)
```julia
sha3_512(data)
```
Hash data using the `sha3_512` algorithm and return the resulting digest. See also [`SHA3_512_CTX`](#SHA.SHA3_512_CTX).
```julia
sha3_512(io::IO)
```
Hash data from io using `sha3_512` algorithm.


## [Working with context](#Working-with-context)
To create a hash from multiple items the `SHAX_XXX_CTX()` types can be used to create a stateful hash object that is updated with `update!` and finalized with `digest!`
```julia-repl
julia> using SHA

julia> ctx = SHA2_256_CTX()
SHA2 256-bit hash state

julia> update!(ctx, b"some data")
0x0000000000000009

julia> update!(ctx, b"some more data")
0x0000000000000017

julia> digest!(ctx)
32-element Vector{UInt8}:
 0xbe
 0xcf
 0x23
 0xda
 0xaf
 0x02
 0xf7
 0xa3
 0x57
 0x92
    ⋮
 0x89
 0x4f
 0x59
 0xd8
 0xb3
 0xb4
 0x81
 0x8b
 0xc5
```
Note that, at the time of this writing, the SHA3 code is not optimized, and as such is roughly an order of magnitude slower than SHA2.
```julia
update!(context, data[, datalen])
```
Update the SHA context with the bytes in data. See also [`digest!`](#SHA.digest!) for finalizing the hash.
**Examples**
```julia-repl
julia> ctx = SHA1_CTX()
SHA1 hash state

julia> update!(ctx, b"data to to be hashed")
```
```julia
digest!(context)
```
Finalize the SHA context and return the hash as array of bytes (Array{Uint8, 1}). Updating the context after calling `digest!` on it will error.
**Examples**
```julia-repl
julia> ctx = SHA1_CTX()
SHA1 hash state

julia> update!(ctx, b"data to to be hashed")

julia> digest!(ctx)
20-element Array{UInt8,1}:
 0x83
 0xe4
 ⋮
 0x89
 0xf5

julia> update!(ctx, b"more data")
ERROR: Cannot update CTX after `digest!` has been called on it
[...]
```


### [All SHA context types](#All-SHA-context-types)
**SHA-1**
```julia
SHA1_CTX()
```
Construct an empty SHA1 context.
**SHA-2**
Convenience types are also provided, where `SHAXXX_CTX` is a type alias for `SHA2_XXX_CTX`.
```julia
SHA2_224_CTX()
```
Construct an empty SHA2_224 context.
```julia
SHA2_256_CTX()
```
Construct an empty SHA2_256 context.
```julia
SHA2_384()
```
Construct an empty SHA2_384 context.
```julia
SHA2_512_CTX()
```
Construct an empty SHA2_512 context.
```julia
SHA2_224_CTX()
```
Construct an empty SHA2_224 context.
```julia
SHA2_256_CTX()
```
Construct an empty SHA2_256 context.
```julia
SHA2_384()
```
Construct an empty SHA2_384 context.
```julia
SHA2_512_CTX()
```
Construct an empty SHA2_512 context.
**SHA-3**
```julia
SHA3_224_CTX()
```
Construct an empty SHA3_224 context.
```julia
SHA3_256_CTX()
```
Construct an empty SHA3_256 context.
```julia
SHA3_384_CTX()
```
Construct an empty SHA3_384 context.
```julia
SHA3_512_CTX()
```
Construct an empty SHA3_512 context.


## [HMAC functions](#HMAC-functions)
```julia-repl
julia> using SHA

julia> key = collect(codeunits("key_string"))
10-element Vector{UInt8}:
 0x6b
 0x65
 0x79
 0x5f
 0x73
 0x74
 0x72
 0x69
 0x6e
 0x67

julia> bytes2hex(hmac_sha3_256(key, "test-message"))
"bc49a6f2aa29b27ee5ed1e944edd7f3d153e8a01535d98b5e24dac9a589a6248"
```
To create a hash from multiple items, the `HMAC_CTX()` types can be used to create a stateful hash object that is updated with `update!` and finalized with `digest!`.
```julia-repl
julia> using SHA

julia> key = collect(codeunits("key_string"))
10-element Vector{UInt8}:
 0x6b
 0x65
 0x79
 0x5f
 0x73
 0x74
 0x72
 0x69
 0x6e
 0x67

julia> ctx = HMAC_CTX(SHA3_256_CTX(), key);

julia> update!(ctx, b"test-")
0x0000000000000000000000000000008d

julia> update!(ctx, b"message")
0x00000000000000000000000000000094

julia> bytes2hex(digest!(ctx))
"bc49a6f2aa29b27ee5ed1e944edd7f3d153e8a01535d98b5e24dac9a589a6248"
```


### [All HMAC functions](#All-HMAC-functions)
**HMAC context type**
```julia
HMAC_CTX(ctx::CTX, key::Vector{UInt8}) where {CTX<:SHA_CTX}
```
Construct an empty HMAC_CTX context.
**SHA-1**
```julia
hmac_sha1(key, data)
```
Hash data using the `sha1` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha1(key, io::IO)
```
Hash data from `io` with the passed key using `sha1` algorithm.
**SHA-2**
```julia
hmac_sha224(key, data)
```
Hash data using the `sha224` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha224(key, io::IO)
```
Hash data from `io` with the passed key using `sha224` algorithm.
```julia
hmac_sha256(key, data)
```
Hash data using the `sha256` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha256(key, io::IO)
```
Hash data from `io` with the passed key using `sha256` algorithm.
```julia
hmac_sha384(key, data)
```
Hash data using the `sha384` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha384(key, io::IO)
```
Hash data from `io` with the passed key using `sha384` algorithm.
```julia
hmac_sha512(key, data)
```
Hash data using the `sha512` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha512(key, io::IO)
```
Hash data from `io` with the passed key using `sha512` algorithm.
```julia
hmac_sha2_224(key, data)
```
Hash data using the `sha2_224` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha2_224(key, io::IO)
```


### [All HMAC functions](#All-HMAC-functions)
Hash data from `io` with the passed key using `sha2_224` algorithm.
```julia
hmac_sha2_256(key, data)
```
Hash data using the `sha2_256` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha2_256(key, io::IO)
```
Hash data from `io` with the passed key using `sha2_256` algorithm.
```julia
hmac_sha2_384(key, data)
```
Hash data using the `sha2_384` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha2_384(key, io::IO)
```
Hash data from `io` with the passed key using `sha2_384` algorithm.
```julia
hmac_sha2_512(key, data)
```
Hash data using the `sha2_512` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha2_512(key, io::IO)
```
Hash data from `io` with the passed key using `sha2_512` algorithm.
**SHA-3**
```julia
hmac_sha3_224(key, data)
```
Hash data using the `sha3_224` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha3_224(key, io::IO)
```
Hash data from `io` with the passed key using `sha3_224` algorithm.
```julia
hmac_sha3_256(key, data)
```
Hash data using the `sha3_256` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha3_256(key, io::IO)
```
Hash data from `io` with the passed key using `sha3_256` algorithm.
```julia
hmac_sha3_384(key, data)
```
Hash data using the `sha3_384` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha3_384(key, io::IO)
```


### [All HMAC functions](#All-HMAC-functions)
Hash data from `io` with the passed key using `sha3_384` algorithm.
```julia
hmac_sha3_512(key, data)
```
Hash data using the `sha3_512` algorithm using the passed key. See also [`HMAC_CTX`](#SHA.HMAC_CTX).
```julia
hmac_sha3_512(key, io::IO)
```
Hash data from `io` with the passed key using `sha3_512` algorithm.
------------------------------------------------------------------------


# Serialization · The Julia Language
Source: https://docs.julialang.org/en/v1/stdlib/Serialization/