Usage of 'do' outside of loops

Recently I stumbled upon this piece of code:

local Spring = {} do
	Spring.__index = Spring

	function Spring.new(freq, pos)
		local self = setmetatable({}, Spring)
		self.f = freq
		self.p = pos
		self.v = pos*0
		return self
	end

	function Spring:Update(dt, goal)
		local f = self.f*2*pi
		local p0 = self.p
		local v0 = self.v

		local offset = goal - p0
		local decay = exp(-f*dt)

		local p1 = goal + (v0*dt - offset*(f*dt + 1))*decay
		local v1 = (f*dt*(offset*f - v0) + v0)*decay

		self.p = p1
		self.v = v1

		return p1
	end

	function Spring:Reset(pos)
		self.p = pos
		self.v = pos*0
	end
end

I found it in Roblox’ Freecam script and the way do is used, surprised me. Until now I just used do for loops. Can someone explain to me why do was used in this context and what it does?

1 Like

Scopes. do ... end creates a new scope. Any locals declared in the do ... end would only be accessible to that scope.

Here is an example of this in action.

local get_x, set_x
do
    local x = 0
    
    function get_x()
        return x
    end

    function set_x(value)
        x = value
    end
end

print(x) -- nil
print(get_x()) -- 0
set_x(5)
print(get_x()) -- 5

x is still alive as an upvalue in the getters and setters. As to why they did this, I don’t know, since it didn’t seem necessary since they didn’t use it for htat. Probably some stylistic choice.

4 Likes

Thanks for the quick answer :woot:

In that topic stravant intentionally wraps it in a do ... end so you would lose a reference to the part created, even though it is still “alive”, therefore resulting in memory leaks

1 Like