I want to feed a set of varargs into #evalpoly. I tried the following:
tup = (1,2,3,4,5);
#evalpoly(40, tup...)
But this gives a BoundsError. However, according to the Standard Library, #evalpoly(z, c...) gives a polynomial evaluation. Is the ... used in the Standard Library definition different from the usual varargs syntax? Or am I simply misusing the varargs syntax?
Related
Compared to the Python documentation, I find that Julia documentation are much harder to read.
For example, the rand function:
rand([rng=GLOBAL_RNG], [S], [dims...])
How should I interpret this? What do the brackets mean? Which parameters are optional, and which are not?
Also, in Flux's documentation for Dense:
Dense(in, out, σ=identity; bias=true, init=glorot_uniform)
Why are some parameters separated by commas and others by semicolons?
The parameters is square brackets [] are optional - this is a convention for documentation across many programming languages - this is not a part of language syntax though. Hence all parameters for rand are optional and you can do just rand.
Actually it is a good idea to try to type methods(rand) in the console to see the huge number of methods required to cover all such use cases:
julia> methods(rand)
# 80 methods for generic function "rand":
[1] rand() in Random at c:\Julia-1.7.2\share\julia\stdlib\v1.7\Random\src\Random.jl:257
.....
Semicolon is a part of syntax used for separating positional parameters from named parameters in Julia functions.
As an example consider a function:
function foo(a, b=4; c, d=8)
return a+b+c+d
end
Than you could do:
julia> foo(1,c=100)
113
I am puzzled by the following results of typeof in the Julia 1.0.0 REPL:
# This makes sense.
julia> typeof(10)
Int64
# This surprised me.
julia> typeof(function)
ERROR: syntax: unexpected ")"
# No answer at all for return example and no error either.
julia> typeof(return)
# In the next two examples the REPL returns the input code.
julia> typeof(in)
typeof(in)
julia> typeof(typeof)
typeof(typeof)
# The "for" word returns an error like the "function" word.
julia> typeof(for)
ERROR: syntax: unexpected ")"
The Julia 1.0.0 documentation says for typeof
"Get the concrete type of x."
The typeof(function) example is the one that really surprised me. I expected a function to be a first-class object in Julia and have a type. I guess I need to understand types in Julia.
Any suggestions?
Edit
Per some comment questions below, here is an example based on a small function:
julia> function test() return "test"; end
test (generic function with 1 method)
julia> test()
"test"
julia> typeof(test)
typeof(test)
Based on this example, I would have expected typeof(test) to return generic function, not typeof(test).
To be clear, I am not a hardcore user of the Julia internals. What follows is an answer designed to be (hopefully) an intuitive explanation of what functions are in Julia for the non-hardcore user. I do think this (very good) question could also benefit from a more technical answer provided by one of the more core developers of the language. Also, this answer is longer than I'd like, but I've used multiple examples to try and make things as intuitive as possible.
As has been pointed out in the comments, function itself is a reserved keyword, and is not an actual function istself per se, and so is orthogonal to the actual question. This answer is intended to address your edit to the question.
Since Julia v0.6+, Function is an abstract supertype, much in the same way that Number is an abstract supertype. All functions, e.g. mean, user-defined functions, and anonymous functions, are subtypes of Function, in the same way that Float64 and Int are subtypes of Number.
This structure is deliberate and has several advantages.
Firstly, for reasons I don't fully understand, structuring functions in this way was the key to allowing anonymous functions in Julia to run just as fast as in-built functions from Base. See here and here as starting points if you want to learn more about this.
Secondly, because each function is its own subtype, you can now dispatch on specific functions. For example:
f1(f::T, x) where {T<:typeof(mean)} = f(x)
and:
f1(f::T, x) where {T<:typeof(sum)} = f(x) + 1
are different dispatch methods for the function f1
So, given all this, why does, e.g. typeof(sum) return typeof(sum), especially given that typeof(Float64) returns DataType? The issue here is that, roughly speaking, from a syntactical perspective, sum needs to serves two purposes simultaneously. It needs to be both a value, like e.g. 1.0, albeit one that is used to call the sum function on some input. But, it is also needs to be a type name, like Float64.
Obviously, it can't do both at the same time. So sum on its own behaves like a value. You can write f = sum ; f(randn(5)) to see how it behaves like a value. But we also need some way of representing the type of sum that will work not just for sum, but for any user-defined function, and any anonymous function. The developers decided to go with the (arguably) simplest option and have the type of sum print literally as typeof(sum), hence the behaviour you observe. Similarly if I write f1(x) = x ; typeof(f1), that will also return typeof(f1).
Anonymous functions are a bit more tricky, since they are not named as such. What should we do for typeof(x -> x^2)? What actually happens is that when you build an anonymous function, it is stored as a temporary global variable in the module Main, and given a number that serves as its type for lookup purposes. So if you write f = (x -> x^2), you'll get something back like #3 (generic function with 1 method), and typeof(f) will return something like getfield(Main, Symbol("##3#4")), where you can see that Symbol("##3#4") is the temporary type of this anonymous function stored in Main. (a side effect of this is that if you write code that keeps arbitrarily generating the same anonymous function over and over you will eventually overflow memory, since they are all actually being stored as separate global variables of their own type - however, this does not prevent you from doing something like this for n = 1:largenumber ; findall(y -> y > 1.0, x) ; end inside a function, since in this case the anonymous function is only compiled once at compile-time).
Relating all of this back to the Function supertype, you'll note that typeof(sum) <: Function returns true, showing that the type of sum, aka typeof(sum) is indeed a subtype of Function. And note also that typeof(typeof(sum)) returns DataType, in much the same way that typeof(typeof(1.0)) returns DataType, which shows how sum actually behaves like a value.
Now, given everything I've said, all the examples in your question now make sense. typeof(function) and typeof(for) return errors as they should, since function and for are reserved syntax. typeof(typeof) and typeof(in) correctly return (respectively) typeof(typeof), and typeof(in), since typeof and in are both functions. Note of course that typeof(typeof(typeof)) returns DataType.
I am trying to understand the new type system in Julia v0.6, based on reading the release notes.
Can anyone tell me what
inv(M::Matrix{T}) where T <: AbstractFloat
gives me which is different from using the classic
inv{T<:AbstractFloat}(M::Matrix{T})
?
The new syntax means the same thing but can be used in more circumstances and can express more constructs and eliminates a number of conceptual ambiguities, especially surrounding parametric constructors. The old syntax will be deprecated in 0.6 and some of the old syntax will be reclaimed with different meaning in 1.0. Fundamentally, the problem with F{T}(args...) is that the F{T} part is conceptually ambiguous – the parser knows what it means, but it's often confusing to humans:
In isolation F{T} means the parametric type F with type parameter T.
Followed by parens, not as part of a method definition, F{T}(args...) means to apply the type F{T} to the arguments args... as a function, typically constructing an instance of the type F{T}.
Followed by parens and equals, i.e. as part of a method definition as in F{T}(args...) = expr, it means to define a method for F as a function, with type parameters T formal arguments args... and definition expr.
In particular, there is no syntax for either of these:
Adding a method to F{T} for the concrete value of T in the current scope.
Adding a method to F{T} for each parametric value T.
This situation causes constructor syntax in Julia 0.5 and prior to be more confusing and unintuitive than necessary. In Julia 1.0 type parameters and constructors will be both more intuitive and consistent, following these principles:
The syntax used to define a method always matches the syntax used to call it.
The F{T} syntax always refers to the type F with parameter T.
Type parameters are always introduced by where clauses.
There will be a more detailed explanation of the changes when 0.6 comes out, probably in a blog post on highlights of the 0.6 release.
Is there a command in Julia that lists all the methods that are available in a package?
For example I load up Distributions
using Distributions
and now I would like to see what function to call to draw a random value from a normal distribution. Is there a good way to do this from inside of Julia without a google search?
Sort of, although I don't think its of much utility:
julia> using Distributions
julia> names(Distributions)
215-element Array{Symbol,1}:
:median
:logpdf
:logpmf!
:Chisq
:posterior_rand
:fit_mle!
:NegativeBinomial
:posterior_rand!
:ContinuousMatrixDistribution
:ValueSupport
:InverseGamma
:complete
:TDist
:NormalCanon
:SufficientStats
:Chi
:logpmf
:logdetcov
:Gumbel
:Sampleable
...
or non-programmatically, using
julia> whos(Distributions)
AbstractMixtureModel DataType
AbstractMvNormal DataType
Arcsine DataType
Bernoulli DataType
Beta DataType
BetaPrime DataType
Binomial DataType
I think that with the inclusion of an inbuilt documentation system in Julia 0.4, we'll get way more packages with docs available at the REPL.
Lambda term can be:
variable
lambda abstraction (for example \x.t)
application. If t and s are lambda terms, then ts is an application.
So, application with abstraction in the left part (for example (\x.t)a) looks good. It looks like function calling. But what does application mean when left part is a variable or other application? What does mean ab, ((\x.x)a)b or a(\x.x) if a and b are variables?
((\x.x)b)c is a function application. Here It applies b to c.
((\x.x)b)c
= bc
a(\x.y) is a function application, applying the function a to its sole argument, which happens to be a function, namely the function that returns y (a free variable).
One of the featues of the lamdba calculus is the ease in which functions can be applied to functions and functions can take other functions as arguments. Your two examples show both cases nicely.
EDIT There are (at least) two versions of the lambda calculus: the untyped and the typed. In the untyped calculus, which you are using here, anything can be applied to anything. In the typed calculus there exist base types which are not functions, such as the type of propositions and the type of "individuals." So you would only be able to write ab if the type of a were a function type mapping the type of b to something.