sodapopcan

sodapopcan

I’m with you in that I really really dislike the term “magic” when it comes to macros. They aren’t magic and I feel the difficulty people have with them is their own mental blockers thinking they are harder than they are. Macros are great and are at the heart of what makes Elixir what it is.

However, I do personally dislike the general purpose type stuff. I actually prefer happy_with’s syntax but I’ve never used it because regular with isn’t bad and I would always rather use the vanilla language. I also do get annoyed at “having to learn” (macros or functions) different ways of doing things there are already perfectly good answers to. It’s a death by a thousand cuts scenario for me. Really, I just really like Elixir how it is :slight_smile:

2
Post #11
cmo

cmo

ok_tuple, wrap_in_ok ok_wrap, wrap_in_ok_tuple, to_ok_tuple.

Solution 1 is evil, bad, bad, naughty, ugly, eww, yucky.
Solution 3 is to return exception structs, as discussed in the thread you linked, in keathley’s blog post that @soadpopcan lined and this one. Using this method, you can either ignore the error, raise it or use it.

Your example is still contrived because you either don’t care which error it is or all you’re doing with the error is IO.puts. All of those User and Country functions must be in your codebase(?), so you could easily write functions that return ok/error tuples if that is what you need.

To me, it feels easier to rewrite a function in a legible way than to introduce a library that does things in an idiomatic-Rust/non-idomatic-Elixir way. You can’t call your library idiomatic Elixir code if you just wrote it and nobody is using it yet.

As @sodapopcan touched on, pipes are often data transformations, and putting a bunch of conditionals in a pipe makes the control flow difficult to see at a glance.

2
Post #12
dorgan

dorgan

It’s not, I love with, I just wish it was better, and thankfully elixir is extensible via macros(and I kinda like Zig’s try). I’d love if we didn’t have to wait for those changes to land in the languages themselves or to be added in a library by someone with an important name.

In the context of the OP I think it’s valuable because, well, having a normalized return type is valuable but it has the same side effect as with: it makes you create functions

I have a problem personally with that because there wasn’t a case where this sequence doesn’t happen:

  1. A few lines of code exist, and they’re extracted to a private function to make with less painful or avoid credo’s cyclomatic complexity check, or the formatter butchers the code, or with would only handle sparse branching points and you need many nested cases and Credo gets mad at you, or some other “small” issue
  2. Now that the private function exist, that piece of code can be called by other code in the same module
  3. 2 or more functions that use those private functions have slightly different use cases, so they start to add opts to it to change the behavior
  4. These functions get used by even more functions ouside the module, which also have different requirements
  5. On top of the many slightly changes in required behavior, they also produce side effects, so now you need to keep track of that too

Functions have the side effect of encouraging reuse and that reuse is rarely intentional enough to not cause problems

So while, again, I value value normalization, I don’t think libraries like the OP help a lot in the long term. I have similar gripes with Ecto.Multi vs Repo.transact like in the other thread. The common suggestion of “create more functions”(and maybe pipe them) sounds good on paper but it almost always gives me problems and I don’t want all that.

1
Post #13
D4no0

D4no0

Why? Is there some kind of company policy that restricts you defining a DSL/features that are valuable to your business needs?

IMO with beats competition by far. Take a look at how scala deals with their “monoids”, in a for comprehension, it just feels like an afterthought to some feature they couldn’t implement.

The usage of course varies and there is room for abuse, this especially happens from people coming from other ecosystems, however if you use it correctly it is invaluable.

1
Post #14
dorgan

dorgan

It’s very hard to convince people to adop something or to not thoroughly question the implementation to the point of inaction if you don’t have a well known name or reputation. To be more concrete also in reply of the previous “why heresy?” question, I don’t see it mentioned as often nowadays but people were very reluctant to adop patterns outside of “the blessed way”, so heresy seemed appropriate for something that explores the opposite thing. It was nothing intentional, it just happened. (Also to be fair Jose got a lot of pushback in the proposals to improve for, change is hard)

It does, but again, it could be better. And the best way to find what’s better is to actually try other approaches and try to identify what exactly could be better. I pointed above what I personally think that is. Sometimes you are not “holding it wrong” but it could really be different.

1
Post #15
tfwright

tfwright

I agree that the “result tuple” is such a widespread convention in Elixir it’s a little puzzling there’s not something built in to help you construct those tuples from raw values. But there have been many libraries created to “help” with the problem but they don’t ever seem to gain widespread traction I believe because it is too easy to just add something to your project to assist with whatever specific flavor of that convention the maintainers want to promote.

I think to move forward on this issue we would need a proposal for a change to the standard lib (Tuple.result?) rather than another lib, which there very well might have been, but I don’t think I’ve seen any.

1
Post #16
D4no0

D4no0

It is kinda true, this is our nature as humans, even though I would recommend you to try, you never know.

Delivering the idea correctly is also very important, this is why even though the library from this post might prove useful in other ecosystems, there is a clear lack between idea and practicality in elixir ecosystem.

0
Post #17
D4no0

D4no0

I think this is a terrible idea. The tuple convention {:ok, response} is a ghetto monad that counts as a pure data structure.

When you will start enforcing in the language a convention that functions must return a specific shape of data, you will start to have inconsistent behavior:

  • What if my function doesn’t abide by these rules? Example bang functions.
  • What if my return response is a more comprehensive data structure? Example: {:ok, response, partial_errors}

Instead of dealing with that proactively it is better to let the user decide, defensive programming is bad practice that needs to die out.

This however doesn’t mean that you can’t use any kind of linters, specific credo rules or dialyzer configurations that would invlolve your local codebase following some specific rules.

2
Post #18
tfwright

tfwright

I don’t disagree, and I wouldn’t be surprised if this is how the core team feels as well, but it’s unfortunate that the strength of the convention continually creates the pressure for these various libs to help “standardize” the practice…

3
Post #19
sodapopcan

sodapopcan

lol, ya! It’s actually someone pointing out on this forum a few years ago that {:ok, response} is a monad is what made me finally understand wtf a monad is. I had a decent, most-of-the-way understanding already, but it never quite clicked. I said this recently but I really see Elixir as “elegant yet scrappy” and I love that about it. I am also a big fan of convention and really dislike codebases that are a mish-mash of styles. I have a love/hate relationship with reading code and and dealing with a frustrating bug is not when I want to be met with someone’s creative coding around a straightforward problem.

@dorgan there is actually a lot to respond to there since you touch on a few things I find myself thinking about a lot.

Warning: Lots of stream-of-consciousness word vomit ahead… please feel free to skip :slight_smile:

The easiest to address it that my only problem with with as it is how the formatter handles it. I wish it would let you just put the do on its own line! It’s literally the only thing about the formatter I really dislike.

Otherwise, the whole “extracting private functions” thing has been on my mind a lot recently. I feel that a lot of people coming to Elixir from OO, particularly Ruby, have been burned by the gross overuse of single-use private functions. I feels that many have the perfectly common human response to revolt by going too much the other direction. I try and just extract private functions when the meaning starts to get muddled. I’ve never actually thought too much about how they will get used by other functions in the module and honestly, this is because I don’t much experience working alongside other Elixir developers (only about 8 months-worth). What I’m getting at is that I really only use with with library functions that have consistent return types or each step is itself a significant local function (or in another module that I own). If I can’t do that I just don’t use with, although I don’t have any good examples of what that looks like.

Otherwise, I do think it’s great to be able to mold the language around so people can experiment with new ideas. But for me, it’s not really about big names it’s more whether or not it will ever make it into the language that I would continue to use it. It’s funny you mention the transact thread because I’ve been following along and, even though Ecto is a library itself and I do find Ecto.Multi a bit clunky at times, it’s so ubiquitous that I’d have a hard time adopting transact in my own projects. I also actually found myself needing to compose multis in a recent project which was my immediate question when first reading that thread and it got answered without my asking :sweat_smile: In any event, maybe it’s a little closed-minded of me but I like to keep dependencies lean and I’d much rather pull in libraries that are solving the tough application problems I don’t want to deal with.

One thing I am very interested in is using macros to mold the language into a DSL for your business domain. From what I understand this was one of the original ideas behind LISP that has never caught on (and I do think I understand why). To me that would be well worth coming onto a project and learning. But when teams pull in libraries just to make something “a little more like other functional languages” I find it a bit annoying. It means I’m going to get used to random little things and then probably miss them when they are gone, ha. As I said earlier, I really love the scrappy side of Elixir and that a lot of stuff is left up to convention.

2
Post #20