The Universal Function Library Project

Introduction

The UFL, Universal Function Library, is a set of around 100-300 standard functions for all programming languages. Languages do not have to implement anything exactly to the UFL specification, it is a guide. In addition, a small number of recommendations are made regarding operators and statements. See below. Furthermore, some recommendations regarding specific programming languages are made. See below.

General Recommendations: Operators and Statements

All programming languages should have the following: a standard ternary operator (use alternative symbols if '?' and ':' aren't available): c ? x : y [C uses c ? x : y][Raku uses c ?? x !! y][perhaps c ??? x : y][perhaps c ??? x ::: y] a short ternary operator x ?: y [PHP uses x ?: y][JavaScript uses x || y][equivalent to x ? x : y] a swap statement or function: swap var1 var2 Swap(&var1, &var2) [Swift uses swap(&a, &b)][C++ uses std::swap(a, b)] a noop statement or function: noop [Python uses pass] Noop() 2 mod operators: a % b [C-style (truncated) mod][C uses %][more common, but less useful: for positive b, the return value is positive, 0 or negative (depending on the sign of a)] a %% b [floor mod][R uses %%][Python uses %][more useful: for positive b, the return value is always positive or 0] 3 integer division operators for integers and floats: a / b [true divide][returns a float][use an alternative symbol if / does C-style (truncated) integer division][returning a float is more intuitive, and pretty common (e.g. JavaScript/PHP/Python)][truncating the return value breaks the principle of least astonishment, and often leads to bugs] a ~/ b [C-style (truncated) integer divide][Dart uses ~/] a ~~/ b [floor divide][Python uses //][perhaps ~//][perhaps _/][there may be a better symbol than ~~/] See the relevant pages for more details: Programming Language Comparison: General (Control Flow/Debugging) Programming Language Comparison: Operators and Symbols

General Recommendations: Functions and Methods

common debugging functions: ● Print: a good variable print function, either the main print function, or an additional function, that can display the contents of primitives/strings/arrays/maps etc (full depth by default, perhaps with a depth parameter) (appends linefeed by default) ● Type: succinct 'get variable type' functions, that work on all variables (perhaps 2 versions, short name, and full name) ● Version/LangVersion: a well-thought out, version number function, to report the programming language version number, the one function that must be designed right first time (e.g. it just returns a friendly string e.g. '1.2.3.4', or it returns an object, where one member is a friendly string) (new version functions may be added, but old version functions must not be removed/modified to be backwards incompatible) key string functions that should be more widespread: ● StrStarts/StrEnds ('StrStartsWith'/'StrEndsWith') (avoids verbosity and arithmetic errors with string slicing, makes the intention clear) ● ... in addition, StrContains ('StrIncludes'), is shorter, more readable and more intuitive than (StrIndexOf() != -1) ● ... and to complete the set, StrEquals, is more intuitive than !StrCompare() and allows for a case-sensitivity parameter, unlike 'str1 == str2' ● StrCount (PHP uses substr_count, Python uses str.count), e.g. do a line count, useful in algorithms ● StrRept (JavaScript uses repeat, PHP uses str_repeat), e.g. indent text, useful in speed tests, useful in unit tests and demo scripts, useful in algorithms ● SubStr/StrSlice: languages should have both of: SubStr (pos/length) and StrSlice (pos1/pos2) key mathematical functions that should be more widespread: ● FloorMod (extremely useful) ● Sign/Clamp (they make the intention clearer, avoid bugs, and can be useful for writing readable one-liners) ● VerCompare/IPCompare (compare version numbers/IP addresses, return negative/0/positive) ● PopCount (useful for algorithms, and useful for tight loops where speed matters) ● MRound (round to the nearest multiple of n) ● Combin/Permut ● Gamma ● Erf ● Between See the relevant pages for more details: Programming Language Comparison: Strings Programming Language Comparison: Mathematics Programming Language Comparison: Dates Programming Language Comparison: Objects

Specific Language Recommendations

AutoHotkey: ● add Array methods: Sort/Reverse/(Swap), Join, IndexOf/LastIndexOf, (FirstOrDefault), (Flat), (IsDense) ● add Array methods with a 'WithIndex' option: Map/Reduce/(ReduceRight)/Filter, GroupBy, (Count), (All)/(Any) ● add a Range object C++: ● add a short-ternary operator (Elvis operator) (e.g. 'a ?: b') (equivalent to 'a || b' in JavaScript, and 'a ?: b' in PHP) that returns the first truthy value or the last falsy value, rather than a boolean) ● add some form of Array.Join() (that can at least handle string/integer/float values) ● add an insertion-order map (dictionary) ● std::accumulate (i.e. reduce): allow omitting the seed (init) value, i.e. the first value is the seed ● int to string 'dec to base' conversion (like itoa) (std::stoi already does 'base to dec') C#: ● make dec to/from base conversions possible for all bases 2-36 (Convert.ToString/Convert.ToInt32 only handle bases 2/8/10/16) ● add a short-ternary operator (Elvis operator) (e.g. 'a ?: b') (equivalent to 'a || b' in JavaScript, and 'a ?: b' in PHP) that returns the first truthy value or the last falsy value, rather than a boolean) ● (add a spread operator for function calls) (note: awaiting confirmation: the '..' operator may fulfil this role in future) Crystal: ● multi-line comments Excel: ● add a sheet function to count string occurrences (working name: 'TEXTCOUNT') Go: ● implement a standard ternary operator (use alternative symbols to ? and : if necessary, like Raku) (in Go, a ternary operator is currently a 5-liner, or a 6-liner if also declaring a variable) ● add a Range object ● add a Tuple object ● various built-in array/map functions (to reduce the need for code inspection where everyone rolls their own basic functions, and to facilitate sharing/consistency/code reuse/performance) ● Go currently lacks both default function arguments and function overloading (without at least one of these, currently each function 'overload' needs a different name) Java: ● add a standard Round method (e.g. 1.5/0.5/-0.5/-1.5 etc should always round away from zero) ● add object properties (i.e. 'obj.myprop = value' and 'value = obj.myprop'), where myprop is either a standard property or is defined by getter/setter methods (versus the verbose-to-define/verbose-to-increment/less-maintainable-rename-it-3-times/parallel-collections-anti-pattern 'obj.setmyprop(value)' and 'value = obj.getmyprop()' conventions) ● allow specifying default function parameter values (or some convenient/succinct alternative) ● add a short-ternary operator (Elvis operator) (e.g. 'a ?: b') (equivalent to 'a || b' in JavaScript, and 'a ?: b' in PHP) that returns the first truthy value or the last falsy value, rather than a boolean) ● add anonymous functions that work much like normal functions (one return type pattern (not 43), that can handle any number of parameters, that don't require (one of 11) special methods to call them) ● (add subscript/subscript-like syntax for maps/dictionaries) (the clunkiness of method syntax makes them off-putting to work with (e.g. getting/setting/incrementing/appending), and doesn't play well when working in multiple languages) ● (add a spread operator for function calls) ● (add C++-style pairs or similar) (note: this is/was a big debate, SimpleEntry may be sufficient) JavaScript: ● add a function for creating date strings from parts (e.g. AutoHotkey: FormatTime(d, "ddd yyyy-MM-dd HH:mm:ss"), e.g. Python: d.strftime("%a %Y-%m-%d %H:%M:%S %z")) ● add a function for creating strings from parts (e.g. AutoHotkey: Format("{:02}:{:02}:{:02}", 1, 2, 3), e.g. Python: "{:02d}:{:02d}:{:02d}".format(1, 2, 3)) (note: padStart is too verbose for use with multiple values simultaneously, and doesn't play well with negative numbers) ● (add subscript/subscript-like syntax for maps/dictionaries) (the clunkiness of method syntax makes them off-putting to work with (e.g. getting/setting/incrementing/appending), and doesn't play well when working in multiple languages) ● (add a function to return the variable's type, e.g. 'Array'/'Map'/'Object' rather than 'object') Kotlin: ● add a standard Round method (e.g. 1.5/0.5/-0.5/-1.5 etc should always round away from zero) ● implement a standard ternary operator (use alternative symbols to ? and : if necessary, like Raku) ● add a short-ternary operator (Elvis operator) (e.g. 'a ?: b') (equivalent to 'a || b' in JavaScript, and 'a ?: b' in PHP) that returns the first truthy value or the last falsy value, rather than a boolean) (confusingly, '?:' is already in use as a null-coalescing operator) ● (add square bracket syntax for defining arrays) ● (add subscript/subscript-like syntax for maps/dictionaries) (the clunkiness of method syntax makes them off-putting to work with (e.g. getting/setting/incrementing/appending), and doesn't play well when working in multiple languages) PHP: ● array_reduce: allow omitting the seed (init) value, i.e. the first value is the seed (at present, if the seed is omitted, null is used as the seed, not the first value) Python: ● add a string slice method (the unusual 's[i,j]' slice syntax, doesn't play well when working across multiple programming languages) ● implement a standard ternary operator (use alternative symbols to ? and : if necessary, like Raku) (particularly as it's such a mathematical language, it's frustrating that Python currently lacks this) (many languages that lack a ternary operator, at least have an alternative that uses the *same operand/parameter order* as a ternary operator, e.g. 'if (c) x else y' (Kotlin) and 'if c {x} else {y}' (Rust)) ● add && and || operators (clearer/easier to find than 'and'/'or') ('&&' is shorter than 'and') (also useful when working across multiple programming languages) ● add a join method to 'list' objects (that can at least handle string/integer/float values) ● partially reimplement the print statement ('print myvar'), to print strings/numbers/lists/dictionaries (useful for testing code when coding at speed, and to speed up the manual (non-automated) conversion of Python 2 scripts (by avoiding countless nags), and to avoid copying-and-pasting a trailing ')') (also, unlike Python 2, this could allow 'print myvar = 123', currently one must do 'print(myvar := 123)', but that requires refactoring, to use the walrus operator) ● add a string repeat method (the unusual 's * n'/'n * s' string repeat syntax, doesn't play well when working across multiple programming languages) ● int to string 'dec to base' conversion (int already does 'base to dec') ● multi-line comments ● (more succinctly handle sort comparator functions that return negative/0/positive) ● (add an inclusive range function) (working name: 'rangeinc') ● (add a 'getOrDefault'/'getOrElse' method to 'list' objects for indexes that are out of bounds) (e.g. allow specifying a fallback value, or perhaps a fallback function, that receives the index and outputs a value) (without this, 1-liners become try/catch 4-liners) ● (add a 'rindex'/'lastindex' method to 'list' objects, i.e. a right-to-left version of 'index') R: ● multi-line comments ● int to string 'dec to base' conversion for bases 2-36 (strtoi already does 'base to dec') Rust: ● implement a standard ternary operator (use alternative symbols to ? and : if necessary, like Raku) ● add an insertion-order dictionary (map) (e.g. as the default, as an option, or as a separate class) ● int to string 'dec to base' conversion (from_str_radix already does 'base to dec') ● Rust currently lacks both default function arguments and function overloading (without at least one of these, currently each function 'overload' needs a different name) Swift: ● add a short-ternary operator (Elvis operator) (e.g. 'a ?: b') (equivalent to 'a || b' in JavaScript, and 'a ?: b' in PHP) that returns the first truthy value or the last falsy value, rather than a boolean) ● add an insertion-order dictionary (map) (e.g. as the default, as an option, or as a separate class) ● add a more succinct way to perform a string slice ● reduce: allow omitting the seed (init) value, i.e. the first value is the seed ● (more succinctly handle sort comparator functions that return negative/0/positive) ● (add a spread operator for function calls)