Fan

 

Symbols

Overview

Symbols are used to model name/value pairs. Symbols may be used namespace aware keys (where you might use a String in another language). In this regard they are similar to the :symbol construct in Ruby. But symbols also have a statically typed value, which you might think about like a "pod level field". In some cases this value may be overridden at deployment time with configuration files. In this regard symbols work similiar to how you might use an XML or properties file for configuration in Java or C#.

Symbols have the following features:

  • Declared in the "pod.fan" declaration
  • Always scoped within a pod using a unique name (as peers to types in the namespace)
  • A given pod may never have a symbol and type with the same name, by convention symbols are lower case and types are upper case
  • Symbols are typed like a field
  • Symbols have a const value like a field
  • There is exactly one Symbol instance per symbol in a VM

Declaration

Symbols are always declared in the "pod.fan" source file within the pod definition itself. Symbols use a syntax just like fields:

pod acme
{
  ** Facet symbol
  Bool someFacet := false

  ** Timeout for protocol
  virtual Duration timeout := 10sec

  ** List of servers for configuration
  virtual hosts := Str[,]
}

Symbols can have fandoc which may used to generate documentation. Unlike fields, symbols may use type inference as shown by the hosts symbol above which is inferred as Str[]. The values of symbols must be serializable.

Symbol Literals

The @ operator is used to create a symbol literal:

@sys::serializable  // qualified
@serializable       // unqualified

Unqualified symbols are resolved according to the source file's using statements. Only pod level using statements import symbols into the namespace.

Symbol literals evaluate to the sys::Symbol instance itself:

@transient.type    =>  sys::Symbol
@transient.pod     =>  sys
@transient.name    =>  transient
@transient.qname   =>  sys::transient
@transient.of      =>  sys::Bool
@transient.defVal  =>  false

Virtual Symbols

Virtual symbols are declared with the virtual keyword. Virtual symbols can be overridden at deployment time via configuration files. Let's take our example above:

pod acme
{
  virtual timeout := 10sec
  virtual hosts := Str[,]
}

In this example, we can write code which uses these symbols:

@hosts.val.each |host| { checkHost(host) }

Then the symbol values can be configured using a fansym file named:

etc/{podName}/pod.fansym

For example:

// etc/acme/pod.fansym
timeout=30sec
hosts=["hostA", "hostB"]

The file itself is formatted as a list of name/serialized object pairs. See Serialization for the formal definition of the file format.

Symbol configuration files are backed by the sys::Repo.readSymbolsCached method. This means that symbols can be configured across multiple repos and merged together. It also means that you can change a symbol config file at runtime and it will be automatically updated in a running VM.