Skip to content

Left to Right Programming

Technology
27 11 0
  • This post did not contain any content.
  • This post did not contain any content.

    IMO all those examples are less readable than writing it in an imperative way using good function and variable names.

    Also, len() is a Python convention and a built-in function that calls __len__() on that object. It's even more established than .length in JS, so I really don't see why someone would expect anything else. And even then, one could call my_list.__len__() if they really wanted to be sure and have that "left to right" bonus.

  • This post did not contain any content.

    That sounds a lot like Functional Programming

  • This post did not contain any content.

    I also tend to prefer left to right and use threading macros a lot.

  • Except they don't like functional primitives like map unless they're namespaced to iterable types...

  • This post did not contain any content.

    I'm always suspicious of people who say that a language is suboptimal and use as evidence some filthy one-liner. Maybe if you bothered to write some whitespace and didn't write the language ignorant of its features (like generator expressions) you would end up with better code?

    sum(
        all(
            abs(x) >= 1 and abs(x) <= 3 for x in line
        ) and (
            all(x > 0 for x in line) or
            all(x < 0 for x in line)
        )
        for line in diffs
    )
    

    You no longer have to "jump back and forth" except one single time - you have to look to the end to see where line is coming from and then you can read the body of the main expression from start to finish.

    People don't, in fact, read code from top to bottom, left to right; they read it by first looking at its "skeleton" - functions, control flow, etc - until finding the bit they think is most important to read in detail. That implies that "jumping back and forth" is a natural and necessary part of reading (and hence writing) code, and so is nothing to fear.

    There is still a slight advantage to not having to jump around, but consider the costs: in Javascript, map and filter are methods on Array and some other types. So how are you going to implement them for your custom iterable type? Do you have to do it yourself, or write lots of boilerplate? It's easy in Python. It's not bad in Rust either because of traits, but what this all means is that to get this, you need other, heavy, language features.

    In practice, you often know what a comprehension is iterating over due to context. In those situations, having what the comprehension produces be the most prominent is actually a boon. In these scenarios in Rust/JS you are left skipping over the unimportant stuff to get to what you actually want to read.

  • I'm always suspicious of people who say that a language is suboptimal and use as evidence some filthy one-liner. Maybe if you bothered to write some whitespace and didn't write the language ignorant of its features (like generator expressions) you would end up with better code?

    sum(
        all(
            abs(x) >= 1 and abs(x) <= 3 for x in line
        ) and (
            all(x > 0 for x in line) or
            all(x < 0 for x in line)
        )
        for line in diffs
    )
    

    You no longer have to "jump back and forth" except one single time - you have to look to the end to see where line is coming from and then you can read the body of the main expression from start to finish.

    People don't, in fact, read code from top to bottom, left to right; they read it by first looking at its "skeleton" - functions, control flow, etc - until finding the bit they think is most important to read in detail. That implies that "jumping back and forth" is a natural and necessary part of reading (and hence writing) code, and so is nothing to fear.

    There is still a slight advantage to not having to jump around, but consider the costs: in Javascript, map and filter are methods on Array and some other types. So how are you going to implement them for your custom iterable type? Do you have to do it yourself, or write lots of boilerplate? It's easy in Python. It's not bad in Rust either because of traits, but what this all means is that to get this, you need other, heavy, language features.

    In practice, you often know what a comprehension is iterating over due to context. In those situations, having what the comprehension produces be the most prominent is actually a boon. In these scenarios in Rust/JS you are left skipping over the unimportant stuff to get to what you actually want to read.

    I agree with you that the one liner isn't a good example, but I do prefer the "left to right" syntax shown in the article. My brain just really likes getting the information in this order: "Iterate over Collection, and for each object do Operation(object)".

    The cost of writing member functions for each class is a valid concern. I'm really interested in the concept of uniform function call syntax for this reason, though I haven't played around with a language that has it to get a feeling of what its downsides might be.

  • I agree with you that the one liner isn't a good example, but I do prefer the "left to right" syntax shown in the article. My brain just really likes getting the information in this order: "Iterate over Collection, and for each object do Operation(object)".

    The cost of writing member functions for each class is a valid concern. I'm really interested in the concept of uniform function call syntax for this reason, though I haven't played around with a language that has it to get a feeling of what its downsides might be.

    I was also thinking about UFCS. I do like it for its flexibility, but I did try it in Nim one time and was left feeling unsure. Unfortunately I now can't remember what exactly I didn't like about it.

  • This post did not contain any content.

    Is string length len, length, size, count, num, or # ? Is there even a global function for length? You won’t know until you try all of them.

    This is Python basics, so the argument would be to optimize readability specifically for people who have zero familiarity with the language.

    (The other examples have the same general direction of readability tradeoff to the benefit of beginners, this one was just simplest to pick here)

    That's a valid tradeoff to discuss, if discussed as a tradeoff. Here it is not. The cost to readability for anyone with language familiarity appear to be not even understood.

  • Is string length len, length, size, count, num, or # ? Is there even a global function for length? You won’t know until you try all of them.

    This is Python basics, so the argument would be to optimize readability specifically for people who have zero familiarity with the language.

    (The other examples have the same general direction of readability tradeoff to the benefit of beginners, this one was just simplest to pick here)

    That's a valid tradeoff to discuss, if discussed as a tradeoff. Here it is not. The cost to readability for anyone with language familiarity appear to be not even understood.

    The point of the article is about how IDE's can't validate certain things as you type them in this order. The example of a string length function could be replaced by any other API.

  • The point of the article is about how IDE's can't validate certain things as you type them in this order. The example of a string length function could be replaced by any other API.

    That is one of the points, yes.

    But, the reason for wanting the IDE to validate based on partially entered expressions is given as making it easier to follow the code for a person working left-to-right.

    And it's not an invalid thing to want, but I expect the discussion to also include how it affects reading the code for a non-beginner.

  • I'm always suspicious of people who say that a language is suboptimal and use as evidence some filthy one-liner. Maybe if you bothered to write some whitespace and didn't write the language ignorant of its features (like generator expressions) you would end up with better code?

    sum(
        all(
            abs(x) >= 1 and abs(x) <= 3 for x in line
        ) and (
            all(x > 0 for x in line) or
            all(x < 0 for x in line)
        )
        for line in diffs
    )
    

    You no longer have to "jump back and forth" except one single time - you have to look to the end to see where line is coming from and then you can read the body of the main expression from start to finish.

    People don't, in fact, read code from top to bottom, left to right; they read it by first looking at its "skeleton" - functions, control flow, etc - until finding the bit they think is most important to read in detail. That implies that "jumping back and forth" is a natural and necessary part of reading (and hence writing) code, and so is nothing to fear.

    There is still a slight advantage to not having to jump around, but consider the costs: in Javascript, map and filter are methods on Array and some other types. So how are you going to implement them for your custom iterable type? Do you have to do it yourself, or write lots of boilerplate? It's easy in Python. It's not bad in Rust either because of traits, but what this all means is that to get this, you need other, heavy, language features.

    In practice, you often know what a comprehension is iterating over due to context. In those situations, having what the comprehension produces be the most prominent is actually a boon. In these scenarios in Rust/JS you are left skipping over the unimportant stuff to get to what you actually want to read.

    People don’t, in fact, read code from top to bottom, left to right

    100% this.

    This false premise is also why a few (objectively wrong) people defend writing long essays: functions with hundreds of lines and files with thousands; saying "then you don't have to go back and forth to read it", when in fact, no one should be reading it like a novel in the first place.

    Once you get used with list and dict comprehensions, they read just fine. Much like the functional approach is not really that readable for a newcomer either.

  • The point of the article is about how IDE's can't validate certain things as you type them in this order. The example of a string length function could be replaced by any other API.

    The example of a string length function could be replaced by any other API

    I don't know about that, len is a built-in -- like str, abs, bool. There are only a few of them and they're well known by people familiar to the language (which seems to exclude the article author). Their use is more about the language itself than about what to expect from a particular API.

    In fact, most Python APIs that go beyond built-in usage actually look much more object-oriented with "left-to-right" object.method() calls. So this argument seems silly and goes away with some familiarity with that language.

  • Comprehension is functional programming too, they arise from list monad https://www.schoolofhaskell.com/school/starting-with-haskell/basics-of-haskell/13-the-list-monad
    And Haskell do notation indeed reads top-down, unlike Python, but I find both quite readable.

  • That is one of the points, yes.

    But, the reason for wanting the IDE to validate based on partially entered expressions is given as making it easier to follow the code for a person working left-to-right.

    And it's not an invalid thing to want, but I expect the discussion to also include how it affects reading the code for a non-beginner.

    It's got nothing to do with being a beginner. I've been working as a professional software developer for ~15 years now and still I have to use new libraries/frameworks/in-house dependencies quite frequently. I know how to get the length of a string, and so does the author of the article.

    But that's why it's a simple example and nothing more, and it applies to everything else. We write left to right, and IDEs autocomplete left to right, so it makes sense for languages to be designed to work that way.

    There's a lot of reasons why Java works much better with IDEs than python, and this is one of them.


    Besides that, it is best practice to show problems on simple, easy to follow use cases that highlight exactly the problem in question without further fluff. It's expected that a non-beginner can abstract that problem into more difficult use cases, so I don't think OOP did anything wrong with choosing string length as an example.

  • The example of a string length function could be replaced by any other API

    I don't know about that, len is a built-in -- like str, abs, bool. There are only a few of them and they're well known by people familiar to the language (which seems to exclude the article author). Their use is more about the language itself than about what to expect from a particular API.

    In fact, most Python APIs that go beyond built-in usage actually look much more object-oriented with "left-to-right" object.method() calls. So this argument seems silly and goes away with some familiarity with that language.

    The argument is not silly, it totally makes sense, and your point even proves that.

    A lot of libraries use module-level globals and if you use from imports (especially from X import *) you get exactly that issue.

    Yes, many more modern APIs use an object-oriented approach, which is left-to-right, and that's exactly what OOP is argueing for. If you notice, he didn't end the post with "Make good languages" but with "Make good APIs". He highlights a common problem using well-known examples and generalizes it to all APIs.

    The auther knows full well that this blog post will not cause Python to drop the List comprehension syntax or built-in functions. What he's trying to do is to get people to not use non-LTR approaces when designing APIs. All the points he made are correct, and many are even more pressing in other languages.

    For example, for a hobby project of mine I have to use C/C++ (microcontrollers). And this problem is huge in C libraries. Every function is just dumped into the global name space and there's no way to easily find the right function. Often I have to go to google and search for an external documentation or open up the header files of a project to find a function that does what I want, instead of being able to just follow the IDE autocomplete on an object.

    And sure, if I know every library and framework I use inside out and memorized all functions, methods, objects, variables and fields, then it's easy, but unless you work 30 years in a bank where you maintain the same old cobol script for decades, that's not going to happen.

  • I'm always suspicious of people who say that a language is suboptimal and use as evidence some filthy one-liner. Maybe if you bothered to write some whitespace and didn't write the language ignorant of its features (like generator expressions) you would end up with better code?

    sum(
        all(
            abs(x) >= 1 and abs(x) <= 3 for x in line
        ) and (
            all(x > 0 for x in line) or
            all(x < 0 for x in line)
        )
        for line in diffs
    )
    

    You no longer have to "jump back and forth" except one single time - you have to look to the end to see where line is coming from and then you can read the body of the main expression from start to finish.

    People don't, in fact, read code from top to bottom, left to right; they read it by first looking at its "skeleton" - functions, control flow, etc - until finding the bit they think is most important to read in detail. That implies that "jumping back and forth" is a natural and necessary part of reading (and hence writing) code, and so is nothing to fear.

    There is still a slight advantage to not having to jump around, but consider the costs: in Javascript, map and filter are methods on Array and some other types. So how are you going to implement them for your custom iterable type? Do you have to do it yourself, or write lots of boilerplate? It's easy in Python. It's not bad in Rust either because of traits, but what this all means is that to get this, you need other, heavy, language features.

    In practice, you often know what a comprehension is iterating over due to context. In those situations, having what the comprehension produces be the most prominent is actually a boon. In these scenarios in Rust/JS you are left skipping over the unimportant stuff to get to what you actually want to read.

    Did we read the same blog post?

    Not a single time did OOP talk about readability. That was not a point at all, so I don't know why you are all about readability.

    It was all about having a language that the IDE can help you write in because it knows what you are talking about from the beginning of the line.

    The issue with the horrible one-liner (and with your nicely split-up version) is that the IDE has no idea what object you are talking about until the second-to-last non-whitespace character. The only thing it can autocomplete is "diffs". Up until you typed the word, it has no idea whether sum(), all(), abs(), <, >, or for-in actually exist for the data type you are using.

    If you did the same in Java, you'd start with diffs and from then on the IDE knows what you are talking about, can help you with suggesting functions/methods, can highlight typos and so on.

    That was the whole point of the blog post.

  • People don’t, in fact, read code from top to bottom, left to right

    100% this.

    This false premise is also why a few (objectively wrong) people defend writing long essays: functions with hundreds of lines and files with thousands; saying "then you don't have to go back and forth to read it", when in fact, no one should be reading it like a novel in the first place.

    Once you get used with list and dict comprehensions, they read just fine. Much like the functional approach is not really that readable for a newcomer either.

    The blog post wasn't about reading, but about writing. And people usually do write top-to-bottom, left-to-right.

    The whole point of the blog post was to write code that the IDE can help you with when writing. It didn't go into readability even once.

  • This post did not contain any content.

    I'll agree that list comprehensions can be a bit annoying to write because your IDE can't help you until the basic loop is done, but you solve that by just doing [thing for thing in things] and then add whatever conditions and attr access/function calls you need.

  • Did we read the same blog post?

    Not a single time did OOP talk about readability. That was not a point at all, so I don't know why you are all about readability.

    It was all about having a language that the IDE can help you write in because it knows what you are talking about from the beginning of the line.

    The issue with the horrible one-liner (and with your nicely split-up version) is that the IDE has no idea what object you are talking about until the second-to-last non-whitespace character. The only thing it can autocomplete is "diffs". Up until you typed the word, it has no idea whether sum(), all(), abs(), <, >, or for-in actually exist for the data type you are using.

    If you did the same in Java, you'd start with diffs and from then on the IDE knows what you are talking about, can help you with suggesting functions/methods, can highlight typos and so on.

    That was the whole point of the blog post.

    I dunno, did we?

    Screenshot from the post

    I think rust's iterator chains are nice, and IDE auto-complete is part of that niceness. But comprehension expressions read very naturally to me, more so than iterator chains.

    I mean, how many python programmers don't even type hint their code, and so won't get (accurate) auto-complete anyway? Auto-completion is nice but just not the be-all and end-all.

  • Your dedicated virtual assistant for data entry and web research

    Technology technology
    1
    2
    1 Stimmen
    1 Beiträge
    0 Aufrufe
    Niemand hat geantwortet
  • When A Face Scan Decides Who Eats And Who Keeps Their Job

    Technology technology
    2
    1
    24 Stimmen
    2 Beiträge
    35 Aufrufe
    R
    Someone heard about IBM providing punch card machines for Auschwitz and thought that was insufficiently banal.
  • I made a porn scroller without the clutter

    Technology technology
    1
    1
    4 Stimmen
    1 Beiträge
    30 Aufrufe
    Niemand hat geantwortet
  • We need to stop pretending AI is intelligent

    Technology technology
    331
    1
    1k Stimmen
    331 Beiträge
    5k Aufrufe
    dsilverz@friendica.worldD
    @technocrit While I agree with the main point that "AI/LLMs has/have no agency", I must be the boring, ackchyually person who points out and remembers some nerdy things.tl;dr: indeed, AIs and LLMs aren't intelligent... we aren't so intelligent as we think we are, either, because we hold no "exclusivity" of intelligence among biosphere (corvids, dolphins, etc) and because there's no such thing as non-deterministic "intelligence". We're just biologically compelled to think that we can think and we're the only ones to think, and this is just anthropocentric and naive from us (yeah, me included).If you have the patience to read a long and quite verbose text, it's below. If you don't, well, no problems, just stick to my tl;dr above.-----First and foremost, everything is ruled by physics. Deep down, everything is just energy and matter (the former of which, to quote the famous Einstein equation e = mc, is energy as well), and this inexorably includes living beings.Bodies, flesh, brains, nerves and other biological parts, they're not so different from a computer case, CPUs/NPUs/TPUs, cables and other computer parts: to quote Sagan, it's all "made of star stuff", it's all a bunch of quarks and other elementary particles clumped together and forming subatomic particles forming atoms forming molecules forming everything we know, including our very selves...Everything is compelled to follow the same laws of physics, everything is subjected to the same cosmic principles, everything is subjected to the same fundamental forces, everything is subjected to the same entropy, everything decays and ends (and this comment is just a reminder, a cosmic-wide Memento mori).It's bleak, but this is the cosmic reality: cosmos is simply indifferent to all existence, and we're essentially no different than our fancy "tools", be it the wheel, the hammer, the steam engine, the Voyager twins or the modern dystopian electronic devices crafted to follow pieces of logical instructions, some of which were labelled by developers as "Markov Chains" and "Artificial Neural Networks".Then, there's also the human non-exclusivity among the biosphere: corvids (especially Corvus moneduloides, the New Caleidonian crow) are scientifically known for their intelligence, so are dolphins, chimpanzees and many other eukaryotas. Humans love to think we're exclusive in that regard, but we're not, we're just fooling ourselves!IMHO, every time we try to argue "there's no intelligence beyond humans", it's highly anthropocentric and quite biased/bigoted against the countless other species that currently exist on Earth (and possibly beyond this Pale Blue Dot as well). We humans often forgot how we are species ourselves (taxonomically classified as "Homo sapiens"). We tend to carry on our biological existences as if we were some kind of "deities" or "extraterrestrials" among a "primitive, wild life".Furthermore, I can point out the myriad of philosophical points, such as the philosophical point raised by the mere mention of "senses" ("Because it’s bodiless. It has no senses, ..." "my senses deceive me" is the starting point for Cartesian (René Descartes) doubt. While Descarte's conclusion, "Cogito ergo sum", is highly anthropocentric, it's often ignored or forgotten by those who hold anthropocentric views on intelligence, as people often ground the seemingly "exclusive" nature of human intelligence on the ability to "feel".Many other philosophical musings deserve to be mentioned as well: lack of free will (stemming from the very fact that we were unable to choose our own births), the nature of "evil" (both the Hobbesian line regarding "human evilness" and the Epicurean paradox regarding "metaphysical evilness"), the social compliance (I must point out to documentaries from Derren Brown on this subject), the inevitability of Death, among other deep topics.All deep principles and ideas converging, IMHO, into the same bleak reality, one where we (supposedly "soul-bearing beings") are no different from a "souless" machine, because we're both part of an emergent phenomena (Ordo ab chao, the (apparent) order out of chaos) that has been taking place for Æons (billions of years and beyond, since the dawn of time itself).Yeah, I know how unpopular this worldview can be and how downvoted this comment will probably get. Still I don't care: someone who gazed into the abyss must remember how the abyss always gazes us, even those of us who didn't dare to gaze into the abyss yet.I'm someone compelled by my very neurodivergent nature to remember how we humans are just another fleeting arrangement of interconnected subsystems known as "biological organism", one of which "managed" to throw stuff beyond the atmosphere (spacecrafts) while still unable to understand ourselves. We're biologically programmed, just like the other living beings, to "fear Death", even though our very cells are programmed to terminate on a regular basis (apoptosis) and we're are subjected to the inexorable chronological falling towards "cosmic chaos" (entropy, as defined, "as time passes, the degree of disorder increases irreversibly").
  • Honda successfully launched and landed its own reusable rocket

    Technology technology
    170
    1
    1k Stimmen
    170 Beiträge
    2k Aufrufe
    gerryflap@feddit.nlG
    Call me an optimist, but I still hold the hope that we can one day do better as humanity than we do now. Humanity has become a "better" species throughout its existence overall. Even a hundred years ago we were much more horrible and brutal than we are now. The current trend is not great, with climate change and far-right grifters taking control. But I hold hope that in the end this is but a blip on the radar. Horrible for us now, but in the grand scheme of things not something that will end humanity. It might in the worst case set us back a few hundred years.
  • 136 Stimmen
    29 Beiträge
    304 Aufrufe
    J
    Yeah, I was going to say that TV wasn't much of a news source to begin with. The real issue is that social media for news is probably worse - now everyone can be spoonfed the news they want.
  • 22 Stimmen
    14 Beiträge
    139 Aufrufe
    F
    you don’t need to worry about trying to enforce it ( By the simple expedient of there being essentially nothing you can enforce.
  • Microsoft's AI Secretly Copying All Your Private Messages

    Technology technology
    4
    1
    0 Stimmen
    4 Beiträge
    58 Aufrufe
    S
    Forgive me for not explaining better. Here are the terms potentially needing explanation. Provisioning in this case is initial system setup, the kind of stuff you would do manually after a fresh install, but usually implies a regimented and repeatable process. Virtual Machine (VM) snapshots are like a save state in a game, and are often used to reset a virtual machine to a particular known-working condition. Preboot Execution Environment (PXE, aka ‘network boot’) is a network adapter feature that lets you boot a physical machine from a hosted network image rather than the usual installation on locally attached storage. It’s probably tucked away in your BIOS settings, but many computers have the feature since it’s a common requirement in commercial deployments. As with the VM snapshot described above, a PXE image is typically a known-working state that resets on each boot. Non-virtualized means not using hardware virtualization, and I meant specifically not running inside a virtual machine. Local-only means without a network or just not booting from a network-hosted image. Telemetry refers to data collecting functionality. Most software has it. Windows has a lot. Telemetry isn’t necessarily bad since it can, for example, help reveal and resolve bugs and usability problems, but it is easily (and has often been) abused by data-hungry corporations like MS, so disabling it is an advisable precaution. MS = Microsoft OSS = Open Source Software Group policies are administrative settings in Windows that control standards (for stuff like security, power management, licensing, file system and settings access, etc.) for user groups on a machine or network. Most users stick with the defaults but you can edit these yourself for a greater degree of control. Docker lets you run software inside “containers” to isolate them from the rest of the environment, exposing and/or virtualizing just the resources they need to run, and Compose is a related tool for defining one or more of these containers, how they interact, etc. To my knowledge there is no one-to-one equivalent for Windows. Obviously, many of these concepts relate to IT work, as are the use-cases I had in mind, but the software is simple enough for the average user if you just pick one of the premade playbooks. (The Atlas playbook is popular among gamers, for example.) Edit: added explanations for docker and telemetry