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 8 to 1

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.

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:

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.

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.

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!

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:

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

kokolegorille

kokolegorille

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

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
caslu
I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. ...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
marciol
It would be helpful to have a list of companies worldwide that hire engineers without prior experience in Elixir. Often, it can be quite ...
New
durvia
Anyone running long-lived stateful processes on BEAM? We’re building an AI agent runtime and would love to compare notes. We’re a small ...
New

Other Trending Topics Top

marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
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
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
Aludel - LLM Evaluation Workbench Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews