[Proposal] Add support for compile-time function execution


(Alexander Momchilov) #1

Preface: I know this is likely a large undertaking to implement, but I think it's worth it.

In addition to the typical compiler optimization of constant math expressions, some languages (such as D and C++) have support for running arbitrary functions at compile time <https://en.wikipedia.org/wiki/Compile_time_function_execution> (with some constraints).

I see many advantages of this:
On iOS/OS X: it could precompute the UI and app initialization logic (wherever possible) to speed app load times
It can significantly speed up the initialization of applications with large static properties. E.g. large constant Dictionaries could be precomputed.
You could keep complex math expressions (including custom functions) in their unevaluated form, without the pressure to precompute them elsewhere and hardcode in the result.
Dynamic programming: expensive look-up tables could be precomputed. These wouldn't necessarily be large in size, but if their elements are especially expensive to compute, there would be a huge advantage to precomputing them.

What do you guys think? Can you think of any other useful applications? Would it be worth the implementation effort?

- Regards,
        Alexander Momchilov


(L Mihalkovic) #2

Chris has rules macros out-of-scope for 3.0. Who knows, maybe they'll be allowable in 4.0

···

On Jun 9, 2016, at 1:41 AM, Alexander Momchilov via swift-evolution <swift-evolution@swift.org> wrote:

Preface: I know this is likely a large undertaking to implement, but I think it's worth it.

In addition to the typical compiler optimization of constant math expressions, some languages (such as D and C++) have support for running arbitrary functions at compile time (with some constraints).

I see many advantages of this:
On iOS/OS X: it could precompute the UI and app initialization logic (wherever possible) to speed app load times
It can significantly speed up the initialization of applications with large static properties. E.g. large constant Dictionaries could be precomputed.
You could keep complex math expressions (including custom functions) in their unevaluated form, without the pressure to precompute them elsewhere and hardcode in the result.
Dynamic programming: expensive look-up tables could be precomputed. These wouldn't necessarily be large in size, but if their elements are especially expensive to compute, there would be a huge advantage to precomputing them.

What do you guys think? Can you think of any other useful applications? Would it be worth the implementation effort?

- Regards,
        Alexander Momchilov
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Jean-Daniel) #3

Preface: I know this is likely a large undertaking to implement, but I think it's worth it.

In addition to the typical compiler optimization of constant math expressions, some languages (such as D and C++) have support for running arbitrary functions at compile time <https://en.wikipedia.org/wiki/Compile_time_function_execution> (with some constraints).

I see many advantages of this:
On iOS/OS X: it could precompute the UI and app initialization logic (wherever possible) to speed app load times

I can’t see how it would speed up app launch time. You still all have to allocate and init all UI objects, especially as they are opaque objects and can’t be precomputed.

···

Le 9 juin 2016 à 01:41, Alexander Momchilov via swift-evolution <swift-evolution@swift.org> a écrit :

It can significantly speed up the initialization of applications with large static properties. E.g. large constant Dictionaries could be precomputed.
You could keep complex math expressions (including custom functions) in their unevaluated form, without the pressure to precompute them elsewhere and hardcode in the result.
Dynamic programming: expensive look-up tables could be precomputed. These wouldn't necessarily be large in size, but if their elements are especially expensive to compute, there would be a huge advantage to precomputing them.

What do you guys think? Can you think of any other useful applications? Would it be worth the implementation effort?

- Regards,
        Alexander Momchilov
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(L Mihalkovic) #4

Aren't macros totally different?

Anyways, weren't macros rejected? I thought Swift was trying to avoid having the hefty reliance of preprocessor macros that C did.

Sorry I was not referring to C-style macros (i.e. preproc). I was referring to a macro language in the sense of the scala compiler macros or other languages that let you insert compile time code inside your source (like D). I was of the opinion that it would be a short step to support something like embedded SIL inside string literals. But Chirs ruled out compile time code execution stressing that it should not be a replacement for designing a great language. Maybe around 4 or 5, when the language is mature, then compile time code execution (macros) can be added

···

On Jun 12, 2016, at 6:05 AM, Alexander Momchilov <alexandermomchilov@gmail.com> wrote:

On Jun 9, 2016, at 1:48 AM, L. Mihalkovic <laurent.mihalkovic@gmail.com <mailto:laurent.mihalkovic@gmail.com>> wrote:

Chris has rules macros out-of-scope for 3.0. Who knows, maybe they'll be allowable in 4.0

On Jun 9, 2016, at 1:41 AM, Alexander Momchilov via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Preface: I know this is likely a large undertaking to implement, but I think it's worth it.

In addition to the typical compiler optimization of constant math expressions, some languages (such as D and C++) have support for running arbitrary functions at compile time <https://en.wikipedia.org/wiki/Compile_time_function_execution> (with some constraints).

I see many advantages of this:
On iOS/OS X: it could precompute the UI and app initialization logic (wherever possible) to speed app load times
It can significantly speed up the initialization of applications with large static properties. E.g. large constant Dictionaries could be precomputed.
You could keep complex math expressions (including custom functions) in their unevaluated form, without the pressure to precompute them elsewhere and hardcode in the result.
Dynamic programming: expensive look-up tables could be precomputed. These wouldn't necessarily be large in size, but if their elements are especially expensive to compute, there would be a huge advantage to precomputing them.

What do you guys think? Can you think of any other useful applications? Would it be worth the implementation effort?

- Regards,
        Alexander Momchilov
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Haravikk) #5

I think it’s important to identify cases where you absolutely need to use compile-time macros, versus simply having the compiler precompute the results of regular Swift functions.

In the original post the linked article shows a macro calculating a factorial, but it’s a poor example IMO as it’s not something that definitely needs to be a macro, and indeed it’s something that would be more useful as a Swift function since you would also gain the ability to perform the same calculations dynamically at runtime. You get the same benefit to performance by having the compiler recognise which cases can be computed in advance and just let it do that. In fact in the fibonacci case it’s a clear one for the compiler to optimise away since storing the result as a constant should use less memory than storing the instructions required to trigger the function at run time, so it’s better for both performance and memory (there’s no downside to doing it).

The compiler probably already does this as part of its optimisations in cases where this can be done without any cost, so all that may be needed is a mechanism for forcing the compiler to do it in less obvious cases; e.g- where a function may generate a large set of results. Point being that in these cases it’s better to not use macros to do this, since you end up with two languages to maintain instead of just one, rather than just using a general purpose optimisation that works automatically across the whole, single, language.

I think a more clear benefit would be cases that could for example replace the .gyb files that are currently in the Swift stdlib code-base; I’m not 100% sure on what these actually do (besides make it harder for me to look up the implementation details of things ;), but if they could be replaced with some kind of macro constructs within a regular Swift file it may make them easier to work with, though you’re still talking about something that’s essentially a language within a language.

The other kinds of cases are things like platform-specific optimisations, but that’s something you should only ever do if you have to do it, and we already have conditionals that should support this I think.

Unless I’ve totally misunderstood the problem, but my experience with other languages has usually been that compile-time macros are most often used in place of good support for generics, which isn’t obviously a problem for Swift, either that or they’re used in cases that are actually redundant cases that a good compiler can optimise away for you (i.e- preemptive optimisation, which isn’t always a good thing). I can’t think of many good cases where I’ve thought “oh yeah that makes sense”, doesn’t mean there aren’t any of course, it might be helpful to have some good examples of where this kind of feature is necessary in Swift, versus some alternative feature in the language itself.

···

On 12 Jun 2016, at 09:47, L Mihalkovic via swift-evolution <swift-evolution@swift.org> wrote:

On Jun 12, 2016, at 6:05 AM, Alexander Momchilov <alexandermomchilov@gmail.com <mailto:alexandermomchilov@gmail.com>> wrote:

Aren't macros totally different?

Anyways, weren't macros rejected? I thought Swift was trying to avoid having the hefty reliance of preprocessor macros that C did.

Sorry I was not referring to C-style macros (i.e. preproc). I was referring to a macro language in the sense of the scala compiler macros or other languages that let you insert compile time code inside your source (like D). I was of the opinion that it would be a short step to support something like embedded SIL inside string literals. But Chirs ruled out compile time code execution stressing that it should not be a replacement for designing a great language. Maybe around 4 or 5, when the language is mature, then compile time code execution (macros) can be added