
Programming in the Point-Free Style - douche
https://eiriktsarpalis.wordpress.com/2017/04/02/programming-in-the-point-free-style/
======
astrobe_
Point-free is generally the main style for concatenative languages.

In order to be able to read it, you have to know by heart the signature of the
standard operators, and then you have to learn on the go the signature of the
operators of the particular program your are studying.

It doesn't fly well if the author doesn't follow certain "usability" rules:

\- name things thoughtfully and properly,

\- no more than 3 arguments for your functions,

\- keep the complexity of the functions as low as possible.

This is good advice in any language, but I'd say that with concatenative
languages at least, deviations are likely to have more acute negative
consequences on maintainability.

~~~
kazinator
_In order to be able to read it, you have to know by heart the signature of
the standard operators_

Unfortunately, while that tells you how many operands there are, it doesn't
help you find them in the surrounding syntax.

In Forth, for instance, the operands of a + could be a pair of immediately
preceding constants like _1 2 +_. These could be far away in a contrived way:
_1 2 [... snip stuff that produces side effects and keeps stack balanced ...]
+_. Or just due to expression complexity: _[30 word expr] [27 word expr] +_ :
the left operand of + is the result of the 30 word expr, which is 27 words
away from the + symbol. Or is that 26? 29?

~~~
astrobe_
> These could be far away in a contrived way: 1 2 [... snip stuff that
> produces side effects and keeps stack balanced ...] +

This is obviously poorly written. "1 2 + [stuff]" is the sane way to write it.
Or "2 [stuff] 1 +" if [stuff] takes one parameter and outputs one result.

> Or just due to expression complexity: [30 word expr] [27 word expr] +

Post that on comp.lang.forth, and people will certainly tell you "don't do
that" or "why do you that" if it's less trivial than a factoring issue.

In similar situations some people have this trick of separating sub-
expressions with double spaces. But that's ignoring the writing on the wall.

What I learned from Forth is that it's true that it has its shortcomings, but
I have my own shortcomings too. As Forth is a DIY language, you have to make
this distinction in order to improve language/programmer pair.

~~~
kazinator
_This is obviously poorly written._

It's only obvious in the example form which I have. If such a thing occurs in
real code, the stuff won't look like _[stuff]_ ; it will not stand out.

"Poorly written" happens.

------
davnn
I have yet to see the benefits of point-free programming. Don't get me wrong
it's fun, but in my opinion it makes reasoning about programs much harder. I
am a huge fan of functional programming nevertheless.

The opinion that a point-free style is "beautiful code" seems pretty esotheric
to me.

~~~
JoshTriplett
How do you feel about shell pipelines? Most shell pipelines don't name the
things they operate on. Point-free style feels the same way: you string
functions together and don't name the input/output.

~~~
coldtea
> _Most shell pipelines don 't name the things they operate on._

That's because they don't operate on much more than strings.

~~~
jdmichal
PowerShell still heavily uses pipes, and those are full-blown .NET objects
being passed around.

------
dep_b
Interesting article. So far I've been working on one (real and deployed)
project that employs F# and I generally liked the experience. Much of my code
still is F#ified C# and lacks a cohesive way of structuring things, but every
time a new piece of the puzzle snaps in place and I get better, shorter and
more beautiful code to replace the old "works but ugly" stuff. The hardest
thing is where reality (.Net frameworks, API's, user input and databases)
meets theory (nice formatted mathematical situations that make F# shine).

------
JadeNB
Lots of the comments seem to be missing the point that, despite the title, the
author is _not advocating the point-free style_ :

> The point of this exercise is to illustrate how the lambda calculus with
> pattern matching (or set theory for that matter) is superior to the point-
> free style in terms of expressive efficiency.

~~~
Avshalom
Sure but it's a deeply uninteresting exercise because no one programs in
category theory.

~~~
AnimalMuppet
No one programs in category theory, therefore... what?

ELI5: What's the connection between your comment and JadeNB's?

~~~
Avshalom
People aren't missing the point, they just aren't engaging with it because TFA
makes it's point by claiming category theory is expressively inefficient...
but nobody programs in category theory, the link between point free
programming in F# and category theory is meaningless. Tacit programming in F#
is a reflection on tacit programming in F# nothing else.

So the commentariate has decided to talk about point free programming in
general instead of engaging the article's very narrow and unsubstantiated
point.

------
kazinator
Point free expression in production ANSI C90 code:

Function defined here, stored in _xform_listed_quote_f_ global:

[http://www.kylheku.com/cgit/txr/tree/eval.c?id=6ca6be767f8ac...](http://www.kylheku.com/cgit/txr/tree/eval.c?id=6ca6be767f8ac84a8c601c08d6e06822ced556f9#n3043)

Used as a mapping function here:

[http://www.kylheku.com/cgit/txr/tree/eval.c?id=6ca6be767f8ac...](http://www.kylheku.com/cgit/txr/tree/eval.c?id=6ca6be767f8ac84a8c601c08d6e06822ced556f9#n3108)

------
pcmonk
Point-free programming is sometimes also called "tacit" programming. I found
this practical description of tacit programming in Racket to be useful:
[http://r-wos.org/blog/tacit-racket](http://r-wos.org/blog/tacit-racket)

------
sp332
Points-free is helpful if you're mentally focusing on the "verb" or function,
and not the "noun" or data. (sqrt x) yields a noun. (sqrt) yields a verb.

------
scandox
> A category consists of abstract functions (or morphisms, or “arrows”) that
> have an origin and destination (or domain and codomain, or “argument type”
> and “return type”).

I think perhaps Maths people need to seek more consensus on terminology.

~~~
mikebenfield
I've only seen mathematicians use the terms morphisms, arrows, and
domain/codomain. It is true that morphisms and arrows mean the same thing, but
I _think_ that's because the term morphism is specific to category theory and
the term arrow is from graph theory.

All the other terms here (abstract functions, origin, destination, argument
type, return type) appear to be the author's attempt to make the subject
understandable to programmers.

~~~
fabianhjr
Morphism is from Algebra/General Mathematics and it is a function that
preserves a "structure". (Group Morphism, Isomorphism between sets, etc)

In Graph Theory the terminology is Node and Vertex.

Arrow, Source and Target are from Category Theory.

------
dcre
A great talk from Strange Loop 2016 on this topic:

"Point-Free or Die: Tacit Programming in Haskell and Beyond" by Amar Shah
[https://www.youtube.com/watch?v=seVSlKazsNk](https://www.youtube.com/watch?v=seVSlKazsNk)

------
rnhmjoj
For haskell there is a fantastic tool that converts code into a pointfree
function definition.

[https://hackage.haskell.org/package/pointfree](https://hackage.haskell.org/package/pointfree)

~~~
JadeNB
> For haskell there is a fantastic tool that converts code into a pointfree
> function definition.

But why? If a point-free style is more readable, then by all means use it, but
if you need an automated tool to do the translation for you, then that seems
unlikely. If it's an efficiency question, then your compiler can, and (given
the trickiness of GHC in particular) probably will, do anything that an
external automated tool can.

~~~
rnhmjoj
For fun mostly but it can be useful too: it can find neat solutions I couldn't
think of and I may decide to use it. Of course it gives also crazy stuff like
`(((.) . (,)) .)` that I will never put in a program because I don't
understand or it's just worse than the original input.

~~~
JadeNB
> For fun mostly but it can be useful too: it can find neat solutions I
> couldn't think of and I may decide to use it. Of course it gives also crazy
> stuff like `(((.) . (,)) .)` that I will never put in a program because I
> don't understand or it's just worse than the original input.

If it is purely an intellectual exercise, to see how else the code _could_
theoretically be written, then I totally see the point. (I am a mathematician,
after all!)

On the other hand, if it is code that you actually use in production, then
surely the old dictum that I will misquote, for want of looking it up, as "if
you write the cleverest code possible, then you are not clever enough to debug
it", applies all the more so to say "if you aren't clever enough to write your
own code, then you certainly aren't clever enough to debug it"! (Not you
_personally_ , I mean; just a comment on programmer-facing auto-generated
code.)

~~~
posterboy
I think the lesson here is, if the conversion looks horrendous, then the
original was questionable in the first place.

------
mxfh
_Two points particularly add to the complexity of the point-free definition_

------
mpweiher
Having done a _lot_ of programming in Postscript, I understand the allure of
point-free style.

Some code can seem extremely elegant, but mostly it's just _clever_ , and an
exercise in showing off how smart you are and how much you can keep in your
head.

And with all due respect to Joe Condon: Eschew clever code.

~~~
finnh
Interesting. I find composing operators on streams to require holding _less_
in my head than the equivalent non-point-free (ie, iterative / loop-based)
code.

When reading (eg) nested for loops with conditions, I have to push a ton of
context variables into my head, and then evolve them over iterations if I'm
doing a close read. That's a lot of ask of my head.

But in the point-free style, each compositional unit tends to be small enough
to be "obviously no bugs" vs. "no obvious bugs".

~~~
comex
All things in moderation. Chaining list transforms (like map and filter) in
one expression does have fewer points than giving every intermediate result a
name or even using a for loop, but it doesn't require the level of tenseness
usually associated with the term "point-free".

------
mh-cx
After a few seconds I was redirected to an ad site that made my mobile vibrate
and that “locked me in“ by some redirect trickery which blocked the back
button.

Not really what I'd expect from a HN link with so many upvotes. Did no one
else experience this?

------
tempodox
I think the article makes good points. We have already seen callback hell. I
wonder how long it will take before we coin the term “monad hell”.

------
sddfd
Great article. 100% agree. Especially the category theory example.

------
z3t4
try not to make global functions. or at least put them in name spaces. if the
function is reusable cross code bases then make it into a module or library.

------
drudru11
Was the language Forth point-free?

~~~
RodgerTheGreat
It can be. Pure functions which exclusively operate upon the stacks are often
considered idiomatic. If you choose, however, you can reference and alter
named global variables within a function, and some dialects offer a facility
for named local variables. You might argue that the 'i' and 'j' words, which
interact with loop constructs to give you a copy of the current and outer loop
induction variable, count as references to named variables, even if they
aren't strictly the same thing.

As with most languages it comes down to the programmer.

