premake/website/docs/Why-Do-Call-Arrays-Need-Functions.md

62 lines
2.6 KiB
Markdown
Raw Normal View History

2021-03-16 15:47:10 +00:00
---
title: Why Do Call Arrays Need Functions?
---
*"Hang on a minute,"* you're now thinking. *"Why do I need to override a function, call it to get the table, and then insert my new call? Why don't you just have a global table? Then I could insert my new call and skip that override business."*
In other words, why couldn't the list of functions look like this instead?
```lua
m.elements.project = {
m.xmlDeclaration,
m.project,
m.projectConfigurations,
-- and so on...
}
-- then I could do this:
table.insertafter(m.elements.project, m.xmlDeclaration, myNewFunction)
-- instead of this!
premake.override(m.elements, "project", function(base, prj)
local calls = base(prj)
table.insertafter(calls, m.xmlDeclaration, myNewFunction)
return calls
end)
```
The answer: that would break the ability to override the functions in the array. Let me explain...
The functions being included in the array are resolved at the time the code is evaluated. For a global table that means at the time the script is first loaded and executed.
When the code is executed, `m.project` (perhaps better thought of here as `m["project"]`) is evaluated and *the function it represents* is stored into the array. Kind of like this:
```lua
m.elements.project = {
function: 0x10017b280
function: 0x100124dd0
function: 0x10017b2c0
-- and so on...
}
```
That's all well and good: `m.project` evaluates to `function: 0x100124dd0` and that's what is in the array.
Now what happens if want to override `m.project`?
```lua
premake.override(m, "project", function(base, prj)
print("All your base are belong to us")
base(prj)
end)
```
`premake.override()` takes your new replacement function and assigns it to `m.project` (or `m["project"]` if that's easier to visualize). Which means the symbol `m.project` now evaluates to a different function, say `function: 0x100300360`.
If you call `m.project(prj)` directly, your replacement function will be executed as expected. However, since the `m.elements.project` table has already been evaluated, it still points to the original `function: 0x100124dd0`. Which means that when the Visual Studio project is generated and that call array is processed, your override will be ignored.
So getting to the point: by putting the call array table inside a function, we defer evaluation *until the function is actually called*. Since all of the user scripts are called before the Visual Studio project is generated, your override will already be in place, `m.project` will evaluate to your replacement function (`function: 0x100300360` instead of `function: 0x100124dd0`), and the correct code will be run.