code: @Override
      public <T extends ImmutableTerm> Optional<ImmutableSubstitution<T>> applyToSubstitution(
              ImmutableSubstitution<T> substitution) {
  
          if (isEmpty()) {
              return Optional.of(substitution);
          }
  
          try {
              ImmutableMap<Variable, T> newMap = ImmutableMap.copyOf(substitution.getImmutableMap().entrySet().stream()
                      .map(e -> new AbstractMap.SimpleEntry<>(applyToVariable(e.getKey()), applyToTerm(e.getValue())))
                      .distinct()
                      .filter(e -> ! e.getKey().equals(e.getValue()))
                      .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                              (e1, e2) -> {
                                  throw new NotASubstitutionException();
                              })));
              return Optional.of(substitutionFactory.getSubstitution(newMap));
          } catch (NotASubstitutionException e) {
              return Optional.empty();
          }
      }
docs: TODO: directly build an ImmutableMap