// Think of it as if the functions do normally what 
// the functions do as well as the variables.

function times2(num) {
 return num * 2;
}

function times3(num) {
 return num * 3;
}

function multiply(func, num) {
 return func(num);
}

// named function expression
var triple = function(num) {
 return num * 3;
}

console.log("3 * 5 = ", multiply(times3, 5));
console.log("3 * 5 = ", multiply(triple, 5));
console.log("2 * 5 = ", multiply(times2, 5));

// renaming a function (sort of)
function sayHi(name) {
 console.log("Hi, "+name);
}

var hi = sayHi; // assign a function to another variable
hi("dude");

// passing a function
function runWithOne(f) { // runs given function with argument 1
 f(1);
}
 
runWithOne(
 function(a){ console.log(a) }
);

// ------- Running at place, envoking ----------
// Function Declarations can’t be called like that
// Even if we remove the name, JavaScript would see the function
// keyword and try to parse Function Delaration:
// function() { // error, function declaration without name.
// .....
// }()

// So, the only way is to wrap the function in brackets. 
// Then the interpreter consider it as a part of a statement, hence a Function Expression.
// 
(function() {
 console.log("I am instant ;)");
})();

// Let me get a free drive
function ab(data) {
 return 500 + cd(data);
 function cd(data) {
 return 600 + data;
 }
}
var result = 19 + (function(data) { return parseInt(data)+78 })(10);
console.log(result);
console.log(ab(80));

// sorting numbers with callback function
var numbers = [10, 5, 2, 3, 19, 6, 0];
numbers.sort(function(x, y) { return y - x });
console.log(numbers);

// unlimited arguments
function sum() {
 var sum = 0;
 for(i = 0; i < arguments.length; i++) {
 sum += arguments[i];
 }
 return sum;
}
console.log(sum(1, 2, 3, 4, 578, 9879, 232, 7));
// on arrays: .push() add items to the array while
// .pop() deletes them/it