defined()
The defined()
function, introduced in Elements 10, is a very special compiler function that is evaluated not at runtime but at compile time, and is used by the compiler to conditionally compile (or not compile) certain sections of code, depending on the presence of a Conditional Define. In that sense, it can replace more traditional {$IF ...}
or #if ...
directives, and allows for conditional code that flows more freely.
The method takes a single String parameter, and returns true
at compile time if the given string is set as conditional define (either by the compiler, in project settings, or via an {$DEFINE ...}
/#define ...
directive), or false
, if not.
Any code that would not execute due to a defined()
check returning false
– i.e. code that is in the if
(or else
) statement not being hit – will be completely eliminated by the compiler, at compile time. Note that this code is allowed to refer to identifiers that are unknown for the current compile target – essentially allowing you to use defined()
to compile conditional code for different platforms or APIs.
Boolean short-circuit is applied, so defined()
can be combined in an if
statement with other, runtime-evaluated conditions.
Simple example:
if defined("COCOA") then
writeLn('this code was compiled for Cocoa.')
else
writeLn('this code was compiled for .NET, Java or Island.');
if (defined("COCOA"))
writeLn("this code was compiled for Cocoa.");
else
writeLn("this code was compiled for .NET, Java or Island.");
if #defined(COCOA) {
writeLn("this code was compiled for Cocoa.")
} else {
writeLn("this code was compiled for .NET, Java or Island.")
}
if (defined("COCOA"))
writeLn("this code was compiled for Cocoa.");
else
writeLn("this code was compiled for .NET, Java or Island.");
In the above example, the compiler would emit the first writeL()
call only when compiling for Cocoa, and the second one only when compiling for a different platform.
But defined()
can do more:
if defined("MACOS") or (Environment.OS ≠ OperatingSystem.Windows) then
directorySeparator := '/'
else
directorySeparator := System.IO.Path.DirectorySeparator;
if (defined("MACOS") || Environment.OS != OperatingSystem.Windows)
directorySeparator = "/";
else
directorySeparator = System.IO.Path.DirectorySeparator;
if #defined(MACOS) || Environment.OS != OperatingSystem.Windows {
directorySeparator = "/"
} else {
directorySeparator = System.IO.Path.DirectorySeparator
}
if (defined("MACOS") || Environment.OS != OperatingSystem.Windows)
directorySeparator = "/";
else
directorySeparator = System.IO.Path.DirectorySeparator;
In this example, two advanced features of defined()
can be seen:
For one, defined()
is combined with a regular run-time condition in the same if clause. The compiler will evaluate defined("MACOS")
at compile time. If true
, it will short-circuit the rest of the expression (i.e. completely ignore it and not even emit code for it), and go straight to emitting the simple assignment statement. Only if false
will it generate code for the second check of Environment.OS
, and emit both parts of the if
clause.
For another, note how the else
statement of the if
clause makes reference to the System.IO.Path
class of the .NET framework. This class does not even exist when compiling for Cocoa – yet the code shown above will compile fine for Cocoa and .NET alike, because the else
clause will be eliminated for Cocoa.
Using defined()
outside of if
Note that while defined()
can be called as a function in ay context, it will only directly influence compiler behavior when used inside the expression of an if
statement. The following code will work, but the isCocoa
variable will be a regular boolean (its initial value determined at compile time, and the if
check will be executed at runtime):
var isCocoa := defined("COCOA");
if isCocoa then
writeLn('this is Cocoa.')
else
writeLn('this is .NET, Java or Island.');
bool isCocoa = defined("COCOA");
if (isCocoa))
writeLn("this is Cocoa.");
else
writeLn("this is .NET, Java or Island.");
let cocoa = defined("COCOA")
if isCocoa {
writeLn("this is Cocoa.")
} else {
writeLn("this is .NET, Java or Island.")
}
boolean cocoa = defined("COCOA");
if (isCocoa)
writeLn("this is Cocoa.");
else
writeLn("this is .NET, Java or Island.");
Swift
Symmetrically to available()
and #available
, a special syntax for defined()
is provided for the Swift language. #defined()
can be used with a hash symbol, and omitting the quotes around the name of the define.
See Also
exists()
System Functionstatic()
System Functionavailable()
System Function[If(defined())]
Aspect