4 ms·
Very solid article with many points I agree with. Some notes: Keywords are not simply "another pragmatic solution that won over finding a more elegant way to
by sodapopcan 3y ago
Very solid article with many points I agree with.
Some notes:
Keywords are not simply "another pragmatic solution that won over finding a more elegant way to support named arguments" and they are inherently different than maps and serve different purposes. Maps are unordered hashes, keyword lists are constant time, ordered list that can have duplicate keys. For example, in the language core, duplicate keys are used:
import Foo, only: [bar: 1, bar: 2]
Ecto's query syntax makes use of both duplicate keys and ordering:
from q in query,
join: t in assoc(q, :table),
on: q.table_id = t.id,
join: o in assoc(t, :other),
on: t.other_id = o.id
Everyone complains about the f.() syntax. It's necessary as explained in the guides in the Anonymous Functions section [0]. There is also a nice little parallel to Erlang in that a regular function call looks like `f()` whereas an anonymous function call looks like `F()`.
Contexts can be confusing, unfortunately. They're based off of bounded contexts from Domain Driven Design. I wouldn't say there is one right way to use Phoenix contexts, though reading up on DDD's bounded contexts really helps. I already had DDD experience before I learned Elixir, though, so it's easy for me to say and maybe more of a pain for others who don't want to do that.
Comprehensions can be much more concise in certain situations. You can certainly get away with avoiding them, but they can really come in handy sometimes. Not gonna give examples as this is getting too long. A short example would be Cartesian products.
Finally, I don't quite understand the gripe with `on_mount` or even `live_session` but that's been addressed in another comment.
[0] https://elixir-lang.org/getting-started/basic-types.html https://elixir-lang.org/getting-started/basic-types.html
- deleted 3y ago[deleted]
- jkhdigital 3y agoAnother note: The “inconsistent” naming is actually a way to distinguish between guard and non-guard functions: is_map can be used in guards while empty? cannot.
- SupremumLimit 3y ago[I am the author of the post.] I know that keyword lists are different from maps, but I think their superficial similarity to maps isn’t ideal, and I don’t think that they’re the best possible solution (eg consider pattern matching on keyword lists which is order dependent, it’s not intuitive in the case of named args). They’re confusing to newcomers because of these things.
- sethcalebweeks 3y agoKeyword lists were certainly confusing as a newcomer. But, FWIW, they existed well before maps. The AST is made up of only tuples and keyword lists on top of atoms and other literals. (Actually, if I'm not mistaken, keyword lists themselves are just lists with tuples of atom/value pairs. If you dig far enough down, it's incredible just how much of the language is built on top of a tiny number of primitives. Almost every bit of syntax you can think of is probably several layers of macros.)
- bobwaycott 3y ago> Actually, if I'm not mistaken, keyword lists themselves are just lists with tuples of atom/value pairs. You are correct. A keyword list is `[{atom, any}]`.
- rkangel 3y agoKeyword lists are from Erlang's history really. Erlang didn't have maps or records for a long time and used keyword lists to perform a similar function.
- sph 3y ago> They’re confusing to newcomers because of these things. Then they learn how they work and stop being confused. I struggle to see why we are so terribly afraid of people learning. Programming is not an innate instinct after all. A programmer that doesn't understand linked lists yet is basically a newbie, but it's a topic you learn in one day and makes you a better programmer. This should be encouraged, rather than listed as a con.
- rapnie 3y ago> Contexts can be confusing, unfortunately. They're based off of bounded contexts from Domain Driven Design. I wouldn't say there is one right way to use Phoenix contexts, though reading up on DDD's bounded contexts really helps. I already had DDD experience before I learned Elixir, though, so it's easy for me to say and maybe more of a pain for others who don't want to do that. Jenny Shih gave a talk comparing Phoenix contexts with DDD bounded contexts. https://www.youtube.com/watch?v=vr-qhHrN5_4 https://www.youtube.com/watch?v=vr-qhHrN5_4
- foldr 3y ago> keyword lists are constant time, ordered list Unless there’s some kind of behind-the-scenes magic that I’m unaware of, keyword list look up is O(n), not O(1).
- bitwalker 3y agoNo, you’re exactly right, they are just regular singly-linked lists of tuples, nothing more.
- sodapopcan 3y agoOops yes, typo sorry, meant non-constant.
- boxed 3y agoMaps can be ordered though. In Python they are, and keyword arguments in Python are implemented as these ordered maps (dicts), and they disallow duplicate keys. So I do understand how it can be confusing coming from another language for example.
- sph 3y agoIt's just a matter of algorithmic complexity. A hashmap, ordered or not, is more complicated than a linked list, which is what Keywords are built upon. The former requires taking an arbitrary piece of data, hashing it to an integer, and indexing a cell based off this value, dealing with potential collisions on the way. In C terms it's 50 lines long. The latter is a simple iteration and pointer equality comparison (due to keywords being interned strings). In C terms it's 5 lines long. It is confusing if you've never programmed close to the metal and only know high level languages. Maps are good for data that you need to access in random order, linked lists/keyword lists for data that either you access in linear order, or it is so small the overhead of a map is too much. If you have less than 10 elements, a linked list will always be faster than any hashmap on modern CPUs.
- boxed 3y ago> It's just a matter of algorithmic complexity. A hashmap, ordered or not, is more complicated than a linked list, which is what Keywords are built upon. You mean implementation complexity right? Anyway, I was talking about semantics, not performance or implementation. > If you have less than 10 elements, a linked list will always be faster than any hashmap on modern CPUs. Citation needed. That personally sounds totally bonkers to me. Faster HOW? If the pointers of each node in the linked list are far apart in memory the L1/L2 cache misses will absolutely destroy the performance. I think you're talking from a ton of assumptions that you haven't stated. If the list is that short, why isn't it a contiguous array in memory? That's going to be way smaller and way way faster in every way.
- hinkley 3y agoOrdered maps are usually a hybrid linked list. When iterating you can traverse the linked list data, rather than the buckets.
- jolux 3y agoI’d also like to add that the Access module provides generic access to key-value collections just like Enum does for sequences.