Files
n8n-openai-adapter/lib/elixir/lib/list.ex
T

398 lines
8.5 KiB
Elixir

defmodule List do
@moduledoc """
Implements functions that only make sense for lists
and cannot be part of the Enum protocol. In general,
favor using the Enum API instead of List.
A decision was taken to delegate most functions to
Erlang's standard lib but following Elixir's convention
of receiving the target (in this case, a list) as the
first argument.
"""
@doc """
Given a list of lists, concatenates the sublists into a single list.
## Examples
List.concat [[1,[2],3], [4], [5,6]]
#=> [1,[2],3,4,5,6]
"""
def concat(list) when is_list(list) do
:lists.append(list)
end
@doc """
Concatenates the list on the right with the list on the left.
This function produces the same result the `++` operator. The only difference
is a minor optimization: when the first list contains only one element, we
simply add it as a head to the second list.
## Examples
List.concat [1,2,3], [4,5,6]
#=> [1,2,3,4,5,6]
"""
def concat(list, elements) when is_list(list) and is_list(elements) do
list ++ elements
end
@doc """
Deletes the given item from the list. Returns a list without the item.
If the item occurs more than once in the list, just the first occurrence
is removed.
## Examples
List.delete([1,2,3], 1)
#=> [2,3]
"""
def delete(list, item) do
:lists.delete(item, list)
end
@doc """
Duplicates the given element n times in a list.
## Examples
List.duplicate "hello", 3
#=> ["hello","hello","hello"]
List.duplicate [1,2], 2
#=> [[1,2],[1,2]]
"""
def duplicate(elem, n) do
:lists.duplicate(n, elem)
end
@doc """
Flattens the given `list` of nested lists. An optional
tail can be given that will be added at the end of
the flattened list.
## Examples
List.flatten [1,[[2],3]]
#=> [1,2,3]
List.flatten [1,[[2],3]], [4,5]
#=> [1,2,3,4,5]
"""
def flatten(list) do
:lists.flatten(list)
end
def flatten(list, tail) do
:lists.flatten(list, tail)
end
@doc """
Folds (reduces) the given list to the left with
a function. Requires an accumulator.
## Examples
List.foldl [5,5], 10, fn x, acc -> x + acc end
#=> 20
List.foldl [1,2,3,4], 0, fn x, acc -> x - acc end
#=> 2
"""
def foldl(list, acc, function) when is_list(list) and is_function(function) do
:lists.foldl(function, acc, list)
end
@doc """
Folds (reduces) the given list to the right with
a function. Requires an accumulator.
## Examples
List.foldr [1,2,3,4], 0, fn x, acc -> x - acc end
#=> -2
"""
def foldr(list, acc, function) when is_list(list) and is_function(function) do
:lists.foldr(function, acc, list)
end
@doc """
Returns the last element in `list` or nil if the `list` is empty.
## Examples
List.last []
#=> nil
List.last [1]
#=> 1
List.last [1, 2, 3]
#=> 3
"""
def last([]), do: nil
def last(list) do
:lists.last(list)
end
@doc """
Checks if the given `term` is included in the list.
This function simply delegates to `lists:member`
which is implemented in C for performance.
## Examples
List.member? [1,2,3], 1
#=> true
List.member? [1,2,3], 0
#=> false
"""
def member?(list, term) do
:lists.member(term, list)
end
@doc """
Receives a list of tuples and returns the first tuple
where the item at position `posistion` matches with the
given `item`.
## Examples
List.keyfind([a: 1, b: 2], :a, 0)
#=> { :a, 1 }
List.keyfind([a: 1, b: 2], 2, 1)
#=> { :b, 2 }
List.keyfind([a: 1, b: 2], :c, 0)
#=> nil
"""
def keyfind(list, key, position, default // nil) do
:lists.keyfind(key, position + 1, list) || default
end
@doc """
Receives a list of tuples and returns true if there is
a tuple where the item at position `posistion` matches
with the given `item`.
## Examples
List.keymember?([a: 1, b: 2], :a, 0)
#=> true
List.keymember?([a: 1, b: 2], 2, 1)
#=> true
List.keymember?([a: 1, b: 2], :c, 0)
#=> false
"""
def keymember?(list, key, position) do
:lists.keymember(key, position + 1, list)
end
@doc """
Receives a list of tuples and replaces the item
identified by `key` at position `pos` if it exists.
## Examples
List.keyreplace([a: 1, b: 2], :a, 0, { :a, 3 })
#=> [a: 3, b: 2]
"""
def keyreplace(list, key, position, new_tuple) do
:lists.keyreplace(key, position + 1, list, new_tuple)
end
@doc """
Receives a list of tuples and replaces the item
identified by `key` at position `pos`. If the item
does not exist, it is added to the end of the list.
## Examples
List.keystore([a: 1, b: 2], :a, 0, { :a, 3 })
#=> [a: 3, b: 2]
"""
def keystore(list, key, position, new_tuple) do
:lists.keystore(key, position + 1, list, new_tuple)
end
@doc """
Receives a list of tuples and deletes the first tuple
where the item at position `posistion` matches with the
given `item`. Returns the new tuple.
## Examples
List.keydelete([a: 1, b: 2], :a, 0)
#=> [{ :b, 2 }]
List.keydelete([a: 1, b: 2], 2, 1)
#=> [{ :a, 1 }]
List.keydelete([a: 1, b: 2], :c, 0)
#=> [{ :a, 1 }, { :b, 2 }]
"""
def keydelete(list, key, position) do
:lists.keydelete(key, position + 1, list)
end
@doc false
def range(first, last, step // nil)
def range(first, last, step) when is_integer(first) and is_integer(last) and first <= last do
IO.write "[WARNING] List.range is deprecated, please use ranges instead\n#{Exception.formatted_stacktrace}"
case step do
nil ->
:lists.seq(first, last, 1)
x when x < 0 ->
[]
_ ->
:lists.seq(first, last, step)
end
end
def range(first, last, step) when is_integer(first) and is_integer(last) and first > last do
IO.write "[WARNING] List.range is deprecated, please use ranges instead\n#{Exception.formatted_stacktrace}"
case step do
nil ->
:lists.seq(first, last, -1)
x when x > 0 ->
[]
_ ->
:lists.seq(first, last, step)
end
end
@doc false
def sort(list) do
IO.write "[WARNING] List.sort is deprecated, please use Enum.sort instead\n#{Exception.formatted_stacktrace}"
:lists.sort list
end
@doc false
def sort(list, fun) do
IO.write "[WARNING] List.sort is deprecated, please use Enum.sort instead\n#{Exception.formatted_stacktrace}"
:lists.sort fun, list
end
@doc false
def uniq(list) when is_list(list) do
IO.write "[WARNING] List.uniq is deprecated, please use Enum.uniq instead\n#{Exception.formatted_stacktrace}"
do_uniq(list, [])
end
@doc """
Wraps the argument in a list.
If the argument is already a list, returns the list.
If the argument is nil, returns an empty list.
## Examples
List.wrap [1,2,3] #=> [1,2,3]
"""
def wrap(list) when is_list(list) do
list
end
def wrap(nil) do
[]
end
def wrap(other) do
[other]
end
@doc """
Zips corresponding elements from each list in `list_of_lists`.
## Examples
List.zip [[1, 2], [3, 4], [5, 6]]
#=> [{1, 3, 5}, {2, 4, 6}]
List.zip [[1, 2], [3], [5, 6]]
#=> [{1, 3, 5}]
"""
def zip([]), do: []
def zip(list_of_lists) when is_list(list_of_lists) do
do_zip(list_of_lists, [])
end
@doc """
Unzips the given list of lists or tuples into separate lists and returns a
list of lists.
## Examples
List.unzip [{1, 2}, {3, 4}]
#=> [[1, 3], [2, 4]]
List.unzip [{1, :a, "apple"}, {2, :b, "banana"}, {3, :c}]
#=> [[1, 2, 3], [:a, :b, :c]]
"""
def unzip(list) when is_list(list) do
:lists.map tuple_to_list(&1), zip(list)
end
## Private
# uniq
defp do_uniq([h|t], acc) do
case :lists.member(h, acc) do
true -> do_uniq(t, acc)
false -> [h|do_uniq(t, [h|acc])]
end
end
defp do_uniq([], _acc) do
[]
end
# zip
defp do_zip(list, acc) do
converter = fn x, acc -> do_zip_each(to_list(x), acc) end
{mlist, heads} = :lists.mapfoldl converter, [], list
case heads do
nil -> :lists.reverse acc
_ -> do_zip mlist, [list_to_tuple(:lists.reverse(heads))|acc]
end
end
defp do_zip_each(_, nil) do
{ nil, nil }
end
defp do_zip_each([h|t], acc) do
{ t, [h|acc] }
end
defp do_zip_each([], _) do
{ nil, nil }
end
defp to_list(tuple) when is_tuple(tuple), do: tuple_to_list(tuple)
defp to_list(list) when is_list(list), do: list
end