Skip to content
Bryan Edds edited this page Sep 29, 2024 · 25 revisions

Sometimes people find custom operators to be a stumbling block when using new F# APIs. We have worked hard to try to minimize the amount of custom operators users need to learn to use Nu. However, in order to make the API practical to succinctly author code with, we had to keep some. Here's a cheat-sheet of Nu's operators, starting with the operators you should familiarize yourself with first.

Operators for MMCC

    /// Define a static property equality.
    let (==) (lens : Lens<'a, 's>) (value : 'a) : DefinitionContent =
        PropertyContent (PropertyContent.make true lens value)

The == operator will define the property of a simulant as some unchanging value in an MMCC context.

    /// Define a dynamic property equality.
    let (:=) (lens : Lens<'a, 's>) (value : 'a) : DefinitionContent =
        PropertyContent (PropertyContent.make false lens value)

The := operator will keep the property of a simulant synchronized with a changing value in an MMCC context. You might think of it like a data binding if you're familiar with MVC or MVVM terminology.

    /// Define an event signal.
    let (=>) (eventAddress : 'a Address) (signal : Signal) : DefinitionContent =
        EventSignalContent (Address.generalize eventAddress, signal)

The => operator will cause an event to produce a signal (either a Message or a Command) that will be consumed by an MMCC context.

    /// Define an event handler.
    let (=|>) (eventAddress : 'a Address) (callback : Event<'a, 's> -> Signal) : DefinitionContent =
        EventHandlerContent (PartialEquatable.make (Address.generalize eventAddress) (fun (evt : Event) -> callback (Event.specialize evt) :> obj))

The =|> operator will cause an event to produce a signal (either a Message or a Command) that will be consumed by an MMCC context. Additionally, it allows the Event<'a, 's> value or its data to be passed into the constructed signal.

Operators for ImNui

    /// Specifies a static ImNui argument.
    let (.=) (lens : Lens<'a, 's>) (value : 'a) =
        { ArgStatic = true; ArgLens = lens; ArgValue = value } : 's ArgImNui

    /// Specifies a dynamic ImNui argument.
    let (@=) (lens : Lens<'a, 's>) (value : 'a) =
        { ArgStatic = false; ArgLens = lens; ArgValue = value } : 's ArgImNui

These .= and @= operators are the ImNui equivalent to the MMCC equality operators.

Operators for Composing Addresses

        /// Concatenate two addresses of the same type.
        static member (-|-) (address : 'a Address, address2 : 'a Address) : 'a Address = Address.acat address address2

        /// Concatenate two addresses, forcing the type of first address.
        static member (-->) (address : 'a Address, address2 : 'b Address) : 'a Address = Address.acatff address address2

        /// Concatenate two addresses, forcing the type of second address.
        static member (<--) (address : 'a Address, address2 : 'b Address) : 'b Address = Address.acatsf address address2

These are the various operators used to conveniently compose new addresses. Generally, if you stick to the MMCC API, you won't have to compose address much yourself.

    /// Concatenate an address with a simulant's address, forcing the type of first address.
    static member (-->) (address : 'a Address, simulant : #Simulant) =
        if isNull (group :> obj) then Address.anonymize address else acatff address simulant.SimulantAddress

The --> operator also has a convenience overload for composing new addresses from simulant handles. You will use this when defining new types of events for your simulants like so -

    [<RequireQualifiedAccess>]
    module Events =
        let ItemSelect = stoa<string> "Item/Select/Event"

    type Entity with
        member this.ItemSelectEvent = Events.ItemSelect --> this

Operator for Constructing Simulant Handles

    static member (/) (simulant : #Simulant, childName) =
        ...

The / operator overload makes it easy to construct hierarchies of simulant handles like so -

[<RequireQualifiedAccess>]
module Simulants =
    let Gameplay = Game / "Gameplay"
    let Scene = Gameplay / "Scene"
    let Player = Scene / "Player"
Clone this wiki locally