docs: def difference(self, other, joinBy=None, exact=False):
          """
          *Wrapper of* ``DIFFERENCE``
  
          DIFFERENCE is a binary, non-symmetric operator that produces one sample
          in the result for each sample of the first operand, by keeping the same
          metadata of the first operand sample and only those regions (with their
          schema and values) of the first operand sample which do not intersect with
          any region in the second operand sample (also known as negative regions)
          
          :param other: GMQLDataset
          :param joinBy: (optional) list of metadata attributes.  It is used to extract subsets of samples on which
                         to apply the operator: only those samples in the current and other dataset that have the same
                         value for each specified attribute are considered when performing the operation
          :param exact: boolean. If true, the the regions are considered as intersecting only if their coordinates
                        are exactly the same
          :return: a new GMQLDataset
  
  
          Example of usage. We compute the exact difference between Example_Dataset_1 and Example_Dataset_2,
          considering only the samples with same `antibody`::
  
              import gmql as gl
  
              d1 = gl.get_example_dataset("Example_Dataset_1")
              d2 = gl.get_example_dataset("Example_Dataset_2")
  
              result = d1.difference(other=d2, exact=True, joinBy=['antibody'])
          """
  
          if isinstance(other, GMQLDataset):
              other_idx = other.__index
          else:
              raise TypeError("other must be a GMQLDataset. "
                              "{} was provided".format(type(other)))
  
          if isinstance(joinBy, list) and \
              all([isinstance(x, str) for x in joinBy]):
              metaJoinCondition = Some(self.opmng.getMetaJoinCondition(joinBy))
          elif joinBy is None:
              metaJoinCondition = none()
          else:
              raise TypeError("joinBy must be a list of strings. "
                              "{} was provided".format(type(joinBy)))
  
          if not isinstance(exact, bool):
              raise TypeError("exact must be a boolean. "
                              "{} was provided".format(type(exact)))
  
          new_index = self.opmng.difference(self.__index, other_idx, metaJoinCondition, exact)
  
          new_local_sources, new_remote_sources = self.__combine_sources(self, other)
          new_location = self.__combine_locations(self, other)
          return GMQLDataset(index=new_index, location=new_location,
                             local_sources=new_local_sources,
                             remote_sources=new_remote_sources,
                             meta_profile=self.meta_profile)