Apply for closure


(James Campbell) #1

This is a discussion inspired by the recent proposal of Chris to remove turple splats.

I would like to propose we add a apply method for all closures.

What would the syntax look like?

To apply a bunch of variables to a normal function and call it we can first access it's closure like so

object.foo

Since this returns a closure to use apply we just do this

object.foo.apply(...)

When it comes to anonymous closures we can do the same:

closure.apply(...)

So why would we need this?

This is an alternative way of performing actions that you would normally do via NSInvocation and I feel it also opens the doors for things other people have proposed else where like partial initialisers.

So how would the syntax work?

The compiler would allow you to pass in a array which will be splatted to have all of its arguments applied. This would be useful for applying vargs.

closure.apply(args:[12])

Since this is only applied to closures the compiler knows how many arguments an array should have and what value.

Additionally it could allow turples to replace the previous splat behviour

closure.apply(turple:(12))

My last is what I call a symbol hash:

closure.apply([
.argument: 12
])

It allows you to pass in dictionary to be used to construct the arguments.

The keys are a special generated symbol(enums maybe) that represent the argument label. The value for each key is passed to the relevant argument.

This allows you to construct a struct without having to pass all the parameters. Which is great for functional programming as you could allow people to partially initialise a struct or to return a new copy with one value mutated (currently this requires a huge amount of boilerplate)

struct.copyWithMutation.apply([
.name: "hey"
])

I know nothing about compilers so would love to hear your thoughts. This makes the most sense to me coming from a ruby and JavaScript background

···

Sent from my iPhone


(Tino) #2

I have no obvious use case, but I like the concept of "functions having functions":
It is most likely not that relevant for Swift 3, but as soon as the macro-system becomes concrete, it could be valuable for meta-programming…

Besides "apply", we could have introspection ("f.parametersByIndex[0].type") and a revival of currying
let twice: (Double) -> Double = *.curry(parameterIndex: 0, value: 2.0)

It could even be possible to do meta-programming without leaving the language, e.g.

class Snitch: SomeClass {
  for f in super.overridableMethods {
    self.implementation[f] = { (args: f.argumentTuple) in
      print("Function \(f.name) has been called with \(args)")
      return f.apply(args)
    }
  }
}

I probably would hate anyone actually using such a feature (unless the debugger is really great ;-), but it would be freaking cool nonetheless :wink:

Tino


(James Campbell) #3

I think making functions first class citizens would be mega cool

···

Sent from my iPhone

On 28 Jan 2016, at 13:07, Tino Heth <2th@gmx.de> wrote:

I have no obvious use case, but I like the concept of "functions having functions":
It is most likely not that relevant for Swift 3, but as soon as the macro-system becomes concrete, it could be valuable for meta-programming…

Besides "apply", we could have introspection ("f.parametersByIndex[0].type") and a revival of currying
let twice: (Double) -> Double = *.curry(parameterIndex: 0, value: 2.0)

It could even be possible to do meta-programming without leaving the language, e.g.

class Snitch: SomeClass {
   for f in super.overridableMethods {
       self.implementation[f] = { (args: f.argumentTuple) in
           print("Function \(f.name) has been called with \(args)")
           return f.apply(args)
       }
   }
}

I probably would hate anyone actually using such a feature (unless the debugger is really great ;-), but it would be freaking cool nonetheless :wink:

Tino