Live data from Hacker News

Left to Right Programming

graic.net

11–20 of 372 posts

Re: Left to Right Programming

#11

len(list(filter(lambda line: all([abs(x) >= 1 and abs(x) 0 for x in line]) or all([x This really isn’t fair on Python. Python isn’t very much not designed for this style of functional programming. Plus you haven’t broken lines where you could. Rewrite it as a list comprehension and add line breaks, and turn the inner list comprehensions into generator expressions (`all([…])` → `all(…)`), and change `abs(x) >= 1 and a…

  abs(x) >= 1 and abs(x) 
Is also unidiomatic in Python.

  1 
Means the same thing and tightens it up a bit, and reads better since it's indicating that you're testing if something is in a range more clearly.

EDIT: To add:

The filter, list construction, and len aren't needed either. It's just:

  sum(map(predicate, diffs)) # this counts the number of elements in diffs which satisfy predicate, map is lazy so no big memory overhead
Or alternatively:

  sum(predicate(diff) for diff in diffs)
The predicate is complex enough and used twice, so it warrants extraction to its own named function (or lambda assigned to a variable), but even if it were still embedded this form would be slightly clearer (along with adding the line breaks and removing the extra list generations):

  sum(map(lambda line: all(1  0 for x in line) or all(x 

Re: Left to Right Programming

#12
post #8

I miss the F# pipe operator ( https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref... ) in other languages. It's so natural to think of function transform pipelines. In other languages you have to keep going to the left and prepend function names, and to the right to add additional args, parens etc ...

n.b. pipe operators also exist in various forms in other languages. OCaml, Elixir, Clojure, Haskell...

Re: Left to Right Programming

#14
post #5

> Programs should be valid as they are typed. That would be nice if devs always wrote code sequentially, i.e. left to right, one character at a time, one line at a time. But the reality is that we often jump around, filling in some things while leaving other things unfinished until we get back to them. Sometimes I'll write code that operates on a variable, then a minute later go back and declare that variable (perhap…

Exactly. You only write code sequentially when it's a new file.

If i decide to add a new field to some class, i won't necessarily go to the class definition first, I'll probably write the code using that field because that's where the IDE was when i got the idea.

If I want to enhance some condition checking, i'll go through a phase where the piece of code isn't valid while I'm rearranging ifs and elses.

Re: Left to Right Programming

#15
post #5

> Programs should be valid as they are typed. That would be nice if devs always wrote code sequentially, i.e. left to right, one character at a time, one line at a time. But the reality is that we often jump around, filling in some things while leaving other things unfinished until we get back to them. Sometimes I'll write code that operates on a variable, then a minute later go back and declare that variable (perhap…

Yes. Seems like an arbitrary limitation to force it.

Re: Left to Right Programming

#16
post #8

I miss the F# pipe operator ( https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref... ) in other languages. It's so natural to think of function transform pipelines. In other languages you have to keep going to the left and prepend function names, and to the right to add additional args, parens etc ...

I've had to migrate to mostly Python for my work, and this is the thing I miss the absolute most from R (and how it works so seamlessly with the tidyverse)

Re: Left to Right Programming

#17
SQL has this problem since it wants the SELECT list before the FROM/JOIN stuff.

I've seen some SQL-derived things that let you switch it. They should all let you switch it.

Re: Left to Right Programming

#18
post #14
post #5

> Programs should be valid as they are typed. That would be nice if devs always wrote code sequentially, i.e. left to right, one character at a time, one line at a time. But the reality is that we often jump around, filling in some things while leaving other things unfinished until we get back to them. Sometimes I'll write code that operates on a variable, then a minute later go back and declare that variable (perhap…

Exactly. You only write code sequentially when it's a new file. If i decide to add a new field to some class, i won't necessarily go to the class definition first, I'll probably write the code using that field because that's where the IDE was when i got the idea. If I want to enhance some condition checking, i'll go through a phase where the piece of code isn't valid while I'm rearranging ifs and elses.

[dead]

Re: Left to Right Programming

#19

> If you aren’t familiar with Rust syntax, |argument| result is an anonymous function equivalent to function myfunction(argument) { return result; }. > Here, your program is constructed left to right. The first time you type line is the declaration of the variable. As soon as you type line., your editor is able to suggest available methods. Yeah, having LSP autocomplete here does feel nice. But it also makes the code…

> But it also makes the code harder to scan than Python. Quick readability at a glance seems like the bigger win than just better autocomplete.

It depends a lot on what you’re accustomed to. You get used to whichever style. Just like different languages use different sentence order: subject, object and verb appear in all possible orders in different languages, and their speakers get along just fine. There are some situations where one is clearly superior to the other, and vice versa.

`text.lines().map(|line| line.split_whitespace())` can be read loosely as “take text; take its lines; map each line, split it on whitespace”. Straightforward and matching execution flow.

`[line.split() for line in text.splitlines()]` doesn’t read so elegantly left-to-right, but so long as it’s small enough you spot the `for` token, realise you’re dealing with a list comprehension, and read it loosely from left to right as “we have a list made up of splitting each line, where lines come from text, split”. Execution-wise, you execute `text.splitlines()`, then `for line in`, then `line.split()`. It’s a bunch of left-to-rights embedded in a right-to-left. This has long been noted as a hazard of list comprehensions, especially the confusion you end up with with nested ones. Now you could quibble over my division of `for line in text.splitlines()` into two runs; but I think it’s fair. Consider how in Rust you get both `for line in text.split_lines() { … }` and `text.split_lines().for_each(|line| { … })`. Sometimes the for block reads better, sometimes .for_each() or .map() or whatever does. (But map(lambda …: …, …) never really does.)

Python was my preferred language from 2009–2013 and I still use it not infrequently, but Rust has been my preferred language ever since. I can say: I find the Rust version significantly easier to read, in this particular case. I think the fact there are two levels of split contributes to this.

Re: Left to Right Programming

#20
post #5

> Programs should be valid as they are typed. That would be nice if devs always wrote code sequentially, i.e. left to right, one character at a time, one line at a time. But the reality is that we often jump around, filling in some things while leaving other things unfinished until we get back to them. Sometimes I'll write code that operates on a variable, then a minute later go back and declare that variable (perhap…

That’s not quite what the article’s about, though it’s interesting too.
Post reply on HN