# Beyond Functions

Learn what functions really are and how much purpose they serve.

Learning Target: I will learn how to use functions past basic calling, and use them in more complicated applications.

Difficulty: Moderate to Hard

# What really are functions, anyways?

Functions in Lua (and other languages) are, believe it or not, values! When you do `function foo() ... end`, you're effectively saying `foo = function() ... end`. This is called syntactic sugar, and it's used in places you wouldn't expect.

Take for example the `:` operator. You might recognize this in lines such as `event:Wait()`. The `:` operator is just syntactic sugar for `event.Wait(event)`, and is used to provide the `Wait` function the table (or object) it's in.

The `+=` operator and it's siblings are also cases of syntactic sugar, and `a += 1` is equivalent to `a = a + 1`.

With this in mind, we can find out that defining a function allows you to treat it like a variable.

``````function foo(bar) -- Create variable `foo` with a function as it's value.
print(bar)
end

foo = nil -- Set `foo`'s value to `nil`.

foo(10) -- ERROR: attempt to call a nil value (global 'foo')
``````
``````function a()
return "Hello, world!"
end

local b = a -- `b` now does what `a` does.

print(a == b)    -- output: true
print(type(a))   -- output: function
print(a(), b())  -- output: Hello, world!, Hello, world!
``````

This adaptability isn't only for us. The language itself uses it everywhere! Take for example `pcall`. `pcall` is also a function (only it uses C, and not Lua), and when we use it, we feed it our own function.

``````local success, err = pcall(function() -- Here, we're calling the `pcall` function, and feeding it a function. Notice how it's not named, it's only `function()`. This is a function being used as a value.
error("Example error")
end) -- Closing off our function.
-- `pcall` returns two values after running.

-- more code...
``````

Because `pcall` is a function, we can call it alone without defining new variables We can also place it into conditionals, equations, and more. Not sure what use we'd get out of that, though.

``````pcall(function() error("Example error") end)
-- this is valid
``````

Another example would be the `Connect` function.

``````event:Connect(function() -- Same idea as `pcall`.
-- code here
end)
``````

The only difference here is that you can't call `Connect` on it's own, since it's part of the event itself.

``````Connect(function() --[[ code here ]] end) -- ERROR: attempted to call global 'Connect' (a nil value)
``````

# Practice 1

Assignment: Play around with functions, see what you can do!

Bonus: What are some other examples of things that use functions as values?

Alright, functions are values. What purpose does this really serve? If functions are values, we can place them anywhere, like regular values, and treat them like such.

This construct can help us make our code much nicer to look at. Here's an example:

``````if ability == "water" then
print("Water used")
-- code for water
elseif ability == "fireball" then
print("Fireball used")
-- code for fireball
elseif ability == "earthquake" then
print("Earthquake used")
-- code for earthquake
end
``````

We can reformat the code to look like this:

``````local abilities = {
water = function()
print("Water used")
-- code for water
end,
fireball = function()
print("Fireball used")
-- code for fireball
end,
earthquake = function()
print("Earthquake used")
-- code for earthquake
end,
end
}
``````

If you remember, `function() foo ... end` is equivalent to `foo = function() ... end`. This is what we're doing here, only it's inside of a table. If you don't like how this looks, you can always use your own syntactic sugar.

``````local abilities = {
water = function() print("Water used")
--[[code for water]]      end
fireball = function() print("Fireball used")
--[[code for fireball]]   end
earthquake = function() print("Earthquake used")
--[[code for earthquake]] end
--[[code for fireball]]   end
}
``````

# Practice 2

Assignment: Add some more abilities to the table, make the functions do more!

Bonus: Figure out how to make it print an error message if the ability is invalid.

# So? Why do that?

Why should I do this? Couldn't I just put the if statement into a function? This is a valid question. However, these function tables have more purpose than you think. Believe it or not, this specific construct is actually the reason for most (if not all) programming languages being able to do what they do!

If we want to call the tornado function specifically, we can do `abilities.tornado()`. The function can also return something, like the new health, stamina, or take in functions, like how much damage to deal, or a custom line to run.

Starting to seem familiar? Let's take a look at `math.round()`. You probably don't think much of this function, and that's with reason. But, the magic behind it is that you're doing exactly the same thing when calling that as you are with calling your ability.

`math` is a table. `round` is a function inside of that table. All functions that start with "`math.`" are part of the `math` table. This extends further. When you create a new instance, you call `Instance.new()`. If you're noticing the pattern, `new` is a function in the `Instance` table, or object in this case. If you want to remove an instance, you use the `:Destroy()` function, which is a part of the instance itself.

Most of what you do functions this way. Any string function, math function, table function or instance function you do uses this construct.

Getting fancy, you can place your abilities table inside of a ModuleScript, and then `require` that every time you need the table in a function. It's amazing.

# Practice 3

Assignment: Explore more cases of this construct in action. Try to make your own instance of this construct.

Bonus: The `:` operator requires a function to be in a table and to have a `self` or `this` argumet. Play around with this, how could it be helpful, and what can it be used for?

# Bonus: Currying

Note: This is an advanced concept.

As a bonus, let's learn what currying is.

It's exact definition as per Wikipedia is:

[...] currying is the technique of translating a function that takes multiple arguments into a sequence of families of functions, each taking a single argument. In simple turns, we're taking a function, and splitting it's arguments into multiple calls.

Here, we have a function `add` that takes in two arguments `a` and `b`.

``````function add(a, b)
return a + b
end
``````

We can curry this function to split it's arguments up to multiple calls.

``````function curryAdd(a)
return function(b)
return a + b
end
end
``````

What this will allow us to do is to partially complete a computation for later use, as so:

``````function curryAdd(a)
return function(b)
return a + b
end
end

``````

Granted, this example isn't the best, but it's still a valid showcase of currying in action.

A more proper example would be an angle interpolator, as such:

``````function angleConstruct(from, to)             -- Create the curry.
return function(at)                       -- Return the interpolator function configured to the `from` and `to` arguments provided.
return from + (to - from) * (at / 100) -- The equation itself.
end
end

local corner = angleConstruct(0, 90)  -- Create an interpolator configured to 0 through 90.
local wall = angleConstruct(0, 180)   -- Do the same for 0 through 180.
local circle = angleConstruct(0, 360) -- And 0 throuh 360.

-- Call the interpolators.
print("Corner middle is "..corner(50)) -- output: Corner middle is 45
print("Corner wedge is "..corner(15))  -- output: Corner wedge is 17.5
print("Wall ramp is "..wall(75))       -- output: Wall ramp is 135
print("Circle ends at "..wall(99))     -- output: Circle ends at 356.4
``````

This is only a glimpse into the power of currying. Much more can be done with this. Also, you can do this:

``````function curryAdd(a)
return function(b)
return a + b
end
end

``````

# [HARD] Practice 4

Assignment: Come up with your own curry function. What is it for?

Bonus 1: Create a curry function that can be ran more than once, i.e `func(?)(?)(?)` returns something.

Bonus 2: Create a function that will create a curried version of the function. It's fine if you only make it handle two calls, i.e it only supports `func(?)(?)`.