<commit_before>local previous_underscore = _

local Underscore = { funcs = {} }
Underscore.__index = Underscore

function Underscore.__call(_, value)
	return Underscore:new(value)
end

function Underscore:new(value, chained)
	return setmetatable({ _val = value, chained = chained or false }, self)
end

function Underscore.iter(list_or_iter)
	if type(list_or_iter) == "function" then return list_or_iter end
	
	return coroutine.wrap(function() 
		for i=1,#list_or_iter do
			coroutine.yield(list_or_iter[i])
		end
	end)
end

function Underscore.identity(value)
	return value
end

function Underscore:no_conflict()
  _ = previous_underscore
  return self
end

-- chaining
function Underscore:chain()
	self.chained = true
	return self
end

function Underscore:value()
	return self._val
end

-- iter
function Underscore.funcs.map(list, func)
	local mapped = {}
	for i in Underscore.iter(list) do
		mapped[#mapped+1] = func(i)
	end	
	return mapped
end

function Underscore.funcs.reduce(list, memo, func)	
	for i in Underscore.iter(list) do
		memo = func(memo, i)
	end	
	return memo
end

function Underscore.funcs.each(list, func)
	for i in Underscore.iter(list) do
		func(i)
	end
end

function Underscore.funcs.detect(list, func)
	for i in Underscore.iter(list) do
		if func(i) then return i end
	end	
	return nil	
end

function Underscore.funcs.select(list, func)
	local selected = {}
	for i in Underscore.iter(list) do
		if func(i) then selected[#selected+1] = i end
	end
	return selected
end

function Underscore.funcs.reject(list, func)
	local selected = {}
	for i in Underscore.iter(list) do
		if not func(i) then selected[#selected+1] = i end
	end
	return selected
end

function Underscore.funcs.all(list, func)
	func = func or Underscore.identity
	
	-- TODO what should happen with an empty list?
	for i in Underscore.iter(list) do
		if not func(i) then return false end
	end
	return true
end

function Underscore.funcs.any(list, func)
	func = func or Underscore.identity

	-- TODO what should happen with an empty list?	
	for i in Underscore.iter(list) do
		if func(i) then return true end
	end	
	return false
end

function Underscore.funcs.include(list, value)
	for i in Underscore.iter(list) do
		if i == value then return true end
	end	
	return false
end

function Underscore.funcs.invoke(list, functionName, ...)
	for i in Underscore.iter(list) do
		i[functionName](i, ...)
	end	
end

function Underscore.funcs.pluck(list, propertyName)
	local properties = {}
	for i in Underscore.iter(list) do
		properties[#properties+1] = i[propertyName]
	end	
	return properties
end

function Underscore.funcs.min(list, func)
	func = func or Underscore.identity
	local min, min_value = nil, nil
	for i in Underscore.iter(list) do
		if min == nil then
			min = i
			min_value = func(i)
		else
			local value = func(i)
			if value < min_value then
				min = i
				min_value = func(i)
			end
		end
	end
	return min
end

function Underscore.funcs.max(list, func)
	func = func or Underscore.identity
	
	local max, max_value = nil, nil
	for i in Underscore.iter(list) do
		if max == nil then
			max = i
			max_value = func(i)
		else
			local value = func(i)
			if value > max_value then
				max = i
				max_value = func(i)
			end
		end
	end
	return max
end

function Underscore.funcs.to_array(list)
	local array = {}
	for i in Underscore.iter(list) do
		array[#array+1] = i
	end	
	return array
end

function Underscore.funcs.reverse(list)
	local reversed = {}
	for i in Underscore.iter(list) do
		table.insert(reversed, 1, i)
	end	
	return reversed
end

function Underscore.funcs.sort(iter, comparison_func)
	local sorted = {}
	for ele in Underscore.iter(iter) do
		sorted[#sorted+1] = ele
	end
	table.sort(sorted, comparison_func)
	return sorted
end

-- arrays
function Underscore.funcs.first(array, n)
	if n == nil then<commit_msg>use _.to_array in _.sort<commit_after>local previous_underscore = _

local Underscore = { funcs = {} }
Underscore.__index = Underscore

function Underscore.__call(_, value)
	return Underscore:new(value)
end

function Underscore:new(value, chained)
	return setmetatable({ _val = value, chained = chained or false }, self)
end

function Underscore.iter(list_or_iter)
	if type(list_or_iter) == "function" then return list_or_iter end
	
	return coroutine.wrap(function() 
		for i=1,#list_or_iter do
			coroutine.yield(list_or_iter[i])
		end
	end)
end

function Underscore.identity(value)
	return value
end

function Underscore:no_conflict()
  _ = previous_underscore
  return self
end

-- chaining
function Underscore:chain()
	self.chained = true
	return self
end

function Underscore:value()
	return self._val
end

-- iter
function Underscore.funcs.map(list, func)
	local mapped = {}
	for i in Underscore.iter(list) do
		mapped[#mapped+1] = func(i)
	end	
	return mapped
end

function Underscore.funcs.reduce(list, memo, func)	
	for i in Underscore.iter(list) do
		memo = func(memo, i)
	end	
	return memo
end

function Underscore.funcs.each(list, func)
	for i in Underscore.iter(list) do
		func(i)
	end
end

function Underscore.funcs.detect(list, func)
	for i in Underscore.iter(list) do
		if func(i) then return i end
	end	
	return nil	
end

function Underscore.funcs.select(list, func)
	local selected = {}
	for i in Underscore.iter(list) do
		if func(i) then selected[#selected+1] = i end
	end
	return selected
end

function Underscore.funcs.reject(list, func)
	local selected = {}
	for i in Underscore.iter(list) do
		if not func(i) then selected[#selected+1] = i end
	end
	return selected
end

function Underscore.funcs.all(list, func)
	func = func or Underscore.identity
	
	-- TODO what should happen with an empty list?
	for i in Underscore.iter(list) do
		if not func(i) then return false end
	end
	return true
end

function Underscore.funcs.any(list, func)
	func = func or Underscore.identity

	-- TODO what should happen with an empty list?	
	for i in Underscore.iter(list) do
		if func(i) then return true end
	end	
	return false
end

function Underscore.funcs.include(list, value)
	for i in Underscore.iter(list) do
		if i == value then return true end
	end	
	return false
end

function Underscore.funcs.invoke(list, functionName, ...)
	for i in Underscore.iter(list) do
		i[functionName](i, ...)
	end	
end

function Underscore.funcs.pluck(list, propertyName)
	local properties = {}
	for i in Underscore.iter(list) do
		properties[#properties+1] = i[propertyName]
	end	
	return properties
end

function Underscore.funcs.min(list, func)
	func = func or Underscore.identity
	local min, min_value = nil, nil
	for i in Underscore.iter(list) do
		if min == nil then
			min = i
			min_value = func(i)
		else
			local value = func(i)
			if value < min_value then
				min = i
				min_value = func(i)
			end
		end
	end
	return min
end

function Underscore.funcs.max(list, func)
	func = func or Underscore.identity
	
	local max, max_value = nil, nil
	for i in Underscore.iter(list) do
		if max == nil then
			max = i
			max_value = func(i)
		else
			local value = func(i)
			if value > max_value then
				max = i
				max_value = func(i)
			end
		end
	end
	return max
end

function Underscore.funcs.to_array(list)
	local array = {}
	for i in Underscore.iter(list) do
		array[#array+1] = i
	end	
	return array
end

function Underscore.funcs.reverse(list)
	local reversed = {}
	for i in Underscore.iter(list) do
		table.insert(reversed, 1, i)
	end	
	return reversed
end

function Underscore.funcs.sort(iter, comparison_func)
	local array = Underscore.funcs.to_array(iter)
	table.sort(array, comparison_func)
	return array
end

-- arrays
function Underscore.funcs.first(array, n)
	if n == nil then
{'fraction_non_alphanumeric': 0.09168527518717982, 'fraction_numerical': 0.0019703139366872456, 'mean_word_length': 3.9059278350515463, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1412109', 'n_tokens_mistral': 2912, 'n_tokens_neox': 2768, 'n_words': 837}