Live data from Hacker News

Tacit programming

en.wikipedia.org

31–40 of 95 posts

Re: Tacit programming

#31

Tinkering with APL (Dyalog) gave me one of my most mind-bending programming moments. dismal ← 10⊥(⌈/10⊥⍣¯1⊢) This is the complete solution to addition in the framework of Dismal Arithmetic [1]. The pivotal idea there was the inverse of a function, and "trains". Until that moment of insight, I was fiddling about with dfns, which looks janky in comparison. dismal ← {10(⊤⍣¯1)⍵}∘{⌈/⍵}∘{10(⊥⍣¯1)⍵}⊢ ⍣¯1 is APL for "inverse…

And if anyone wants an absolute masterclass in tacit programming, have a look at Aaron's Co-dfns compiler. The README has extensive reference material. https://github.com/Co-dfns/Co-dfns/

Re: Tacit programming

#32
post #9

Absolutely every single time when I use functional programming, I store my intermediary calls in a variable, specifically because naming that variable forces me to explain what that intermediary result should be. If the intermediary result makes no sense, and only the function composition makes sense, I'll create a new well named function that does the chaining, even if it's single use. This is literally the only way…

Yeah, point-free sounds cool, until you actually try it out. Even in their example they are not point-free: compose(foo, bar, baz) Here compose is applied to three "points" (which happen to be functions).

That example is as point free as it gets. Just because the syntax doesn’t look like Haskell doesn’t really change that.

Re: Tacit programming

#33

I love the concept of point-free programming - write your function by simply concatenating the transformations you want. I just hate reading the resulting code written by others. What information is expected to come in, and exactly what data passes from one step to the next, and in what position? Data type signatures only go so far. Point-free means you have all that wiring in your head, without assistance from the n…

I think this style requires familiarity with the codebase that its using before it actually becomes readable, but once you have that familiarity reading and understanding what's happening is a lot faster. Like Rxjs for example, if you're unfamiliar with the library its like hieroglyphs, but once you develop familiarity with it you can read other people's code much faster than if everything was implemented procedurally. That said if people are paying me money I usually avoid doing point-free, except for Rxjs. I love Rxjs so much.

Re: Tacit programming

#34
post #9

Absolutely every single time when I use functional programming, I store my intermediary calls in a variable, specifically because naming that variable forces me to explain what that intermediary result should be. If the intermediary result makes no sense, and only the function composition makes sense, I'll create a new well named function that does the chaining, even if it's single use. This is literally the only way…

Yeah, point-free sounds cool, until you actually try it out. Even in their example they are not point-free: compose(foo, bar, baz) Here compose is applied to three "points" (which happen to be functions).

[deleted]

Re: Tacit programming

#35

I love the concept of point-free programming - write your function by simply concatenating the transformations you want. I just hate reading the resulting code written by others. What information is expected to come in, and exactly what data passes from one step to the next, and in what position? Data type signatures only go so far. Point-free means you have all that wiring in your head, without assistance from the n…

I'm smiling a bit because I know exactly what you mean and generally agree, with an exception. A common idiom in Elixir is to return {:ok, result} or {:err, :reason} from calls that can fail. Leaning on that idiom, good function names, and good errors goes a long way:

    params[:id]
    |> find_user
    |> verify_user_has_access_to(params[:post_id])
    |> etc
When I define the functions I'll use pattern matching on the first argument to each function so that you can either pass in a "user" or {:ok, user} or {:err, _}. If it matches the error pattern it'll just return the error unmodified. The errors have enough fidelity to make it clear where the pipeline failed. I'm not sure this is a super common pattern though but it worked pretty well for me.

Re: Tacit programming

#36

The wiki page leaves out the source of the the 'point-free' nomenclature - category theory ( e.g. https://en.wikipedia.org/wiki/Pointless_topology ). The original game was talking about sets (or other similar objects) without talking about 'set membership'/'elements', whence 'point-free'; you want to only talk about functions between sets (or morphisms between objects), and build everything up from those. Is 'tacit'…

The name "tacit" comes from the APL family as far as I know. It certainly fits with Iverson's style, as he was fond of seeking out just the right word to describe something regardless of obscurity ("ravel", "copula", etc.). I think the name would have come about after the development of function trains in 1988, and I found a paper "Tacit definition" about Iverson's J from 1991: https://dl.acm.org/doi/10.1145/114054.114077 (digitized at https://www.jsoftware.com/papers/TacitDefn.htm). Not knowing when "point-free" started to be applied to programming, I can't say which is first. I doubt J's developers were aware of "point-free" in any case.

Re: Tacit programming

#37

Tinkering with APL (Dyalog) gave me one of my most mind-bending programming moments. dismal ← 10⊥(⌈/10⊥⍣¯1⊢) This is the complete solution to addition in the framework of Dismal Arithmetic [1]. The pivotal idea there was the inverse of a function, and "trains". Until that moment of insight, I was fiddling about with dfns, which looks janky in comparison. dismal ← {10(⊤⍣¯1)⍵}∘{⌈/⍵}∘{10(⊥⍣¯1)⍵}⊢ ⍣¯1 is APL for "inverse…

> dismal ← 10⊥(⌈/10⊥⍣¯1⊢)

And what does that look like in C?

Re: Tacit programming

#38
post #9

Absolutely every single time when I use functional programming, I store my intermediary calls in a variable, specifically because naming that variable forces me to explain what that intermediary result should be. If the intermediary result makes no sense, and only the function composition makes sense, I'll create a new well named function that does the chaining, even if it's single use. This is literally the only way…

Yeah, point-free sounds cool, until you actually try it out. Even in their example they are not point-free: compose(foo, bar, baz) Here compose is applied to three "points" (which happen to be functions).

IMO It is point free even if the syntax is not as nice as Haskell. Same as foo . bar . baz

Re: Tacit programming

#39
post #6

My favorite resource on Tacit programming is Point Free or Die: https://www.youtube.com/watch?v=seVSlKazsNk

I didn't agree on it. It's like stating the principle of procreation and someone quoting a pornstar, and now we name it James Deen. Hope this helps, mrn.

Re: Tacit programming

#40

The wiki page leaves out the source of the the 'point-free' nomenclature - category theory ( e.g. https://en.wikipedia.org/wiki/Pointless_topology ). The original game was talking about sets (or other similar objects) without talking about 'set membership'/'elements', whence 'point-free'; you want to only talk about functions between sets (or morphisms between objects), and build everything up from those. Is 'tacit'…

The name "tacit" comes from the APL family as far as I know. It certainly fits with Iverson's style, as he was fond of seeking out just the right word to describe something regardless of obscurity ("ravel", "copula", etc.). I think the name would have come about after the development of function trains in 1988, and I found a paper "Tacit definition" about Iverson's J from 1991: https://dl.acm.org/doi/10.1145/114054.1…

Great, good to know where it comes from - thanks. :)

I'd guess given that I associate point-free with Haskell, which came much later, that the APL nomenclature (of which I was ignorant) came first.

Post reply on HN