Skip to content
johnmcclean-aol edited this page Nov 23, 2016 · 6 revisions

Xor : eXclusive Or

Xor is a 'Right' (or primary type) biased disjunct union. Often called Either, but in a generics heavy Java world Xor is half the length of Either.

No 'projections' are provided, swap() and secondaryXXXX alternative methods can be used instead.

Class Hierarchy

Xor

Xor inherits from the following cyclops types (and others) ApplicativeFunctor, Filterable, Foldable, Functor, MonadicValue1, To, Value,Visitable and Zippable.

## Examples

A member variable

Xor is used to represent values that can be one of two states (for example a validation result, either everything is ok - or we have an error). It can be used to avoid a common design anti-pattern where an Object has two fields one of which is always null (or worse, both are defined as Optionals).

public class Member{
   Xor<SeniorTeam,JuniorTeam> team;      
}

Rather than

public class Member{
   @Setter
   SeniorTeam seniorTeam = null;
   @Setter
   JuniorTeam juniorTeam = null;      
    
}

Xor's have two states

  1. Primary : Most methods operate naturally on the primary type, if it is present. If it is not, nothing happens.
  2. Secondary : Most methods do nothing to the secondary type if it is present.

To operate on the Secondary type first call swap() or use secondary analogs of the main operators.

Instantiating

Instantiating an Xor - Primary

Xor.primary("hello").map(v->v+" world") 
//Xor.primary["hello world"]

Instantiating an Xor - Secondary

Xor.secondary("hello").map(v->v+" world") 
//Xor.seconary["hello"]

Accumulate Secondary

Xor can operate (via map/flatMap) as a Functor / Monad and via combine as an ApplicativeFunctor

Values can be accumulated via

Xor.accumulateSecondary(ListX.of(Xor.secondary("failed1"),
                                 Xor.secondary("failed2"),
                                 Xor.primary("success")),
                                 Semigroups.stringConcat)
 
//failed1failed2

Xor<String,String> fail1 = Xor.secondary("failed1");
fail1.swap().combine((a,b)->a+b)
            .combine(Xor.secondary("failed2").swap())
            .combine(Xor.<String,String>primary("success").swap())
   
//failed1failed2

Conversely accumulatePrimary is also available.

Applicative Functor

Combine values of any type asynchronously

Xor.primary(10)
   .combine(Maybe.just(10),(a,b)->a+b);
//Primary[20]

orElse / coflatMap

orElse and coflatMap can be used to manage Xor's that aren't present and provide a default value.

int result = Xor.primary(10)
                .orElse(-1); //10

int result = Xor.secondary("hello")
                .orElse(-1); //-1

Xor.secondary()
   .coflatMap(xor->xor.visit(s->10,p->p); //Xor.Primary[10]

Pattern matching

We can use the visit method to execute a function depending on whether the Xor is primary or secondary

Xor.secondary(10)
   .visit(s->"This is secondary",p->"This is primary"); //returns This is secondary
      
Xor.primary(10)
   .visit(s->"This is secondary",p->"This is primary"); //returns This is primary
Clone this wiki locally