Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions doc/src/manual/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,50 @@ julia> NoFieldsParam{Int}() === NoFieldsParam{Int}()
true
```

## Types of functions

Each function has its own type, which is a subtype of `Function`.

```jldoctest foo41
julia> foo41(x) = x + 1
foo41 (generic function with 1 method)

julia> typeof(foo41)
typeof(foo41) (singleton type of function foo41, subtype of Function)
```

Note how `typeof(foo41)` prints as itself. This is merely a convention for printing, as it is a first-class object that can be used like any other value:

```jldoctest foo41
julia> T = typeof(foo41)
typeof(foo41) (singleton type of function foo41, subtype of Function)

julia> T <: Function
true
```

Types of functions defined at top-level are singletons. When necessary, you can compare them with [`===`](@ref).

[Closures](@id man-anonymous-functions) also have their own type, which is usually printed with names that end in `#<number>`. Names and types for functions defined at different locations are distinct, but not guaranteed to be printed the same way across sessions.

```jldoctest; filter = r"[0-9\.]+"
julia> typeof(x -> x + 1)
var"#9#10"
```

Types of closures are not necessarily singletons.

```jldoctest
julia> addy(y) = x -> x + y
addy (generic function with 1 method)

julia> Base.issingletontype(addy(1))
false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
false
false
julia> addy(1).y
1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't closures having fields an implementation detail, something we would not necessarily want to expose in the user manual?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't call that an implementation detail. It is a defining feature of closures.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't sound like a defining feature of closures, after all they were implemented differently in the past, and the field names could have been made unavailable through getproperty even with the current implementation. But I don't know whether that's now specified somewhere in the documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in the dev docs.

Incidentally, is it OK to link devdocs in the user manual?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't sound like a defining feature of closures, after all they were implemented differently in the past, and the field names could have been made unavailable through getproperty even with the current implementation.

I actually didn't know that, thanks! I suspect that changing this now would be quite breaking, so we can probably document this somewhere, but we can leave it out of this PR for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incidentally, is it OK to link devdocs in the user manual?

I didn't notice that at first. We should probably have something on closures n the regular docs as well, but for now, maybe we can just have the link point to anonymous functions instead, since in most cases they are actually closures as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in the dev docs.

Thanks. As the "dev docs" document Julia internals, I wouldn't link to the them from the user manual. To show the point here, you might insert in the sessions addy(1) === addy(2) # false, and/or maybe show the output of addy(1) (i.e. var"#3#4"{Int64}(1), which hints at the implementation detail).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I added that example, and now only refer to closures in passing.


julia> addy(1) === addy(2)
false
```

## [`Type{T}` type selectors](@id man-typet-type)

For each type `T`, `Type{T}` is an abstract parametric type whose only instance is the
Expand Down