8 ms·
While action fallback sounds pretty useful, it feels like a framework solution to a language problem. The language just doesn't handle nested if statements very
by tchow 10y ago
While action fallback sounds pretty useful, it feels like a framework solution to a language problem. The language just doesn't handle nested if statements very well.
Also writing elixir always feels like the lines of code are longer than the width of my IDE. It is so much text...
My Elixir (and phoenix) experience so far, has been far from amazing contrary to all the hype on hn all the time.
- pmarreck 10y ago> The language just doesn't handle nested if statements very well One of the advantages of this language I've found is that I specifically DO NOT need to nest "if" statements anymore! Hie thee to pattern-matching and private functions that take different states (which are normally handled by nested ifs). Also, nested ifs are REALLY hard to test well, and breaking them out into separate functions with the same name but different clauses makes it MUCH easier to unit-test.
- pawelduda 10y agoInteresting. While Elixir syntax definitely requires writing more code, than for example Ruby which I use the most, I have not been struggling too much. Could you give some examples of these long, problematic snippets? Also, what are the other things you did not like about Elixir/Phoenix? I am really curious to hear about them since, here on HN they are mostly praised and I wonder myself what are the cons (my experience has been great so far).
- pmontra 10y ago$ irb [1, 2, 3, 4]. select {|n| n % 2 == 0}. map {|n| n * n}. reduce {|sum, n| sum + n} # 20 vs $ iex [1, 2, 3, 4] \ |> Enum.filter(fn(n) -> rem(n, 2) == 0 end) \ |> Enum.map(fn(n) -> n * n end) \ |> Enum.reduce(0, fn(n, sum) -> sum + n end) That Ruby code is so compact that I split it on multiple lines only to make the comparison easier. Even Python is more compact even if it's harder to read because of the reverse order (I'm sure that there is a nested comprehension for that but it's beyond my comprehension skills) from functools import reduce reduce(lambda x, sum: sum + x, \ map(lambda x: x * x, \ filter(lambda x: x % 2 == 0, \ [1, 2, 3, 4]))) # 20 The problem here is having to type Module.function(value) vs object.method OO languages have a more compact notation because objects act as namespaces. Elixir has alias but it doesn't help much and must be used wisely. alias Enum, as: E would only confuse people and gain little. Then Elixir has too many do end compared to Ruby (coming from Ruby I feel them unnecessary), but that's not a big deal. Moving from syntax to programming patterns, having to define twice my functions in GenServer (internal API and public API) is too much boilerplate. I'd like to have time to study macros really well and end up with a DryGenServer that lets me def the external API with the internal implementation. Maybe I'll defmacro a defasync and a defsync, that generate the standard "double" GenServer functions.
- virtualwhys 10y agoscala> List(1,2,3,4). filter(_ % 2 == 0). map(x => x * x). reduce(_ + _)
- detaro 10y agoI know you want to show it as parallel as possible, but: "pythonic" python (sum admittedly is a shortcut that only works for the special case +): sum(x * x for x in [1,2,3,4] if x % 2 == 0)
- klibertp 10y agoWorks in Elixir, too... Enum.sum(for x <- [1, 2, 3, 4], rem(x, 2) == 0, do: x * x) Edit: BTW: I'm not sure, but I think Erlang had list comprehensions even earlier than Python.
- e12e 10y agoI was going to comment along these lines - while functools exists, where appropriate I'd say iterators and/or list comprehensions are more pythonic. Note that if one wants to work with simple reduce functions, there's the operator module to help: from functools import reduce from operator import add # I'd also say this makes for more readable code, # documenting intent - but many will probably say that # basic arithmetic should be clear enough: def is_even(n): return n % 2 == 0 def square(n): return n*n # Don't do this for summing integers, just use "sum": reduce(add, (square(n) for n in range(1,5) if is_even(n))) > 20 Note the use of range() rather than literal list - if you have a list, that should probably be passed in by name. Anyway, the point wasn't so much bikeshedding or code golfing - just expanding on what I think is "more pythonic" take on it. And to be clear, I'd probably prefer: sum(x * x for x in range(1,5) if x % 2 == 0) for this particular example. And for more complex "real world" cases, I'd probably prefer to define my "reduce" function directly ie: def my_sum(iterator): return reduce(add, iterator) int_sequence = range(1,5) my_sum(square(n) for n in int_sequence if is_even(n)) > 20 Note that python has map and filter as built-ins, so it's also possible to do: sum(map(lambda x:x*x,filter(lambda n:n%2==0,range(1,5)))) # Which I find rather unreadable, but gets a bit better # without lambdas: sum(map(square, filter(is_even,int_sequence))) (Phew, please excuse my personal dive into new/old list-comprehension/functional python -- but at least now I'm more clear on why everyone keep adding "threading" macros/syntax to their functional languages :-) [ed: And if one wants threading-like syntax along with some parallelization and lazy-ness in python, there's a module for that: https://github.com/EntilZha/PyFunctional https://github.com/EntilZha/PyFunctional from functional import seq (seq(range(1,5)) .map(square) .filter(is_even) .reduce(add) ) Just FYI.]
- djm_ 10y agoMy first thought when I read this was that it sounds like you're struggling against the language because you're trying to use it in an imperative fashion. I'm well aware this may not be correct but it's what I'm going to assume for the rest of this comment, so please forgive me if it's incorrect. Elixir is a functional language, and while it's not pure, nested if statements deliberately do not belong. The if statement itself is actually just a macro to a case/switch, the only reason it is there is to reduce the verbosity in cases where only one conditional branch is needed, José felt the practicality of this outweighed the fact it may get abused. To use Elixir properly is to try and move away from conditional constructs as much as is realistically possible. This means instead using pattern matching, guard classes and multiple clause functions (both named and anonymous). Once you take advantage of these you'll find your code stays flatter while keeping the individual branches of your conditional logic tied up into small independently testable functions. If anyone would like to read more, I found these [1] [2] to be helpful. [1] http://culttt.com/2016/05/30/branching-conditionals-elixir/ http://culttt.com/2016/05/30/branching-conditionals-elixir/ [2] http://blog.lucidsimple.com/2016/01/24/pattern-matching-helps-reduce-conditional-logic.html http://blog.lucidsimple.com/2016/01/24/pattern-matching-help...
- swanros 10y agoAgreed, the fact that you're saying you can't nest if statements is a sign that you still don't get the grasp of functional programming. cases, conds, with statements, recursion, pattern matching...
- rehemiau 10y agoIt is not an imperative language. You can't hit a nail with a screwdriver. Well, you can, but... ;)
- bsukn 10y agoElixir is essentially just erlang, with a more convenient syntax. Being a functional language, you shouldn't be doing nested if statements in the first place. The if statement in elixir is really just a case-switch macro. Also writing elixir always feels like the lines of code are longer than the width of my IDE This just seems weird to me. The pipe operator makes the code really compact in my experience, and I wish other languages had this feature. I have a feeling you never bothered to really learn the language and just jumped on the new fancy framework, and tried to glue some code you didn't understand. You struggling to write something isn't a language problem. I'm interested in seeing some examples that highlight your problems.
- swanros 10y agoComing from an imperative language background, it certainly took some time for me to start using and understanding functional constructs. But the nice thing is that once you pass that bump, it's a hell of a freeway to go down.
- sotojuan 10y agoWhy are you using if statements in a functional language geared towards pattern matching?