Functions
Functions are the way to interact with objects, with no functions we have no object-oriented behaviors, no abstractions and no encapsulation. Functions have an automatic return type of any
which means it can return any type of variable back to a user and an automatic visibility scope of public
. They also can take in ANY amount of arguments, which don't even have to be defined in the function signature. WOWZA!
Functions in BoxLang are also first-class object citizens. Meaning that each function can be addressed like an object. They can be even deleted, renamed or even injected at runtime. This is one of the most powerful qualities of the BoxLang dynamic language. You can at runtime manipulate objects and their functions.
You can find all the different features of functions in the docs: https://boxlang.ortusbooks.com/boxlang-language/classes/functions
Declaration
Examples
Please note that you can use valid JavaDoc syntax and DocBox will document your functions and arguments as well.
Function Access Types and Scopes
Functions can have different visibility contexts:
public
- Available to the class and externallyprivate
- Available only to the class that declares themethod and any classes that extend the class in
which it is defined
package
- Available only to the class that declares themethod, classes that extend the class, or any
other classes in the package
remote
- Available to a locally or remotely executing pageor class method, or a remote client through a URL,
Flash, or a web service. To publish the function as a
web service, this option is required.
Another interesting tidbit in BoxLang is that the visibility determines where the function will exist within the scope of the class. Remember that functions in BoxLang are objects themselves. They can be added, removed, renamed even at runtime thanks to BoxLang being a dynamic language.
public,remote
- The function reference is placed in both thethis
andvariables
scopeprivate,package
- The function reference is placed in thevariables
scope
Does this mean, that I can programmatically change an object at runtime by injecting (mixing) in new methods, or removing methods, or even renaming them? HECK YES SIREE BOB! This is the beauty of the dynamic language, you can manipulate object instances at runtime.
Function Modifiers
Function modifiers allow you to declare special behaviors to functions, from static
availability to final
and abstract
declarations. We have created a section for each of these types so that you can read more about the modifiers:
Function Attributes & Metadata
The function
construct can also have many attributes or name-value pairs that will give it extra functionality according to the BoxLang engine (metadata). You can find all of them here: https://boxlang.ortusbooks.com/boxlang-language/classes/functions. Below are the most common ones:
output
- Will this function send content to the output stream. Try avoiding this totrue
unless you are building libraries of some type, else you are breaking encapsulationdescription
- A short text description of the function a part from the hintreturnFormat
- Format to return for remote callers
Please note that in BoxLang, you can also declare these attributes via annotations in the comments section:
Apart from the name-value pairs of attributes the BoxLang language gives you, you can also add your own. These are called function annotations or custom function metadata. They can be anything you like and they don't even have to have a value. BoxLang then allows you to read the metadata out of the functions via the getMetadata()
or getClassMetadata()
functions.
Function Arguments
Arguments tell the function how to do their operation. A function can receive zero or more arguments separated by commas in its declaration.
declaration
All BoxLang functions are dynamic, meaning they can take any number of arguments without you adding the signatures. You can call functions by passing arguments by position or via name-value pairs, or even with a structure/array of values, which will be called an argumentCollection
.
example
Tip: Please also note that you can add a-la-carte metadata or name-value pairs to each argument inline or via annotations as we have seen above.
example with annotations
Function Returns
BoxLang functions will use the return
keyword to return a value from the function. A function can be marked void
in its return type to denote that it does not return any value. However, if a function has no return type or any
and you do not explicitly return a value, then the function will automatically return null
.
Function Scopes
You must be getting into the habit of scopes by now. Functions also have access to all Component scopes plus a few more that are only available to the function itself.
arguments
- Collects all the incoming arguments. If the function is called via positional, then this will be a struct with numbers as keys. If the function is called via name-value pairs, the struct will contain the same name-value pairs.local
- A struct that contains all the variables that are ONLY defined in the functions via thevar
keyword.
Function Var Scope or Local Scope
Each function has a local
scope that is ONLY available for the lifetime of the function's execution. This is where you will define localized variables since your object can be multi-threaded. Always plan for multi-threaded applications and make sure you var scope your variables. Why? Well, if you do not var scope a variable, then your variable will end up in the implicit scope, which is variables
.
BoxLang also has a weird cascading lookup for variables, so if you do not explicitly specify its scope, BoxLang will look for it for you. If you use a variable name without a scope prefix, BoxLang checks the scopes in the following order to find the variable:
Local (function-local, UDFs, and Classes only)
Arguments
Thread local (inside threads only)
Query (not a true scope; variables in query loops)
Thread
Variables
CGI
Cffile
URL
Form
Cookie
Client
Because BoxLang must search for variables when you do not specify the scope, you can improve performance by specifying the scope for all variables.
Executing Functions
You can execute functions once you have an instance or reference of a class. If the function has arguments, you can pass them in three ways: positional, name-value pairs, or using a collection (array, struct) via the argumentCollection
attribute.
Last updated