dogweather

dogweather

After using Elixir for a long time I can’t wrap my mind around Python’s APIs.

So with the help of functoolz curry, flip, and pipe, I can write HTML parsing code like this:

    def parse_title(dom: XmlResponse) -> Title:
        name = pipe(
            dom
            , html.xpath("//TITLE-TEXT") 
            , text.titleize
        )
        number = pipe(
            dom
            , html.xpath("//TITLE-NUM")  
            , text.split(" ")                  
            , seq.get(1) 
        )
        children = _parse_divisions_or_articles(number, dom)
        url      = _source_url(number)

        return Title(name, number, children, url)

I’m not re-writing any of these functions. I’m just wrapping each of them with a little code to give them a consistent interface. And once they each have this new API, they can be easily chained together.

Anyone else adapting other languages to the Elixir fluent API style? I don’t get much love from the Python community when showing this kind of code. :smile:

Showing Posts 1 to 8

kokolegorille

kokolegorille

I think You would get the same kind of love from the Elixir community when showing Object Oriented Elixir code :slight_smile:

Eiji

Eiji

Definitely no! In programming that’s the only one thing I call my personal anti-pattern (i.e. that’s my opinion without linking to some resources). I’m 100% against forcing solutions known from other languages in a way you wrote. Simply, every language is different. It have other styles and expectations. There was a talk about pipes in Erlang, but it was hard to implement, because in Erlang the data we work on is in the last function argument instead of first. Forcing Elixir-like pipes into Erlang have no sense as simply there would be no reasonable use case.

Speaking generally the problem often is not what you do, but how you do. You can force other language features and deal with expected hate or write a new features inspired by other languages. It’s not shame for others to improve, but nobody would agree to change habits because something is better in other languages. Same goes for law. You do not force law articles from country you born as it’s simply stupid. However you can instead propose changes to existing law system.

That’s endless topic i.e. assimilation vs integration

ivanov

ivanov

I got to attend the annual American Geophysical Union (AGU) fall meeting that was in San Francisco a few weeks ago, thanks to a pass from Matt Rocklin (author of functoolz and also dask). Someone there was also sharing similar positive sentiments about this kind of chaining, and said how it felt functional and Lisp-like, to which Matt responded something like “that’s exactly why I built it, I was re-writing in Python pieces that were missing for me that I was used to having in Clojure”.

I’d call it cross-pollination :slight_smile:

sodapopcan

sodapopcan

Hello and welcome to the forums!

I have nothing wrong with cross-pollination so long as its adopted by a language’s community as a whole. I also whole-heartedly applaud doing experiments. But I’m otherwise with @Eiji’s here. Coming across business code that someone decided to write in an idiom completely foreign to the language I’m working in is the worst. I’m actually getting a little worked up thinking about the several times this has happened to me :cold_sweat:

Is that how it’s ", ".join(["Hello", "World!"]) or something? I’ve heard Pythonistas say this makes more sense (somehow). I honestly don’t know much Python, though!

dogweather

dogweather OP

That’s very even-handed and balanced—a hard act for me to pull off. :slight_smile:

I don’t think it’s language design differences. I attribute it to their ages: Python is decades older than Elixir and it carries some baggage:

  • Parts of Python core are fluent (Elixir pipe-style) api’s, read left-to-right.
  • Other core libs require a right-to-left function-invocation style reading.

I’ve researched this deeply and the best I can see is, Python’s battling paradigms are present due to historical reasons.

In contrast, Elixir was designed with advantage of seeing was Python, Ruby, etc. did well and not so well. Ruby, in turn, was designed looking at Python. Even though everything in Python is an object, method chaining couldn’t be universally applied. Ruby sought to correct that in its design.

dogweather

dogweather OP

I totally agree. I would never produce code like this for a client. This is my personal indie project, and I prioritize my productivity.

Doh! yeah, it’s join() that kills me. It’s implemented only on string objects, not on lists or iterators.

I want to break up and refactor code where it’s meaningful. Not because a decision made in the 1980’s hasn’t been overturned. I like thinking about language design, and ponder these issues.

Concrete example from my code

I found this in about 3 minutes of looking. Incredibly, I see four different paradigms present in this one section of code. (!)

    # Return an HTML document's plaintext, cleaned up.
    raw_paragraphs         = rule_div.xpath("p")[1:].getall()
    cleaned_up_paragraphs  = [p.strip().replace("\n", "") for p in raw_paragraphs]
    cleaned_up_paragraphs2 = [re.sub(r" +", " ", p) for p in cleaned_up_paragraphs]
    non_empty_paragraphs   = list(filter(None, cleaned_up_paragraphs2))
  • Line 1: Fluent, chained method calls
  • Line 2: Mixed modes: A list comprehension containing chained method calls
  • Line 3: Mixed modes: A list comp containing a namespaced core regex library call
  • Line 4: A right-to-left “chain” of global function calls.

The worst part of this, for me, isn’t the poor maintainability from the need to shift between different styles. It’s that these “semantic roadblocks” of intermediate variables were essentially forced on me by the paradigm changes.

E.g., global replace is a string method when the pattern is a string. When the pattern become a regex, it’s now a library call conventionally namespaced with re.. So whatever data flow you were coding needs to shift paradigms due to this implementation detail.

Ruby (really, Matz) saw this, and fixed it by simply making String.sub() accept either a string or regex pattern.

Eiji

Eiji

Ok … wait, no! That’s not “ok”! :sweat_smile:

Umm … I never know Python is so … well … Why do “we” force it for children in schools? What do “we” teach them? :smiley:

I heard Python is good for beginners, but now I see something else … XP - memes are too old for “young blood”:

“WindowsXP or better” - so Linux will do the job!

so they decided to introduce new one:

“Required 10 years in Python or better” - so 1 day in Elixir will do the job!

Now I better understand why Python community does not like your idea. The 5th paradigm would be a hell for them even if it’s Elixir’s paradigm. Please let them rest at least for now at the start of 2024. :joy:

Happy New Year! :fireworks:

dimitarvp

dimitarvp

This should be qualified with context: many people said that learning an immutable FP language made them write more understandable, clearer, easier to read, easier to debug and test code in imperative OOP languages.

It’s not about trying to make Python stand on its head. It’s about writing Python that is… less ugly and hard-to-work-with Python.

Languages should indeed cross-pollinate as @ivanov said.

One prominent example: after Rust made enums (sum types) prevalent in compiled languages – nevermind that OCaml and Haskell had them for ages before that but oh well :003: – then many people started wanting them in other languages.

— All posts loaded —

Where Next? Top

Trending in Discussions Top

budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New
jtormey
Lately I’ve been thinking about how to organize components as a LiveView application grows. One of the pain points I’ve found (for myself...
New
Null-logic-0
What IDE or editor are you using for Elixir development? Personally, I use Zed, and I really like it, but sometimes I wish there were a ...
New
type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New

Other Trending Topics Top

KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
kip
In 2021 I started a new library called Tempo with the objective of modelling time as a set of intervals - not as instants. In 2022 I gave...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews