function Rx.combineLatest(t)assert(type(t)=="\116\097\098\108\101","\066\097\100 \111\098\115\101\114\118\097\098\108\101\115")return Observable.new(function(P)local W=0 local Y={}for t,P in pairs(t)do if Observable.isObservable(P)then W=W+1 Y[t]=UNSET_VALUE else Y[t]=P end end if W==0 then P:Fire(Y)P:Complete()return end local b=Maid.new()local function i()for t,P in pairs(Y)do if P==UNSET_VALUE then return end end P:Fire(Table.copy(Y))end for t,D in pairs(t)do if Observable.isObservable(D)then b:GiveTask(D:Subscribe(function(P)Y[t]=P i()end,function(...)W=W-1 P:Fail(...)end,function()W=W-1 if W==0 then P:Complete()end end))end end return b end)end

function Rx.combineLatest(observables)
	assert(type(observables) == "table", "Bad observables")

	return Observable.new(function(sub)
		local pending = 0

		local latest = {}
		for key, value in pairs(observables) do
			if Observable.isObservable(value) then
				pending = pending + 1
				latest[key] = UNSET_VALUE
			else
				latest[key] = value
			end
		end

		if pending == 0 then
			sub:Fire(latest)
			sub:Complete()
			return
		end

		local maid = Maid.new()

		local function fireIfAllSet()
			for _, value in pairs(latest) do
				if value == UNSET_VALUE then
					return
				end
			end

			sub:Fire(Table.copy(latest))
		end

		for key, observer in pairs(observables) do
			if Observable.isObservable(observer) then
				maid:GiveTask(observer:Subscribe(
					function(value)
						latest[key] = value
						fireIfAllSet()
					end,
					function(...)
						pending = pending - 1
						sub:Fail(...)
					end,
					function()
						pending = pending - 1
						if pending == 0 then
							sub:Complete()
						end
					end))
			end
		end

		return maid
	end)
end
