Arity constraint on Julialang function type - function

Is it possible to specify a type constraint on arity of a Julia function, something like:
function foo(bar::Function{1})
...
end
This definition gives me an error:
ERROR: too many parameters for type Function

What you are asking is not possible, since a Julia function does not have well-defined arity.
Consider
f(x) = "method 1"
f(x, y) = "method 2"
after which f may be invoked in two ways:
julia> f(0)
"method 1"
julia> f(0, 0)
"method 2"
What, then, is the arity of f? If you are seeking to change behaviour of the function depending on its arity, then you need to pass in the desired arity as an additional parameter. Otherwise, the arity check can probably be left out.

Most probably, the arity constraint is needed to ensure parameter correctness. This does not need to be done in the function signature, but can be done using parameter checks at the top of the function code. One method could be:
if !any(m->length(m.sig.parameters)==2, methods(bar))
error("bar must be callable with 2 parameters")
end
More detailed checks on the signature of bar are also possible.
The declared parameter types of the function foo are idiomatically used to direct optimization through type inference and multiple dispatch and less to validate parameters.
Note that using the internal structure of MethodTable and Method types is not official Julia spec and might be subject to change in future versions of Julia.

Related

Functional parameters in Go functions

Is there a way to pass a function(which can be generic) to another function?
I know that with known input types and return types we can pass a function but a generic approach is needed
When reading the Go2 proposal on generic: "Type Parameters - Draft Design", I am not sure you would be able to pass as parameter a generic function without explicitly specify the type used by said function
See "Instantiating a function"
Go normally permits you to refer to a function without passing any arguments, producing a value of function type.
You may not do this with a function that has type parameters; all type arguments must be known at compile time.
That said, you can instantiate the function, by passing type arguments, but you don't have to call the instantiation. This will produce a function value with no type parameters.
// PrintInts is type func([]int).
var PrintInts = Print[int]

Any efficient way of using Julia in Jupyter without restarting the kernel for redefining variables/functions?

So I have been trying to adapt my python codes to Julia instead of fortran mainly because of the fact I have Jupiter to easily test my work on the fly. But in Julia 1, I am unable to find any easy way to redefine a already defined function in another cell to test it out.
For instance
function a(b);return b+4;end
and then in next cell I would like to test instead loose the condition and have it something like
function a(b,c);return b+c;end
But I do not want to change the name because I have other dependent functions in which I call a. The reason to do this is for prototyping the best possible way to define a and obviously this wouldn't be a part of the main code.
Any way how to do this ?
Julia uses multiple dispatch and these are two different functions (or more exactly two different methods of the same function). Hence, no change of name is needed.
julia> function a(b);return b+4;end
a (generic function with 1 method)
julia> function a(b,c);return b+c;end
a (generic function with 2 methods)
julia> methods(a)
# 2 methods for generic function "a":
[1] a(b) in Main at REPL[1]:1
[2] a(b, c) in Main at REPL[2]:1
Basically, rerunning a Jupyter cell will redefine the function (if it is the same set of parameter types) so there is no problem here.
More complicated situation is when you want to change a type of a constants because they go deeper into compiler. Constants cannot change their type.
Functions are constants. Hence, if you try to assign a non-function type it will trow an error.
julia> typeof(a) <: Function
true
julia> a = 5
ERROR: invalid redefinition of constant a
Stacktrace:
[1] top-level scope at REPL[9]:1

How to do type checking for a recursive function with no explicit return type?

I am writing a language where functions are not typed. Which means I need to infer the return type of a function call in order to do type checking. However when somebody writes a recursive function the type checker goes into an infinite recursion trying to infer the type of the function call inside the function body.
The type checker does something like this:
Infer the types of the function call actual arguments.
Create a mapping of the actual argument types to the formal arguments.
Use the mapping to annotate types on the arguments used inside the function body.
Infer and return the return type of the function body.
Step 4 tries to then infer the type of the function call inside the function body, which calls the same type checker function again, causing an infinite recursion.
An example of a recursive function that gives me this problem:
function factorial(n) = n<1 ? 1 : n*factorial(n-1); // Function definition.
...
assert 24 == factorial(4); // Function call expression usage example.
How can I solve this problem without going in to an infinite recursion loop? Is there a way to infer the type of the recursive function call without having to go into the body again? Or some clean way to infer the type from context?
I know the easy solution might be to add types annotations to functions, this way the problem is trivial, but before doing that I want to know if there is a way to solve this without resorting to that.
I'd also like for the solution to work for mutual recursion.
Type inference can vary a lot depending on the language's type system and on what properties you want to have in terms of when annotations are needed. But whatever your language looks like, I think there's one seminal case you really should read about, which is ML. ML's type inference holds a nice sweet spot where it all fits together in a relatively simple paradigm. No type annotations are needed, and any expression has a single most general type (this property is called principality of typing).
ML's type system is the Hindley-Milner type system, which has parametric polymorphism. The type of an expression is either a specific type, or “any”. More precisely, the type constructor of an expression is either a specific type constructor or “any”, and type constructors can have arguments which themselves either have a specific type constructor or “any”. For example, the empty list has the type “list of any”. Two expressions that can have “any” type in isolation may be constrained to have the same type, whatever it is, so “any” is expressed with variables. For example, function list_of_two(x, y) = [x, y] (in a notation like your language) constrains x and y to have the same type, because they're inserted in the same list, but that type can be any type, so the type of this function is “take any two parameters of the same type α, and return a value of type list of α”.
The basic type inference algorithm for Hindley-Milner is algorithm W. At its core, it works by giving each subexpression a type that's a variable: α₁, α₂, α₃, … Programming language constructions then impose constraints on those variables. For example, if a list contains two elements of types α₁ and α₂ and the list itself has the type α₃, this constraints α₁ = α₂ and α₃ = list of α₁. Putting all these constraints together is a unification problem.
The constraints are based on a purely syntactic reading of the program. If there's a recursive call, you don't need to know the type of the function: it just means that there's a constraint that the variable for the return type of the function is the same as the type at its point of use. That's just one more equation to add to the set of constraints.
I left out an important aspect of ML which is that an expression's type can be generalized: an expression can be used with different types at different places. This is what allows polymorphism. For example,
let empty_list = [] in
(empty_list # [3]), (empty_list # ["hello"])
is a valid program where empty_list is used once with the type “list of integers” and once with the type “list of strings”. The type of empty_list is “for any α, list of α”: that's parametric polymorphism. Generalization adds some complexity to the algorithm, but it also removes complexity elsewhere, because that's what allows principality. Without it, let empty_list = [] in … would be ambiguous: empty_list would have to have some type, but there's no way to know what type without analyzing …, and then when you do analyze the … above you'd need to make a choice between integer and string.
Depending on your language's type system, ML and algorithm W may be directly reusable or may just provide some vague inspiration. But the principle of using variables during the inference, and progressively constraining these variables, is very general.

What happens if we add different parameter type in a function interface of a lambda expression?

I am learning lambda expressions. I came across a scenario that can be understood by the below code:
Function<Integer,String> fn = (String s)->s;
In the above statement of lambda expression, I know that a function accepts an argument and returns the mentioned type. But why do we mention the argument type ,(here, it is Integer) on the part "Function" whereas the arguments are to be passed inside the "()". I know it is part of the syntax, but I just want to understand the point where it may be useful. It runs even if we pass an different argument type(String)?
First of all the Function you have written is wrong. It should be corrected as below.
Function<Integer, String> fn = s -> String.valueOf(s);
You can't state a different data type as above, only thing you can state is an integer. Any other data type as the input parameter would result in a compilation failure. The data type of the lambda function parameter is optional and is inferred by the compiler.

What are the definitions of named method and named function?

I have read the question Difference between method and function in Scala and many articles about differences between method and function. I got a feeling that a 'method' is just a "named function" defined as a method in a class, a trait or an object. A 'function' represents things like the "anonymous function" or "function literal" or "function object" in those articles. An evidence can be found in the book Programming in Scala http://www.artima.com/shop/programming_in_scala_2ed , page 141, section 8.1, "The most common way to define a function is as a member of some object. Such a function is called a method."
However, when I checked the Scala Language Reference http://www.scala-lang.org/docu/files/ScalaReference.pdf, there are concepts like named method. In page 91, Section 6.20 Return expressions: "A return expression return e must occur inside the body of some enclosing named
method or function." You can also find the term "named function" in the same page and other places.
So my question is, in Scala, do method, named method, and named function refer to the same concept? Where do you get the definition of named function?
In code List(1, 2).map(_ + 1), the original expression _ + 1 is a named method, then the method is converted into a function. What kind of function, anonymous function, function object, named function?
In my understanding, Scala only has two types of function: a named function that is a method; an anonymous function that is a function literal. Function literal is compiled into a function object of trait FunctionN for it to be used in the pure object-oriented world of Scala.
However, for a regular named funciton/method such as _ + 1 in the above code, why does Scala transform it into another function object?
At the language level, there are only two concepts,
Methods are fundamental building blocks of Scala. Methods are always named. Methods live in classes or traits. Methods are a construct native to the JVM, and thus are the same in both Scala and Java. Methods in Scala (unlike functions) may have special features: they can be abstracted over type parameters, their arguments can have default values or be implicit, etc.
Function objects are just instances of a function trait (Function1, Function2, ...). The function is evaluated when the apply method on the function object is called. There is special syntax for defining unnamed "anonymous" functions (aka, "function literals"). A function is just a value, and as such can be named (e.g., val f: (Int => Int) = (x => x)). The type A => B is shorthand for Function1[A, B].
In the linked SO question, it was mentioned that some references (like the Scala spec) use the word "function" imprecisely to mean either "method" or "function object". I guess part of the reason is that methods can be automatically converted to function objects, depending on the context. Note, however, that the opposite conversion wouldn't make sense: a method is not a first-class value that lives on the heap with its own independent existence. Rather, a method is inextricably linked to the class in which it is defined.
The answers to the linked question cover this fairly well, but to address your specific queries:
method => The thing you define with the def keyword
named method => The same, all methods have names
named function => a function that has been assigned to a value, or converted from a method. As contrasted with an anonymous function.
The difference between a method and a Function is somewhat like the difference between an int primitive and a boxed Integer in Java.
In general discussion, it's common to hear both described as being "integers". This normally isn't a problem, but you must take care to be precise wherever the distinction is relevant.
Likewise, a method will be automatically converted to a Function (and therefore an object) when your program demands it, much like boxing a primitive. So it's not entirely wrong to refer to a method as being a function.
UPDATE
So how does it work?
When you attempt to pass a method as the argument to e.g. List[A].map, the compiler will generate an inner class (with a synthetic name) that derives Function1[A,B], and an apply method that delegates to the method you originally supplied. An instance of this will then be passed as the actual argument.