def replace(placeholder, actual)
      raise 'wrong placeholder' if placeholder != @target
      @target.heads.delete(ptrs[0]) if @target
      @target = actual
      @target.heads << @ptrs[0]
      @symbols.map! { |s| s == placeholder ? actual : s }
    end
def replace(placeholder, actual)
      raise 'wrong placeholder' if placeholder != @target
      @target.heads.delete(ptrs[0]) if @target
      @target = actual
      @target.heads << @ptrs[0]
      @symbols.map! { |s| s == placeholder ? actual : s }
    end
sometimes a Rule is instantiated before the target is actually known
 it may be given a "placeholder" target first, which is later replaced
 with the real one