code: def pop_choice(self, key: str, choices: List[Any], default_to_first_choice: bool = False) -> Any:
          
          default = choices[0] if default_to_first_choice else self.DEFAULT
          value = self.pop(key, default)
          if value not in choices:
              key_str = self.history + key
              message = '%s not in acceptable choices for %s: %s' % (value, key_str, str(choices))
              raise ConfigurationError(message)
          return value
docs: Gets the value of ``key`` in the ``params`` dictionary, ensuring that the value is one of
          the given choices. Note that this `pops` the key from params, modifying the dictionary,
          consistent with how parameters are processed in this codebase.
  
          Parameters
          ----------
          key: str
              Key to get the value from in the param dictionary
          choices: List[Any]
              A list of valid options for values corresponding to ``key``.  For example, if you're
              specifying the type of encoder to use for some part of your model, the choices might be
              the list of encoder classes we know about and can instantiate.  If the value we find in
              the param dictionary is not in ``choices``, we raise a ``ConfigurationError``, because
              the user specified an invalid value in their parameter file.
          default_to_first_choice: bool, optional (default=False)
              If this is ``True``, we allow the ``key`` to not be present in the parameter
              dictionary.  If the key is not present, we will use the return as the value the first
              choice in the ``choices`` list.  If this is ``False``, we raise a
              ``ConfigurationError``, because specifying the ``key`` is required (e.g., you `have` to
              specify your model class when running an experiment, but you can feel free to use
              default settings for encoders if you want).