Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Humans can't either? I think if this convention had been more usable form of programming, we'd know by now


Once you get used to it, traditional ways look tedious and annoying to me. I think the power is in 'once you get used to it'. That will keep out most people. See python llm implementations vs k ones as a novice and you will see verbose unreadable stuff vs line noise. When you learn the math you see verbose code where the verbose code adds nothing at all vs exactly what you would write if you could.


Tedious and annoying for one-off commands maybe. It's like regex. Pretty compelling if you're writing a one-off pattern, you get immediate feedback and then you throw it away.

But it's not a good idea to use regexes in code that you're going to use long term. It's justifiable for simple regexes, and many people go against this advice, but really for anything remotely complex regexes become totally unreadable and extremely bug prone. Complex regexes are a huge code smell and array languages are pretty much one enormous regex.


Yeah never had that issue; maybe it's because I have been doing regexes (and apl which people call write only as well) for 30 years: it is not unreadable, nor throw away. I find it far more readable than the alternatives; reading pages of elaborate 'pseudocode' is more bothersome/time consuming than a oneliner to me.


What would you propose as an alternative to regexes that provides the same functionality without the unreadable syntax?

I wrote something like that in C# once [0] but I'm not getting the impression that there's a lot of demand for that kind of thing.

[0] https://github.com/Timwi/Generex


Chiming in - I've found the Pattern type in Unison[0] to be very nice to use. When you're just using the built-in patterns, it is similar to verbose regex. The real power of them is that it's easy to define, name, and re-use sub-patterns. I think it's similar to parser combinators in this way, like nom from rust[1].

[0] https://share.unison-lang.org/@unison/website/code/main/late...

[1] https://docs.rs/nom/latest/nom/


There's a whole list of alternative syntaxes here:

https://github.com/oils-for-unix/oils/wiki/Alternative-Regex...

I haven't actually used them because generally the right alternative to a regex is a proper parser.


Parsing expression grammars (pegs) are usually IME more maintainable long term, partially just because of much more testable and composable they are


I suspect but am not sure that PEGs cannot do negative nor positive lookbehind, but it is not a very used feature.


Yeah that’s true IIRC but it’s rarely been a problem for my usage!


I mean, I got used to RPN and think that's the utmost bestest way to write. Objectively it's not as usable. Learnability is a part of usability


It might be a question of familiarity rather than objective usability. I'm writing this comment in Latin letters rather than Cyrillic or Hebrew because I find Latin letters much more usable than Cyrillic or Hebrew. But that's because I've been surrounded by Latin letters since I was born, and have only occasionally encountered Cyrillic or Hebrew.

I think it's obvious that Cyrillic isn't any less usable than the Latin alphabet in any objective sense. In fact, I'm using English orthography, which has all kinds of unnecessary usability problems which aren't present in any Cyrillic orthography that I know of. But familiarity is a much stronger factor; even today I can barely sound out words in Russian or Ukrainian, while English text printed in Latin letters is clearer to me than speech.

On theoretical grounds, I suspect that the APL syntax Gabi is calling RL-NOP is less usable for left-to-right readers than at least LR-NOP and maybe even conventional Please Brutally Execute My Dear Aunt Sally operator precedence. But familiarity is such a strong force that this hypothesis is very difficult to test.

The theoretical grounds are that, when reading left to right, a reader must maintain a stack of pending operators and values in their mind, unless they are saved by parentheses. (The Iverson quote disagrees with this, but I think Iverson was wrong.) Maintaining mental stacks is difficult and error-prone; this is the reason for the Tim Peters proverb, "Flat is better than nested."

I suspect that operator precedence might be superior for two reasons:

1. It more often avoids parentheses, which are extra symbols to recognize and correctly pair up in your mind.

2. The meaning of high-precedence subexpressions like `x×b` are almost context-independent—although an exponentiation operator or something like a C struct field selector could still follow `b` and change its meaning, following multiplications, divisions, additions, subtractions, or comparisons will not, and preceding additions, subtractions, or comparisons also will not. I conjecture that this facilitates subconscious pattern recognition.

But the familiarity factor enormously outweighs these theoretical considerations for me.


> " I suspect that the APL syntax ... is less usable for left-to-right readers"

On the contrary, I find it much more usable for left-to-right readers, because it allows a "top-down" reading of the expressions, instead of a "bottom-up" reading.

When trying to understand an unfamiliar program, for debugging or maintenance, you normally do not want to waste time by reading completely all expressions, which provide irrelevant computation details.

You typically search where some variables are modified and how and why. For this it is frequently enough to look only at the last operations that have been performed before storing a modified value into a variable.

With the Iverson notation, the last operations are always conveniently grouped at the left side of a text line. Thus you read from left to right only as much as necessary to find what you need, then you can skip the rest of the line.

With the school notation, the required information is not grouped at one end of the line, so reading becomes slower.

The opposite of the Iverson notation, which was used in some stack-oriented languages, also groups the information, but in a way that is less usable for left-to-right users.

From natural languages, left-to-right readers expect that a sentence starts with its topic (at the left side), i.e. the most important part, e.g. the last assignment, like in the Iverson notation, instead of ending with its topic, like in the opposite notation.

> "a reader must maintain a stack of pending operators and values in their mind"

I believe that few readers, if any, do this.

The normal case when reading is that you do not want to reproduce in your mind what the computer does, but only to find the information flows between program variables. For this, it is enough to read partial expressions, as explained above.

In the very rare case when you wanted to make a mental calculation identical to that of the computer, you would normally read the expression from right to left.

When writing, the Iverson notation is usually more convenient than the school notation, while writing normally, from left to right. The reason is that for most computations the natural way to find the expression that must be computed is to go backwards, from the desired result towards the available data.


Hmm, could be. I'll have to think about that.


The popularity of a convention has no relationship with its usability.

Everybody learns in school the traditional convention for writing mathematical expressions.

It appears that for most people it is difficult or impossible to unlearn later such a convention, even if they encounter a superior convention.

On the other hand, I am among those fewer for which this is not true, so when I have first read the book "A Programming Language" of K. Iverson, on which the later APL language and its successors have been based, I have immediately recognized that the Iverson convention is much better than the school convention, and I have no trouble in using it.

When reading a program written with the Iverson convention, you still read from left to right, but you typically do not read until the end of the line, but only as much of the left part as necessary to understand the purpose of the line. (Because the right operand of any operator is everything that follows it until the end of the line, and the details of that computation may be irrelevant. With school notation, when searching where a variable has been modified and how, you must jump between the beginning of the line and the end of the line, to find the last operations that have generated the stored value, when reading and understanding the complete expression would be a waste of time.)

The original motivation of the Iverson convention, which remains very important, was to give a useful meaning for a sequence of identical non-commutative operators, e.g. subtraction and division. This is particularly desirable when the operators are used in vector reductions.

(With school notation, a0 - a1 - a2 - ... - an is seldom a useful expression, but with the Iverson convention it becomes alternate sum, which is needed very frequently. Similarly for division.)


I think there is a reason for this, but maybe not a good one.

1. Function application should be left to right, e.g. `sqrt 4`

2. Precedence order should be very simple. In k, everything has the same precedence order (with the exceptions of brackets)

1 + 2 forces you to have this right to left convention, annoyingly.

Fwiw, I think 2 is great and I would rather give up 1 than 2. However, writing function application as `my_fun arg` is a very strong convention.


Even if you aren’t used to it, you’d be able to reason yourself through it, knowing how the language works, and would be aware that you need to reason through it. And it isn’t that LLMs don’t know that the language works that way, if you ask them about it. It also isn’t that they aren’t able to reason through it, if you ask them to do so. It’s that they lack awareness when to switch modes, lack the ability to have their knowledge interrupt their “intuitive” output and instead start reasoning about how to proceed.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: