public override Expression Replace(Symbol variable, Expression argument)
 {
     var newHead = _head.Replace(variable, argument);
     var newTail = _tail.Replace(variable, argument);
     if (newHead == _head && newTail == _tail)
         return this;
     return new Apply(newHead, newTail);
 }
 public override Expression Replace(Symbol variable, Expression argument)
 {
     var newBody = _body.Replace(variable, argument);
     if (newBody == _body)
         return this;
     ImmutableList<char> taken = newBody.FreeVariableNames(new Symbol[] { _variable }.ToImmutableList());
     if (taken.Contains(_variable.Default))
     {
         int ordinal = (int)(char.ToLower(_variable.Default) - 'a') + 1 % 26;
         while (taken.Contains((char)('a' + ordinal)))
             ordinal++;
         var newVariable = new Symbol((char)('a' + ordinal));
         newBody = newBody.Replace(_variable, new BoundVariable(newVariable));
         return new Lambda(newVariable, newBody);
     }
     return new Lambda(_variable, newBody);
 }
 public Apply(Expression head, Expression tail)
 {
     _head = head;
     _tail = tail;
 }
 public override Expression Replace(Symbol variable, Expression argument)
 {
     return this;
 }
 public override Expression Replace(Symbol variable, Expression argument)
 {
     if (_variable == variable)
         return argument;
     return this;
 }
 public Expression Apply(Expression argument)
 {
     return _body.Replace(_variable, argument);
 }
 public Lambda(Symbol variable, Expression body)
 {
     _variable = variable;
     _body = body;
 }
 public abstract Expression Replace(Symbol variable, Expression argument);