5 ms·
The approach of avoiding having to explicitly name variables is known in computer science as "point free" or "tacit" programming, and in math as "combinatory lo
by jph00 4y ago
The approach of avoiding having to explicitly name variables is known in computer science as "point free" or "tacit" programming, and in math as "combinatory logic". Languages like APL have even less boilerplate/ceremony for this than shown in the post. E.g the examples shown:
[ even? ]
[ even? not ]
[ 4 > ]
in APL are:
2∘|
1-2∘|
>∘4
`∘` is partial/bind, and `|` is modulo.
Many other languages are pretty good for point-free programming. For instance this series goes into the benefits of using this approach in Swift:
https://www.pointfree.co/ https://www.pointfree.co/
Point-free programming has always been a controversial subject. Some people passionately hate it (particularly people that haven't invested in learning to use it) and some passionately love it.
- Akronymus 4y agoAPL is such an interesting language. VERY concise, makes sense but is still incomprehensible to me, without being an actual esolang.
- skruger 4y agoI’ve written a gentle intro to APL for experienced programmers if you’re interested in making it a bit less incomprehensible: https://xpqz.github.io/learnapl https://xpqz.github.io/learnapl
- Akronymus 4y ago> …but it’s unreadable! Should I feel called out? (Yeah, I get that its down to familiarity, rather than actually being hard to read) Interesting read though.
- TuringTest 4y agoFor people without a functional language background, it makes sense to think of point-free style with an example they understand: Unix pipes. The controlled producer-consumer flow in pipes is a subset of the declarative combinatorics of values in a point-free function composition. Approaching it as an ongoing process that generates values and consumes them at the same pace can make it easier to understand.
- Tainnor 4y ago> Point-free programming has always been a controversial subject. Some people passionately hate it (particularly people that haven't invested in learning to use it) and some passionately love it. And for other people, such as myself, it depends on the particular case. I think that point-free style can be clearer and more concise in certain cases (particularly when you're chaining a sequence of operations), but you can also really overdo it. I think when you start to use (in Haskell) "flip", "uncurry", etc., the question is whether it wouldn't be more readable to just name the arguments instead. But obviously, people are going to have varying levels of tolerance for such things.
- chriswarbo 4y agoPoint-free style can be useful as an intermediate step when refactoring, since making code point-free (a) is largely mechanical (although judgement can still useful to avoid horrible results!), and (b) removes many of the abstractions and variable names in the code. The latter are often historical baggage, telling us what the code used to do, or was meant to do; whilst a point-free version shows us more directly what it actually does. If the point-free version makes sense as-is, we can leave it; but that's rarely the case. Usually, we'll introduce a few abstractions and variables; but this time they'll be more appropriate for the current codebase.
- heavenlyblue 4y agoYou can also look at the generated assembly to figure out exactly what the code does
- chriswarbo 4y agoAssembly obfuscates the implementation with memory allocation, garbage collection, etc. which is often worse than even 'the wrong' (i.e. legacy) abstractions in a high level language.
- Xophmeister 4y agoIn my (admittedly newbie) experience, it's particularly useful when application of your function is going to be in a context where η-reduction is natural. For example, your fmap is going to look cleaner without a wrapping lambda inside it.
- thesz 4y agoAdd spaces around APL operators and name them. You examples become: 2 partial mod 1 minus 2 partial mod > partial 4 I guess your examples still need some framing to make them somehow passable around, for example, a definition or some kind of closure. Let's say they require no more than square brackets around them. Now your examples will look like this: [ 2 partial mod ] [ 1 minus 2 partial mod ] [ > partial 4 ] And, magically, they are not more terse than what was expressed in Joy. Not at all. Quite the opposite. One character operator is still an operator. If it does not require spaces around it most of the time, for sake of comparison between languages it should have them.
- HelloNurse 4y agoWhat would be useful is the definition of abstractions, breaking long chains of combinators and functions into manageable pieces, instead of playing one-liner code golf. Meaningful function names rather than superfluous parameter names. For example (adapted from Wikipedia and untested): arrayaverage =: +/ % # arrayaverage 1 2 3 i.e. defining the average as the ratio (%) between the sum (+/) and the cardinality (#) of an array, with the advantage of being able to replace this function with a better version that doesn't fail miserably for an empty array.
- marcosdumay 4y ago> One character operator is still an operator. Yet if you look at the original code and you version, the difference is perfectly clear. Programmers are not computers, so syntax is important.
- thesz 4y agoWhat I did was not even at syntax level. These are lexems that were changed, a level below syntax. When you use C, you can write "~ x" and you can also write "??- x" [1], a slightly more verbose version of the same thing. [1] https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C I did exactly the same - I changed lexical structure of language, mainitaining the syntax, most of it. Programmers, just like most other people, read words as a whole entities, quite like hierogliphics [2]. If we talk about "people are not computers" we should recognize that and allow for longer (yet atomic) lexical structure of the same language. [2] https://www.mrc-cbu.cam.ac.uk/people/matt.davis/cmabridge/ https://www.mrc-cbu.cam.ac.uk/people/matt.davis/cmabridge/
- mlochbaum 4y agoFor comparison, [0] is my page on tacit programming in BQN, which is laid out a lot like the OP. It even begins with a filtering example, taking positive entries of a list l with 0⊸<⊸/ l. For odd entries it would be 2⊸|⊸/ and for evens (¬2⊸|)⊸/. APL does have a negation function ~ (not sure why jph hasn't used it), but it has trouble with filtering because / is overloaded to be both a function and an operator[1]. BQN fixes some problems like these in APL, and I'd consider it to be an improvement on both J and APL for tacit programming. [0] https://mlochbaum.github.io/BQN/doc/tacit.html https://mlochbaum.github.io/BQN/doc/tacit.html [1] https://aplwiki.com/wiki/Function-operator_overloading https://aplwiki.com/wiki/Function-operator_overloading