7 ms·
Oh shit here I go (and learn Elixir for a whole year (again)) again. I love everything about Elixir, but Elixir constantly makes me doubt myself like no other
by sevenzero 4mo ago
Oh shit here I go (and learn Elixir for a whole year (again)) again.
I love everything about Elixir, but Elixir constantly makes me doubt myself like no other language. My brain isnt made for functional stuff, but this makes me want to try again.
Sucks that it's not really a beginner friendly ecosystem and usually, when having questions answered, people assume you already know a lot about the language.
- pdimitar 4mo agoI invite you to ask on ElixirForum. I have never seen a truly hostile response. Sometimes posts don't get traction due to ambiguity, and some smelled like "do my homework" so people ignored them. But every post with a genuine curiosity in it gets answered, as far as I can tell.
- sevenzero 4mo agoYea I've posted there twice as far as I remember. You will absolutely get help, whether you understand the answers is a whole different story. Elixirs community is great. Its just hard to learn because it's not yet widely adopted, there are no (non senior) roles for it and it's a lot of work understanding all the BEAM concepts. A thing just being interesting isn't enough motivation for me to learn, I need a bigger goal but with Elixir there do not seem to be any. My last experience with it was building something with Phoenix Liveview until I noticed how easily you can hijack the websocket and just spam random commands to your server or temper with payloads (with regular webapps ive built i never had this issue). Which made me quit that project.
- ch4s3 4mo ago> whether you understand the answers is a whole different story. You can always ask follow up questions for clarification, people there are generally really friendly.
- pdimitar 4mo agoFair. If you have this friction then it's not worth pursuing. One thing that really helped me pick it up was saying YOLO and rewriting one part of the business stack from Ruby on Rails to Elixir. It taught me quickly and well. The official guides are also great and IMO you can get through them all without a rush in two weekends. But again, if you don't want to then don't. You can also try asking right here in this HN thread. Maybe I or others would be willing to give you a more detailed response.
- sevenzero 4mo agoWhen building I couldn't get "what if I have ghost processes", "what if I spawn too many processes", "what if this architecture is bad compared to...", "when to kill processes", "whats the correct restart strategy for this" out of my head... It's so confusing to build for the BEAM that I ultimately gave up on it.
- pdimitar 4mo agoAh, true. You are right this assumes some familiarity. Definitely a gap. Check this out: https://www.theerlangelist.com/article/spawn_or_not https://www.theerlangelist.com/article/spawn_or_not Written by one of the very best Elixir mentors. I believe it will dispel most (hopefully all) of your doubts and clear things up.
- macintux 4mo agoI'd also suggest skimming this free ebook: https://erlang-in-anger.com https://erlang-in-anger.com
- toast0 4mo ago> "what if I have ghost processes", I'm not sure what a ghost process is? I guess something that's living beyond its usefulness / isn't supervised, etc? ... I don't speak Elixir, but you can do the equivalent of this Erlang to see everything on the node: rp([{X, erlang:process_info(X)} || X <- erlang:processes()]). Then you'll know what's going on. Caveat: if you have a lot of processes, that's going to use a bunch of memory; for production you probably don't want to use erlang:process_info/2 with specific items instead of the default items. And you might don't want to output something for all the processes if you have a lot of "normal" processes that won't need to be listed. > "what if I spawn too many processes", The default limit is 1,048,576, if you want to have more, you can add +P X to the erl command line with a bigger limit? Have your monitoring alert you when you're at ~ 80% of the limit. > "what if this architecture is bad compared to...", This probably addresses the real question of your too many process question. If your architecture is bad or if you spawn more processes than a good architecture would, your performance will be bad. If your architecture is really bad, you'll have a hard time solving the problems you're trying to solve. Future you will look upon your system and despair; you may also despair in the present... Eh, you're going to make bad architecture. BEAM won't solve all your problems. But, if you've got problems it can solve, IMHO, it can be a very nice way to solve them. > "when to kill processes", Kill processes (or let them crash) when they misbehave. Kill them (or let them exit normally) when they've done their work and they don't have anything else to do or wait for. When you spawn a process, you'll often have a pretty good idea of the conditions that would lead to its death... Ex: if you spawn a process to handle a connection, it should probably die around the time that the connection ends. If you spawn a process to handle a request, it should probably die when the request is handled. If you spawn a process to listen for connections, it probably should die when you don't want to listen anymore. Etc. > "whats the correct restart strategy for this" Well... it depends. Almost never the default strategy. The default strategy is a big foot gun; at least it is for Erlang, maybe they changed it in Elixir. I need zero hands to count the number of times I actually wanted BEAM to stop because some supervised process failed 3 times in a small time frame; but it's happened to me a lot more times than that. For per connection or per request things, the appropriate strategy is not to restart at all; for other things, try to restart a few times quickly then maybe every minute or so is probably sufficient. You'll want some sort of alerting. And if the restart strategy isn't right, you can always console in and poke it.
- arcanemachiner 4mo agoI haven't dug into this for a while, bit you should be able to define a catch-all event to return a respond to non-compliant requests . It should be built-in to some degree IMO, but I think it's not an unsolved problem.
- sevenzero 4mo agoThis will not work if a attacker guesses a function signature correctly as the catch all block usually is at the bottom of the module. If you use atoms in the function signature, attackers can just guess them, even if you never intended that function to be reachable from frontend code. That being said, I am not forced to use liveview, its just that most ressources nowadays use it.
- qaq 4mo agocommunity is super nice I am sure you will get help.
- ai_critic 4mo agoWhat functional stuff is throwing you off? A whole bunch of it can be written procedurally when starting out.
- sevenzero 4mo agoWith Elixir specifically it was the learning experience I had with Phoenix. I didn't understand how a Phoenix app booted, didn't know where to edit my config. Syntax like: ``` socket "/ws/:user_id", MyApp.UserSocket, websocket: [path: "/project/:project_id"] ``` Elixir gives you too much freedom on how to write something on a syntax level which really annoyed me.
- ch4s3 4mo ago> Elixir gives you too much freedom on how to write something on a syntax level This is true perhaps compared to python or go, but not compared to Java, JS/TS, or some others. > socket "/ws/:user_id", MyApp.UserSocket, websocket: [path: "/project/:project_id"] Socket is a behavior, which is like a trait or interface. MyAppWeb.UserSocket implements the behavior. It's basically a convenience over having to write a bunch of repetitive WS or long poll handling every time you want a socket like thing. Its pretty well documented https://phoenix.hexdocs.pm/Phoenix.Socket.html https://phoenix.hexdocs.pm/Phoenix.Socket.html.
- solid_fuel 4mo agoI love Elixir and Phoenix, but Phoenix especially uses a lot of compile-time macros and it can be a steep learning curve when you need to pull apart the skeleton framework to figure out how things are actually wired. I pretty frequently find myself needing to open up the source to understand what's actually going on, the docs aren't bad but it often feels like they assume a lot of existing familiarity with phoenix. In this example, `socket` is a compile time macro and it's being called with path = "/ws/:user_id" module = MyApp.UserSocket args = [ websocket: [ path: "/project/:project_id" ] ] and what is does is register that data with the `phoenix_sockets` attribute inside the module you called `socket` from. At compile time that gets turned into a lookup inside your module, and presumable then the UserSocket module is invoked when a websocket request hits the specified path. Would you find it more clear if socket was called like this? socket("/ws/:user_id", MyApp.UserSocket, [websocket: [path: "/project/:project_id"]]) Or, alternatively, would it help if the endpoint was more specifically defined like defmodule MyApp.Endpoint do use Phoenix.Endpoint, otp_app: :my_app, web_sockets: [ socket("/ws/:user_id", MyApp.UserSocket, [websocket: [path: "/project/:project_id"]]) ] end
- mihaelm 4mo agoDo you maybe know some Rust? I'm also not that experienced with FP languages, but Gleam felt familiar enough, due to some Rust-isms, to allow me to focus more on the concepts rather than the syntax. Granted, I spent a few afternoons with it, but if I were to pick a FP language again to wrestle my brain into submission, I'd probably go with Gleam due to familiarity.
- sevenzero 4mo agoI gave up on Rust even quicker than on Elixir haha. But yea I know about Gleam and I did build some fourier transform stuff with Rust a while back. I like Gleam generally. I am just much much slower with FP and think its extremely unintuituve compared to, say, Go for example.
- pjm331 4mo agohttps://pragprog.com/titles/lhelph/functional-web-development-with-elixir-otp-and-phoenix/ https://pragprog.com/titles/lhelph/functional-web-developmen... don't let the title fool you - the first half of the book is just elixir over the past 8 years this is the book i've used to ramp back up on elixir and it works like a charm every time - i've never finished it for me, a mark of a good programming book in this tutorial-project style is that I have started it half a dozen times and never finished it because at some point before the end I've been equipped w/ the tools to go off and do my own thing
- sevenzero 4mo agoYea I've worked through Elixir in Action and appreciate all book recommendations. My issue is, tutorial style books rarely cover security related concerns.
- felixgallo 4mo agowhat do you mean by 'security related concerns'?
- sevenzero 4mo agoHow to properly build a liveview thats safe against hijacking the websocket phoenix uses for liveviews. You can just do it from the devtools on client side. With regular HTTP requests at least I know what to look out for, with liveview there are almost no resources on how to build a view securely. Like I was able to just call the functions in my module by just addressing them from my browsers console. Just to name an example.
- OkayPhysicist 4mo ago[1] https://phoenix-live-view.hexdocs.pm/security-model.html https://phoenix-live-view.hexdocs.pm/security-model.html There's a guide in the LiveView docs that walks you through the security model. To be clear, you need to always assume that the user can send you anything. That's a fact of any networked system: Clients need to be assumed to be completely under the control of an evil user, because at the end of the day it is impossible to know whether you're talking to the client you wrote, or some evil program written by an adversary. Any function that acts as a handler for an event/message can be called by the user, at any time. You have to use session/socket state to handle authorization.
- cpursley 4mo agoI find beginners respond well to this resource: https://joyofelixir.com/toc.html https://joyofelixir.com/toc.html
- jimbokun 4mo agoComments like this always confuse me as object oriented programs riddled with state are much harder to reason about to me.
- sph 4mo agoI'm working on a game engine right now (written in object oriented language, of course) and I keep itching to design a compiled functional language for games, because state spread in thousand of objects, eldritch class hierarchies, are complete hell. Once you taste Elixir/Erlang, there is no going back to the madness.
- isityettime 4mo ago> I keep itching to design a compiled functional language for games Jank wants to be this, right? IIRC its author and chief maintainer was a game dev before he dedicated himself to the language. https://jank-lang.org/ https://jank-lang.org/ Maybe porting your engine would be a great way to prove out Jank 1.0 when it arrives ;)
- sph 4mo agoThanks for the pointer, never heard of this!
- isityettime 4mo agoAwesome! Maybe it's even a language you could enjoy contributing to. :D
- sevenzero 4mo agoThe confusing state riddling here happens in the background as your whole app basically is a state. The thing that really throws me off with Elixir is having to handle (possibly) hundreds of thousands of processes. Doing this correctly seemed impossible to learn for me.
- 4mo ago
- adamddev1 4mo agoDo https://htdp.org https://htdp.org and follow all the exercises carefully (yes, it will feel like baby work at first) - you will retrain your brain for functional stuff. :-)
- isityettime 4mo ago> I love everything about Elixir, but Elixir constantly makes me doubt myself like no other language. My brain isnt made for functional stuff, but this makes me want to try again. I experienced this really painfully when I was in college and took a kind of "survey of programming paradigms" course and tried Haskell for the first time. I'd been programming for years by then, and I couldn't believe how helpless I was at trying to complete things that had long felt "basic" to me. But I don't think it's about the brain not being suited, I think it's that contrast of your experience level in imperative languages vs. the fact that when working in a pure functional style, you start out as a newbie again. I think you'll gradually improve. I think the thing that finally made functional programming feel comfy for me was realizing how much I love composing code that basically feels like more generously spaced Bash "one-liners". The data starts out in one shape, so you run a command to dump it. Then you think of a step that gets it closer to what you want, you pipe it to that next command, and you take another look. And you keep going and at the end what you're looking at is typically pretty close to a series of transformations of data that you never mutate! Part of what makes this feel comfy in the shell is that you build up that vocabulary of commands just by puttering around your file system every day. Over the years my library of familiar "functions" in a Unix-like environment has grown quite large. In a pure functional programming environment, you have to do the same thing but it takes a little more effort to learn the vocabulary. Your most frequently used "commands" will be functions like map, fold, and zip instead of grep, cat, or sort. But the core of it is really the same, and what I love about building pipelines applies equally to both: you can build it piece by piece, and for each puzzle you're on, you can forget about the previous steps and just think about the next transformation of the data that's in front of you. There is something refreshingly, relaxingly low-context about that. Anyway I hope you give it a try and enjoy it. When we can learn to enjoy being bad at something, that's how we finally get good at it.
- cubefox 4mo ago> But I don't think it's about the brain not being suited, I think it's that contrast of your experience level in imperative languages vs. the fact that when working in a pure functional style, you start out as a newbie again. When I was in university, the introductory class was about Java, and an advanced class in the next semester was about Haskell. There were many imperative/functional newbies in both classes, but the Haskell class still progressed much more slowly. Haskell is simply much harder to grasp, independently of experience. You can also see this in the fact that even mathematicians use Python rather than Haskell for simulations. Despite the fact that there is no population that is better suited for Haskell than mathematicians. Even cookbooks are always written in an imperative style, never in a functional one. Why is that? Human brains find imperative algorithms simply more intuitive, and this is not explained by not being used to functional ones.
- sodapopcan 4mo agoCome hang out on Elixir Forum! Lots of friendly folks there who are happy to answer (and re-answer) beginner questions. It's not quite what it was a few years ago thanks to LLMs, but it's still quite active. EDIT: I see my cohort has already given you this suggestion :P