Next: , Previous: , Up: Reference Guide   [Contents][Index]


3.4 Enums and Flags

While GObject is an OOP framework and as such mainly focuses on objects, there also exists functionality to deal with enumerated types. Enumerated types are a way of converting raw numbers into meaningful expressions and broadly fit into two categories: enumerations and flags. Both assign tokens to numerical values at compile time, but their use is different. Enumerations are used for equality checks only, whereas flags can be composed through bitwise or, tested by bitwise and, and operated on in other ways – as long as the basic operations are bitwise, the result will make some sense.

In Scheme, the closest analogues to enumerations and flags are symbols and symbol lists. Symbol equality can be checked with eq?, symbol list equality with equal? and in Guile specifically, the other operations can be implemented based on the lset-* procedures.3 However, both of these lose information needed to convert them into a numerical representation.

In Guile-GI, we bind enumerations and flags to GOOPS objects as we do with every other object type. Specifically, enums derive from <GEnum> and flags derive from <GFlags>.

3.4.1 Conversions

Procedure: number->enum (class <class>) (number <number>)
Procedure: number->enum (class <class>)
Procedure: number->flags (class <class>) (number <number>)
Procedure: number->flags (class <class>)
Procedure: number->type (number <number>)

Converts number into an enum or flags of class class. Called with just class, produces a procedure, that can be used to call itself with just number.This is often referred to as currying.

number->type calls the appropriate constructor for the given type. Note, that this type is shortened to its name without any prefixes. For instance, a GtkOrientation may be created using number->orientation. We will henceforth refer to this construction as “binding class on type

Procedure: symbol->enum (class <class>) (symbol <symbol>)
Procedure: symbol->enum (class <class>)
Procedure: type (symbol <symbol>)

Converts symbol into an enum of class class. Curries. Binds class on type.

Procedure: list->flags (class <class>) (list <list>)
Procedure: list->flags (class <class>)
Procedure: type (list <list>)

Converts symbol into flags of class class. Curries. Binds class on type.

Procedure: enum->number (enum <GEnum>)
Procedure: enum->number (class <class>) (enum <GEnum>)
Procedure: enum->number (class <class>) (symbol <symbol>)
Procedure: enum->number (class <class>)
Procedure: type->number (class <class>)

If symbol is given, returns the value represented by symbol in class.

If enum is given, converts it to a symbol. If both enum and class are given, raises an error if enum is not of type class.

Curries. Binds class on type.

Procedure: enum->symbol (enum <GEnum>)
Procedure: enum->symbol (class <class>) (enum <GEnum>)
Procedure: enum->symbol (class <class>)
Procedure: type->symbol (class <class>)

Converts enum to a symbol. If class is given, raises an error if enum is not of type class. Curries. Binds class on type.

Procedure: flags->number (enum <GEnum>)
Procedure: flags->number (class <class>) (enum <GEnum>)
Procedure: flags->number (class <class>) (list <list>)
Procedure: flags->number (class <class>)
Procedure: type->number (class <class>)

If list is given, returns the value represented by list in class.

If flags is given, converts it to a symbol. If both flags and class are given, raises an error if flags is not of type class.

Curries. Binds class on type.

Procedure: flags->list (enum <GEnum>)
Procedure: flags->list (class <class>) (enum <GEnum>)
Procedure: flags->list (class <class>)
Procedure: type->list (class <class>)

Converts flags to a list of symbols. If class is given, raises an error if flags is not of type class. Curries. Binds flags on type.

3.4.2 Standard Procedure overrides

<GEnum> and <GFlags> display as their symbolic/list representation and also use them in write in lieu of their addresses. Enumerations can be numerically compared to enumerations and numbers using =. Flags can be numerically compared to flags and numbers using =. Enumerations and flags can be compared to enumerations and flags of the same type using equal?.

3.4.3 R6RS-esque flag operations

Some would certainly like to see an equivalence the enumerated types discussed above and R6RS enum sets. However, it turns out, that they are not compatible. Enumerations are not enum sets, because they are not sets – they are atoms. Flags are not enum sets, because they don’t have a universe. Instead, they have a numerical mask. In an enum universe, each value is distinct from any other. GObject flags can however be combinations of other flags. A commonly found pattern is SOME_READWRITE = SOME_READ | SOME_WRITE for example. Hiding 'readwrite would take a lot of work just so we can explicitly go against the design of the library writer, which is not a good idea at all.

To cope with this fact, we implement our own – similar, albeit somewhat different – set of functions, that aim to be close to what you see in R6RS.

Procedure: enum-universe (class <class>)
Procedure: enum-universe (enum <GEnum>)
Procedure: enum-universe (flags <GFlags>)

Returns a list of meaningful symbols (i.e. those that can be used in symbol->enum or list->flags) for class. If enum flags is given, class is inferred from it.

Procedure: flags-mask (class <class>)
Procedure: flags-mask (flags <GFlags>)

Returns flags of class class, that has all possible values set. If flags is given, class is inferred from it.

Procedure: flags-union (flags <GFlags>) . rest

Constructs the union of all flags given by flags and rest. All of them must belong to the same class.

Procedure: flags-intersection (flags <GFlags>) . rest

Constructs the intersection of all flags given by flags and rest. All of them must belong to the same class.

Procedure: flags-difference (flags1 <GFlags>) (flags2 <GFlags>)

Constructs the difference of flags1 and flags2. Both of them must belong to the same class.

Procedure: flags-complement (flags <GFlags>)

Returns the flags not set in flags.

Procedure: flags-set? (flags <GFlags>) (number <number>)
Procedure: flags-set? (flags <GFlags>) (symbol <symbol>)
Procedure: flags-set? (flags <GFlags>) (list <list>)

Return #t if and only if the flag(s) given by number, symbol or list are set.

Procedure: flags-projection
Procedure: flags-projection/list (flags <GFlags>) (class <class>)
Procedure: flags-projection/list (flags <GFlags>) (flags2 <GFlags>)
Procedure: flags-projection/number (flags <GFlags>) (class <class>)
Procedure: flags-projection/number (flags <GFlags>) (flags2 <GFlags>)

Project flags onto class class. (class is inferred from flags2).

flags-projection/list constructs flags from all symbols in (flags->symbol flags), that are valid in class. flags-projection/number constructs flags, that have the same bits set with respect to (flags-mask class).

flags-projection is an alias for flags-projection/list.


Footnotes

(3)

Other implementations may offer similar functions – otherwise they can be implemented by the user themselves.


Next: Utilities, Previous: GType Constants and Operations, Up: Reference Guide   [Contents][Index]