7 ms·
Elixir has always been a pleasure for me to work with. Maybe true with most FP languages as well. The main positive I see is that I can easily navigate through
by princevegeta89 7y ago
Elixir has always been a pleasure for me to work with. Maybe true with most FP languages as well.
The main positive I see is that I can easily navigate through code (due to absence of complex objects/classes) and the standard library seems to be very extensive.
The language was also easy to get into. My only complaint is that the IDE support for intelliJ(through the plugin) hasn't been impressive though I can live with it.
- AlecSchueler 7y agoCould you, or anyone else, recommend some well written and idiomatic elixir code that's free to browse through? Coming from an object oriented background the idea that classless code could be less complex is sorta blowing my mind!
- minhajuddin 7y agoCheck out hex: https://github.com/hexpm/hexpm https://github.com/hexpm/hexpm
- toast0 7y agoFor me, the benefit vs OO is that everything is explicit. If I'm calling into a function from another module, it's almost always clear which other module -- if I need to see what it does, I can go look and the code is likely to be there. Compared to something in OO where I've got an object to call a method on, and it may actually be an object that extends/implements making it much harder to find code (IDEs can often help, if you've taken the time to setup the IDE). You can call into a module with a variable, but it's rarely done, outside of some specific types of code interaction (ex: structural event loop processing like gen_server takes a Module to callback into). Of course, when sending messages to processes, there's not really anything in code to indicate where those will be processed, and I don't know that IDEs help there either. Usually, code organization helps, but it's not required. Caveat: my experience is with Erlang, not Elixir, but should generally apply.
- princevegeta89 7y agoSpot on! I did some work on OTP and it seemed to be neat. I did learn Go just to compare how easy/fun it would be to work with. I liked Go but I came back to Elixir because of pattern matching, minimal configuration and readable semantics. Not to mention, there's not much boilerplate to deal with and we've got useful control structures like the very readable `cond`s instead of if {} else if { } blocks (Although you can use these, it is generally discouraged in Elixir). I will tell you that being pushed towards writing "cond" s and "when"s, "with"s has guided me towards achieving a better and more readily understood codebase.
- filmor 7y agoThe explicitness of Erlang is exactly what Elixir is lacking. A /lot/ is done via macros. This makes it really easy to build domain-specific language extensions, but it also means that you'll have to learn what they are doing to fully understand the code. In Erlang, the few simplifications you get are very local (as long as you don't apply a parse_transform on your whole project, which is rarely a good idea).
- Communitivity 7y agoI agree, and I'm a rarity maybe, because I think it is much easier to understand and debug Elixir if you learn Erlang first. You don't have to, in order to code in Elixir, but understanding what was going on under the hood made it much easier for me to work with Elixir.
- pmontra 7y agoI understand how that could be a problem. However it never was with the countless DSLs I saw in Ruby. The trick is never write one. Only use the ones of widely popular projects. I never wrote a macro in Elixir (only for experimenting with them), nobody ever did in the projects I worked on and I'm perfectly happy with that. On the other side everybody uses macros, mainly with/do/else. I wish they implemented it as keywords of the language. They could probably have spared us the annoyance of converting code from = to <- and comma everytime it is moved inside a with and viceversa. That's the part of the syntax that I like less.
- hew 7y agoPlug for this book when stepping beyond syntax (I'm just a satisfied reader): https://pragprog.com/book/jgotp/designing-elixir-systems-with-otp https://pragprog.com/book/jgotp/designing-elixir-systems-wit... It was hugely helpful to me in wrapping my head around something bigger than hello world.
- lawik 7y agoI've found most Elixir projects I've taken a look at to be surprisingly easy to follow when I've needed to. I've dug into Ecto, Ecto SQL, Elixir itself at times. This was just because I was trying to figure out some corner-case behavior. The overhead of understanding someone else's classes when I tried similar things in Python was always just a much heavier mental load. Idiomatic or not. As mentioned by another comment, the important thing is that each function you need to read can pretty much be read on its own. You might need to follow a few trails. But the way a library can hide where the magical state comes from in a Python class is sometimes maddening. I know, because I've written that code. I find Elixir incredibly readable, nicely writable and the mental overhead continuously lower.
- emerongi 7y agoGenerally I agree, but I've found it hard to parse macro logic in projects that I am not familiar with. I've written a project that uses macros heavily as well and it's hard to make it easy to understand. It's a double-edged sword. Macros are nice and can simplify the top-level API significantly, but at the same time they add complexity under the hood.
- dnautics 7y agoThe biggest sin is that it's too fun to write macros in elixir.
- thrwaway69 7y agoNot sure if it's me but I find decorators a terrible annoyance most of the time if I am reading random code in the wild. It feels like magic with a can of worms that you have to go through multiple files to fully understand. I like them for use in some bigger frameworks but overall, they seem to provide negative value to me as a reader, often confusing names doing some magical coating which could very well be solved with pure function composition. I have noticed some python projects making heavy use of it... they rely on you to read their guide to write code instead of switching and using the project fine because you know the language. Sort of like another DSL? Elixir hits the balance for me between being not too intense (haskell) and friendly usable with a nice community.
- di4na 7y agochangelog.com opensourced their whole website https://github.com/thechangelog/changelog.com https://github.com/thechangelog/changelog.com
- lliamander 7y agoI felt the same way going from Java to Erlang. One hurdle that was difficult for me was understanding Behaviors (which are an abstraction used in both Erlang and Elixir). On the one hand, a Behavior is much like an class/object: it has public methods, internal state, polymorphism (via message passing) and to some extent a notion of inheritance. According to Alan Kay, it's more Object-Oriented than Smalltalk! However, a Behavior runs in it's own process. Like a typical class, public and private functions are defined in the same file This makes reading the code where a Behavior is defined more difficult because the public methods are executing in the client process, but the callbacks (i.e. private functions) are executing in the Behavior's own process. One insight I gained from working with Erlang was that the "academic" notion of OOP modeling (i.e. model the entities of your domain as discrete objects) works much better with Erlang's proceses/Behaviors than it ever did with classes/objects in languages like Java. Objects in languages like Java, C#, Ruby, JS, etc. are much at modeling the architectural components of a system, than at actually modeling domain entities directly. That's actually partly why I really the Pony language: it combines both objects as processes (called Actors) and objects as components/capabilities (called Objects).
- tomn 7y ago> Behavior is much like an class/object: it has public methods, internal state, polymorphism (via message passing) > a Behavior runs in it's own process This doesn't sound right; a behaviour is just a set of functions to be implemented in a 'callback module'; you seem to be talking about processes and modules. I agree with your points though.
- lliamander 7y ago> This doesn't sound right; a behaviour is just a set of functions to be implemented in a 'callback module'; Going back, I see that you are right: the Behavior is technically the common pattern that is shared across specific processes. Is there a name for a process that is defined in a callback module? And really, this complaint about confusing modules spans to more than just callback modules. Most processes define both the client and server functions in the same module. For small modules it's not too big a deal, but even then it is very difficult for someone new to the language to learn how follow the flow of data. Dave Thomas has some interesting ideas about this and other problems, but as I don't do Erlang programming professionally at the moment I haven't had time to really dig in deep.
- rubyn00bie 7y agoOh yeah, friend, here are a few packages: Mint (HTTP client library) - https://github.com/elixir-mint/mint https://github.com/elixir-mint/mint Jason (JSON library) - https://github.com/michalmuskala/jason https://github.com/michalmuskala/jason Tesla (Another HTTP library) - https://github.com/teamon/tesla https://github.com/teamon/tesla --- Yeah, the thing that has driven me to FP, and made Elixir/Erlang such a joy is that data and state are like not coupled (not saying they have to be in OOP, but god damn if I haven't had something that should only do a read do a write and fuck me too many times to count). Given the same input a function will always produce the same output, because values are constant. I've been writing Elixir for like 5-6 years now and four of them professionally, and I hope I never go back to a non FP language (save Rust or mind-boggling pay). It's kind of mind blowing when you realize, at any point in your program, you can simply serialize out your data, inspect it. Try that with a class, good fucking luck with whatever marshaling system you have... In Elixir/Erlang, all you (generally speaking) ever have are: - Strings (binaries, bit-strings, charlists) - Numbers (integer, float) - Lists (a list of things) - Maps (a set of keys and values) - Structs (a map with a predetermined set of keys) Recursion and pattern matching make for more readable code IMHO. Here's a fairly trivial snippet from the other day, of converting structs to maps (which Elixir doesn't do implicitly): https://gist.github.com/tehprofessor/fd8aebeb4804201a49f37d99ba4c900c https://gist.github.com/tehprofessor/fd8aebeb4804201a49f37d9... The biggest thing to keep in mind coming to a BEAM language from somewhere else is that both the language you're using (Elixir/Erlang/LFE[1]/etc) and the runtime were explicitly designed together to solve a specific category problem (distributed systems). This very unique combination provides, IMHO, the best environment you could ever want to run code in... In most languages you start up your server in its own process. Want to debug it? You gotta restart the process and then put your debug point in. Not the case in Erlang/Elixir, here's how I start up the Phoenix framework: iex -S mix phx.server What that does is both (a) starts the server, (b) opens up an interactive repl for the running application. You can then interact with the running system as it is, and holy shit does it make debugging wonderful. Want a fast cache for that one operation but don't want to setup X, Y, or Z? Use ETS it's built in: https://elixir-lang.org/getting-started/mix-otp/ets.html https://elixir-lang.org/getting-started/mix-otp/ets.html I can't tell you how much frustration I've saved just having reliable mechanisms for timing (thanks pre-emptive scheduling) like `Process.send_after` https://hexdocs.pm/elixir/Process.html#send_after/4 https://hexdocs.pm/elixir/Process.html#send_after/4 Need to make sure you're only sending messages to live nodes? `pg2` (process groups to the rescue): https://erlang.org/doc/man/pg2.html https://erlang.org/doc/man/pg2.html Something in Erlang just too slow, write a NIF (but really don't; this (NIF) is a last resort and the only way to you're likely to ever actually crash the VM). You can see a VERY simple example I have in the `wyhash_ex` directory: https://github.com/tehprofessor/shorts https://github.com/tehprofessor/shorts (please note shorts is just a toy project, and not quite complete as I got obsessed with the `gen_tcp` part). Finally, while yes processes, are the fucking peanut butter, jam, and jelly-- you really don't end up using them directly that often in your day to day life. If they aren't making a ton of sense or you don't find yourself using them everywhere, don't sweat it-- when you need to they'll be the obvious solution (even if implementing that solution isn't obvious at first b'cuz learnings). If you have any Elixir questions, I'm available on Twitter at the same handle as my Github links. Also, the Elixir slack is quite great as well. [1] LFE is List Flavoured Erlang Edit: Fixing formatting. God damn I suck at this.
- sjtgraham 7y agoThe Elixir source code itself.