Last active
December 23, 2024 01:07
-
-
Save hazzard993/c75e50cb5fd0343e091afd000e2b5e66 to your computer and use it in GitHub Desktop.
Inline pasteable functional functions for some functional programming in GameMaker (at least to my understanding of FP).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// | |
/// Performs right-to-left function composition. | |
/// | |
/// @param {Function[]} ...functions The pipeline of functions to send values through. | |
/// @returns The head of this pipeline. | |
var compose = function() { | |
var functions = []; | |
for (var i = 0; i < argument_count; ++i) { | |
array_push(functions, argument[i]); | |
} | |
if array_length(functions) == 0 { | |
return function(arg) { return arg; }; | |
} | |
if array_length(functions) == 1 { | |
return functions[0]; | |
} | |
return array_reduce(functions, function(previous, current) { | |
return method({ previous, current }, function() { | |
var arguments = []; | |
for (var i = 0; i < argument_count; ++i) { | |
array_push(arguments, argument[i]); | |
} | |
var result; | |
if is_method(current) { | |
result = method_call(current, arguments); | |
} else { | |
result = script_execute_ext(current, arguments); | |
} | |
return previous(result); | |
}); | |
}); | |
} | |
/// | |
/// Returns a pipeline make up of functions. | |
/// | |
/// @param {Function[]} ...functions The pipeline of functions to send values through. | |
/// @returns The head of this pipeline. | |
var pipe = function() { | |
var arguments = []; | |
for (var i = 0; i < argument_count; ++i) { | |
array_push(arguments, argument[i]); | |
} | |
var functions = array_reverse(arguments); | |
if array_length(functions) == 0 { | |
return function(arg) { return arg; }; | |
} | |
if array_length(functions) == 1 { | |
return functions[0]; | |
} | |
return array_reduce(functions, function(previous, current) { | |
return method({ previous, current }, function() { | |
var arguments = []; | |
for (var i = 0; i < argument_count; ++i) { | |
array_push(arguments, argument[i]); | |
} | |
var result; | |
if is_method(current) { | |
result = method_call(current, arguments); | |
} else { | |
result = script_execute_ext(current, arguments); | |
} | |
return previous(result); | |
}); | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// | |
/// Converts a function into a curried equivalent. | |
/// Can be a workaround for the lack of closures in GML. | |
/// See https://ramdajs.com/docs/#curry | |
/// | |
/// @param {Function} f Provided function. | |
/// @param {Real} n How many parameters it is expecting. | |
/// @returns {Any} A curried equivalent of the provided function. | |
var curry = function(f, n) { | |
var next = function(f, n, args, next) { | |
if array_length(args) < n { | |
return method({ f, n, args, next }, function() { | |
var new_args = variable_clone(args); | |
for (var i = 0; i < argument_count; ++i) { | |
array_push(new_args, argument[i]); | |
} | |
return next(f, n, new_args, next); | |
}); | |
} | |
if is_method(f) { | |
return method_call(f, args); | |
} | |
return script_execute_ext(f, args); | |
}; | |
return next(f, n, [], next); | |
}; | |
/// | |
/// Debugging tool for closures. Returns a string describing the closure. | |
/// The <> denotes parameters that haven't arrived yet. | |
/// | |
/// @param {Callable} curry_function The curried function. | |
/// @returns {String} A string describing the state of the curried function. | |
var curry_debug = function(curry_function) { | |
if not is_callable(curry_function) { | |
return string(curry_function); | |
} | |
var ctx = method_get_self(curry_function); | |
var result = $"{script_get_name(ctx.f)}("; | |
for (var i = 0; i < ctx.n; ++i) { | |
if i <= array_length(ctx.args) { | |
result += chr(97 + i); | |
} else { | |
result += $"<{i - array_length(ctx.args)}>"; | |
} | |
if i >= ctx.n - 1 { | |
continue; | |
} | |
result += ", "; | |
} | |
result += ")"; | |
return result; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// @param {Struct} a Struct a | |
/// @param {Struct} b Struct b | |
/// @returns A new struct combining both a and b's fields, however b's values take precedent. | |
var struct_merge = function(a, b) { | |
var result = variable_clone(a); | |
var names = struct_get_names(b); | |
for (var i = 0; i < array_length(names); ++i) { | |
var name = names[i]; | |
struct_set(result, name, struct_get(b, name)); | |
} | |
return result; | |
}; | |
/// @param {String | Real} name The name/field to check. | |
/// @param {Any} value The value to check that field for (== equality). | |
/// @returns {Function(Struct) -> Boolean} A function that returns a boolean when given a struct. | |
var name_equals = function(name, value) { | |
return method({ name, value }, function(struct) { | |
return struct_get(struct, name) == value; | |
}); | |
}; | |
/// @param {Function} constructor_name The constructor to check for. | |
/// @returns {Function(Struct) -> Boolean} A function that'll check for a struct using is_instanceof. | |
var is_an_instanceof = function(constructor_name) { | |
return method({ constructor_name }, function(struct) { | |
return is_instanceof(struct, constructor_name); | |
}); | |
}; | |
/// @param {Array} array This array will not be modified. | |
/// @param {Any[]} ...values Additional values to append. | |
/// @returns A copy of the array with all additional values appended. | |
var append = function(array) { | |
var result = variable_clone(array) | |
for (var i = 1; i < argument_count; ++i) { | |
array_push(result, argument[i]); | |
} | |
return result; | |
}; | |
/// | |
/// Flattens an array of arrays. | |
/// | |
/// [[1, 2], [3, 4]] -> [1, 2, 3, 4] | |
/// | |
/// @param {Array} array An array of arrays to flatten. | |
/// @returns A new flatten array based off the given one. | |
var flatten = function(array) { | |
var result = []; | |
for (var i = 0; i < array_length(array); ++i) { | |
var subarray = array[i]; | |
if not is_array(subarray) { | |
array_push(result, subarray); | |
} | |
for (var j = 0; j < array_length(subarray); ++j) { | |
var item = subarray[j]; | |
array_push(result, item); | |
} | |
} | |
return result; | |
}; | |
/// @param {Array} array The array to analyze. | |
/// @param {Any} value The index to remove. | |
/// @returns A copy of the array with the specified index removed. | |
var remove = function(array, index) { | |
var result = []; | |
for (var i = 0; i < argument_count; ++i) { | |
var item = array[i]; | |
if i == index { | |
continue; | |
} | |
array_push(result, value); | |
} | |
return result; | |
}; | |
/// @param {Array} array An array to iterate through. | |
/// @param {String} seperator A seperator to put in between each stringed item. | |
/// @returns {String} All items stringified with the use of a seperator in between. | |
var join = function(array, seperator) { | |
var result = ""; | |
for (var i = 0; i < array_length(array); ++i) { | |
var item = array[i]; | |
result += string(item); | |
if i >= array_length(array) - 1 { | |
continue; | |
} | |
result += seperator; | |
} | |
return result; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment