Skip to content

[Feature Request] Variable-Capturing Functions #457

@Wirmaple73

Description

@Wirmaple73

Suggestion

Howdy, folks. I was thinking if it's possible to implement variable-capturing functions, which means functions should be able to "capture" variables declared earlier outside their scope. This works exactly like functions that don't specify the static keyword in C#.

The Problem

Take the sample script below as an example.

Char scriptPlayer = Player.GetChar(0)

float playerCoords[3]
...playerCoords = scriptPlayer.GetCoordinates()
    
PrintPlayerCoordinates()
ExplodePlayer()

function PrintPlayerCoordinates()
    Text.PrintFormattedNow("X: %f, Y: %f, Z: %f", 5000, ...playerCoords)
end

function ExplodePlayer()
    int speechId = scriptPlayer.SetSayContext(SpeechId.PainOnFire)
    Fx.AddExplosion(...playerCoords, ExplosionType.Car)
end

The code above does not compile, as the functions don't see the variables declared in the main scope. There are two primary methods to fix this:

  • Pass scriptPlayer and playerCoords to both functions every time, which clutters code unnecessarily, especially as more complex functions or function arguments are added.
  • Make both variables global, which is unnecessary and can risk name collisions if the user isn't careful.

The Solution

Add a keyword to make functions capture variables, similar to PHP. Requires minimal code changes on your side (hopefully). Functions are non-capturing by default and users can choose what to capture via the optional use keyword, e.g:

function ExplodePlayer() use scriptPlayer, playerCoords
    int speechId = scriptPlayer.SetSayContext(SpeechId.PainOnFire)
    Fx.AddExplosion(...playerCoords, ExplosionType.Car)
end

Optional Enhancement

Let the user choose whether they want to pass captured arguments by value or reference (so that functions can modify them). Another welcome addition is to add this to regular parameters as well (like the value parameter below).

int a = 0, b = 0, c = 0

float x, y
x, y = IncrementAllBy(5)

function IncrementAllBy(value: int) use a, ref b, ref c: float, float
	a += value
	b += value
	c += value
	// a = b = c = 5

	return 1.0f 1.0f
end

// Out of the function's scope:
// a = 0, because 'a' was passed by value, while 'b' and 'c' were passed by reference.
// b = 5
// c = 5

Please let me know what you think about this suggestion. Keep up the great work!

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions