def connect(signal, *args, &block)
      # ugly argument parsing.
      # Make sure that there is either a block given, or that the second argument is
      # something callable. If there is a block given, the second argument, if given,
      # must be a Hash which defaults to an empty Hash. If there is no block given,
      # the third optional argument must be Hash.
      if block_given?
        observer = block
        if args.size == 1 && args.first.is_a?(Hash)
          options = args.first
        elsif args.size == 0
          options = {}
        else
          raise ArgumentError, 'When given a block, #connect only expects a signal and options hash as arguments'
        end
      else
        observer = args.shift
        raise ArgumentError, 'Use a block, method or proc to specify an observer' unless observer.respond_to?(:call)
        if args.any?
          options = args.shift
          raise ArgumentError, '#connect only expects a signal, method and options hash as arguments' unless options.is_a?(Hash) || args.any?
        else
          options = {}
        end
      end

      # Initialize the list of observers for this signal and add this observer
      observers[signal] ||= Stack.new
      observers[signal].push(observer, options[:priority])
    end
def connect(signal, *args, &block)
      # ugly argument parsing.
      # Make sure that there is either a block given, or that the second argument is
      # something callable. If there is a block given, the second argument, if given,
      # must be a Hash which defaults to an empty Hash. If there is no block given,
      # the third optional argument must be Hash.
      if block_given?
        observer = block
        if args.size == 1 && args.first.is_a?(Hash)
          options = args.first
        elsif args.size == 0
          options = {}
        else
          raise ArgumentError, 'When given a block, #connect only expects a signal and options hash as arguments'
        end
      else
        observer = args.shift
        raise ArgumentError, 'Use a block, method or proc to specify an observer' unless observer.respond_to?(:call)
        if args.any?
          options = args.shift
          raise ArgumentError, '#connect only expects a signal, method and options hash as arguments' unless options.is_a?(Hash) || args.any?
        else
          options = {}
        end
      end

      # Initialize the list of observers for this signal and add this observer
      observers[signal] ||= Stack.new
      observers[signal].push(observer, options[:priority])
    end
Register a observer for a given signal.

 Instead of adding a method or Proc object to the stack, you could
 also use a block. Either the observer argument or the block is required.

 Optionally, you could pass in an options hash as the last argument, that
 can specify an explicit priority. When omitted, an internal counter starting
 from 1 will be used. To make sure your observer is called last, specify
 a high, **positive** number. To make sure your observer is called first, specify
 a high, **negative** number.

 @example Using a block as an observer
   dispatcher.connect('post.publish') do |event|
     puts "Post was published"
   end

 @example Using a method as an observer
   class Reporter
     def log(event)
       puts "Post published"
     end
   end
   dispatcher.connect('post.publish', Reporter.new.method(:log))

 @example Determining observer call order using priority
   dispatcher.connect('pulp', :priority => 10) do
     puts "I dare you!"
   end
   dispatcher.connect('pulp', :priority => -10) do
     puts "I double-dare you!"
   end
   # output when "pulp" is triggered:
   "I double-dare you!"
   "I dare you!"

 @overload connect(signal, observer, options = {})
   @param [String] signal is the name used by the observable to trigger
     observers
   @param [#call] observer is the Proc or method that will react to
     an event issued by an observable.
   @param [Hash] options is an optional Hash of additional options.
   @option options [Fixnum] :priority is the priority of this observer
     in the stack of all observers for this signal. A higher number means
     lower priority. Negative numbers are allowed.
 @overload connect(signal, options = {}, &block)
   @param [String] signal is the name used by the observable to trigger
     observers
   @param [Hash] options is an optional Hash of additional options.
   @option options [Fixnum] :priority is the priority of this observer
     in the stack of all observers for this signal. A higher number means
     lower priority. Negative numbers are allowed.
 @return [#call] the added observer