Hacker News new | ask | show | jobs
by nwg 4076 days ago
> default argument values are a property of named functions, not of function types, and cannot be expressed in the type system.

For what reason? Isn't the gripe exactly with the fact that it's not implemented?

Also why are arguments required to be named in all calls after the first, but not the first?

func f(a: Int)(b: Int)(c: Int) -> Int { return a + b + c }

let v = f(2)(b: 5)(c: 5)

Stuff like this just eats at me when i use a language, especially when that language is brand new and other languages have had nice syntax for similar features for a long time.

2 comments

> For what reason? Isn't the gripe exactly with the fact that it's not implemented?

How should it be represented in the type system? There's no clear answer to that question.

The type of a function is `(Args) -> Ret`. `->` is basically an infix type constructor with two type parameters; it's basically sugar for something along the lines of `Func<(Args),Ret>` (except there's no actual type named that). The arguments list here is actually just a tuple, and functions with named arguments have an arguments list which is a tuple with named fields (since Swift supports that). Given all this, I don't see how default parameters could be crammed in. At a syntactic level, you could say something like `(a: Int = default, b: String = default) -> String`, but when you realize that the arguments list is a tuple, a "tuple with default field values" is a nonsense thing to try and construct.

Also, more generally, a function with default parameters is actually a family of functions, one for each valid combination of parameters. But a function value is a single function, not a family of functions. When you think about it like that, trying to return a function value with default parameters makes no more sense than trying to return a generic function that hasn't been instantiated with concrete type parameters (e.g. you cannot say `func foo() -> (<T>(x: T) -> T)` or anything along those lines). Function values must be a single concrete function, not a family of functions.

They're not required, they just default to having a name. You can tell the compiler you don't want a name, and it works:

    func f(a: Int)(_ b: Int)(_ c: Int) -> Int { return a + b + c }
    let v = f(2)(5)(5)
The rules for what gets an externally visible name automatically are pretty weird, to be sure. But it's easy to have it do what you want if you don't want the default.