لیستها یک نوع دادهی پایه در Elixir برای نگهداری مجموعهای از مقادیر هستند. لیستها تغییرناپذیر هستند، یعنی نمیتوان تغییرشان داد. هر عملیاتی که یک لیست را تغییر دهد، لیست جدیدی برمیگرداند. لیستها پروتکل Enumerable را پیادهسازی میکنند که امکان استفاده از توابع ماژول Enum و Stream را فراهم میکند.
لیستها در Elixir به صورت لیستهای پیوندی پیادهسازی شدهاند، نه به صورت آرایههایی از مکانهای حافظهی پیوسته. بنابراین، دسترسی به یک عنصر در یک لیست زمان خطی میبرد و به طول لیست بستگی دارد.
لیستها را میتوان به شکل مستقیم، با «نشانهگذاری سر-دم» (که از عملگر cons یعنی | استفاده میکند)، یا ترکیبی از هر دو نوشت:
# Literal Form
[]
[1]
[1, 2, 3]
# Head-tail Notation
[]
# same as [1]
[1 | []]
# same as [1, 2, 3]
[1 | [2 | [3 | []]]]
# Mixed
# same as [1, 2, 3]
[1 | [2, 3]]
همچنین میتوان بیش از یک عنصر پیش از عملگر cons (|) نوشت.
# Multiple prepends
[1, 2, 3 | [4, 5]]
از نشانهگذاری سر-دم میتوان برای افزودن عنصرها به انتهای یک لیست استفاده کرد.
list = [2, 1]
[3, 2, 1] == [3 | list]
# => true
افزودن عنصرها به انتهای لیست در حین تکرار یک «ضدالگو» در نظر گرفته میشود. افزودن یک عنصر نیازمند پیمودن کل لیست و افزودن عنصر در انتهای آن است؛ بنابراین، افزودن یک عنصر جدید در هر تکرار نیازمند پیمودن کل لیست در هر تکرار خواهد بود.
میتوانیم همین نتیجه را با افزودن یک عنصر به ابتدای لیست معکوسشده و سپس معکوس کردن نتیجه به دست آوریم. افزودن به ابتدا عملیاتی سریع است و زمان ثابت میبرد.
# Appending to the end of a list (potentially slow)
[1, 2, 3] ++ [4] ++ [5] ++ [6]
# Prepend to the start of a list (faster, due to the nature of linked lists)
[6 | [5 | [4 | [3, 2, 1]]]]
# then reverse!
چند تابع رایج در Kernel برای لیستها وجود دارد:
hd/1 سر لیست را برمیگرداند، یعنی اولین عنصر در لیست.tl/1 دم لیست را برمیگرداند، یعنی لیست منهای اولین عنصر.length/1 تعداد عنصرهای لیست را برمیگرداند.in/2 یک «مقدار منطقی» برمیگرداند که نشان میدهد آیا آن عنصر در لیست وجود دارد یا نه.همچنین ماژول List نیز وجود دارد.
لیستها میتوانند هر نوع دادهای و ترکیبی از انواع دادههای مختلف را در خود جای دهند.
list = [1, :a, 2.0, "string"]