code: def merge_programs(prog_list):
      
      definitions = [gate for prog in prog_list for gate in Program(prog).defined_gates]
      seen = {}
      # Collect definitions in reverse order and reapply definitions in reverse
      # collected order to ensure that the last occurrence of a definition is applied last.
      for definition in reversed(definitions):
          name = definition.name
          if name in seen.keys():
              # Do not add truly identical definitions with the same name
              # If two different definitions share a name, we include each definition so as to provide
              # a waring to the user when the contradictory defgate is called.
              if definition not in seen[name]:
                  seen[name].append(definition)
          else:
              seen[name] = [definition]
      new_definitions = [gate for key in seen.keys() for gate in reversed(seen[key])]
  
      p = sum([Program(prog).instructions for prog in prog_list], Program())  # Combine programs without gate definitions
  
      for definition in new_definitions:
          p.defgate(definition.name, definition.matrix, definition.parameters)
  
      return p
docs: Merges a list of pyQuil programs into a single one by appending them in sequence.
      If multiple programs in the list contain the same gate and/or noisy gate definition
      with identical name, this definition will only be applied once. If different definitions
      with the same name appear multiple times in the program list, each will be applied once
      in the order of last occurrence.
  
      :param list prog_list: A list of pyquil programs
      :return: a single pyQuil program
      :rtype: Program