On Thu, Sep 21, 2023 at 7:19 PM 'Justin Wood' via elixir-lang-core <
elixir-lang-core@googlegroups.com> wrote:

> Languages that support it via square brackets: Rust, Ruby, Javascript,
> Python, C, Julia.
>
> All of these languages (other than maybe Julia? I have not used it at
> all.) are actually using arrays and not lists. It is fairly natural to have
> easy index based lookup for arrays. After all, it is meant to be a
> contiguous block of memory with each element having a known size. At least
> for Rust and C, other languages may be more loose in terms of
> implementation.
>

That's the problem.  Ruby, Python, Javascript are where a lot of Elixir
devs are coming from (or languages that Elixir devs are often "context
switching" with on a daily basis) and these all implement lists that are
not actually arrays in the conventional sense.  I'm pretty sure, in all
three cases, that a list is actually an object that maintains the list
elements -- that might be an actual array of pointers, or it might not.
It's definitely not a low-level single allocated block of memory, because
these are weakly typed languages an all three support mixed type values (an
array in C requires every entry be a fixed size; indexed access is simply
multiplying the index by the size of each element and using that as an
offset to the start of the memory block -- one of the reasons you can
easily segfault by doing that).

Lists in Elixir are linked lists, but we don't regularly refer to them that
way.  We don't explicitly reinforce this implementation by requiring things
like "LinkedList.new(1, 2, foo)"; we use a "conventional array notation"
like "mylist = [1, 2, foo]" -- just like you'd see in Python, Javascript,
Ruby.  So it's really not that much of a surprise, coming from those
languages, that you start off with that kind of a syntax, and you then
expect the language to implement square-bracket-indexing, just like those
languages do.  We have Enum.at() to do this, so it's not like it's an
impossibility to actually make this work.  The question then is why the
syntax doesn't just wrap that function and 'make it work'.  I'm not sure I
buy Jose's argument about preventing "non-idiomatic code".  If someone is
going to forget that Enum.map exists, they're going to write that loop, and
they'll just use Enum.at if they can't get the square brackets to work.

This difference from how those languages have wrapped array-like functions
into their syntax has popped up recently with my team, we've noticed people
forgetting that the length of a List in Elixir isn't "free information"
like it is in Ruby (where the length of a list is actually an attribute of
the object representing the list), so we've had to remind people not to do
things like "assert length(foo) > 0" (fortunately, a lot of this
inefficiency has been limited to our unit tests!) -- because they're coming
from Ruby where the length of a list is always "known", so it doesn't even
occur to them (and I admit, I've been guilty of forgetting this
occasionally as well) that Enum.count() and length() both actively loop
over an argument to compute the length, and aren't just retrieving some
privately cached data.

As an aside, the one oddity around Access' square-bracket-index
implementation that still throws me every once in a while is why you can't
use square brackets to index a field on a struct.  If you have a Map, you
can do foo[key] but on a struct, foo[key] throws an exception.  Where it
gets annoying is that the way to make this work on a struct is to actually
use Map.get -- a Map function!  If a struct is a Map, why can't Access just
treat structs like Maps in this situation?  But that's a completely
different discussion, and I digress.  ;)

Personally, I don't see the harm in supporting it.  If someone's going to
abuse it, they'll abuse Enum.at() to make it work anyway, just like I end
up abusing Map.get() when I need to get a field from a struct based on a
variable key name.  But it's definitely going to be an ongoing point of
confusion because "one of these things is not like the others"

...Paul

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAD3kWz-zd2Eyp97y8AD9VNRwRx_XZhnKHyA%2BsUYSTQLtd3z_yA%40mail.gmail.com.

Reply via email to