Live data from Hacker News

Tacit programming

en.wikipedia.org

11–20 of 95 posts

Re: Tacit programming

#11
Seems like a maintenance nightmare tbh. You have to jump at a billion functions definitions before you can hope to understand what a program is doing.

I could see myself transforming a functional program into a procedual one as I try to understand it just so I can have all information just in front of me and not have to keep things in my head.

Like I get that a functional style helps with the mathematical correctness side of things. But I'm just one of those people who still hold "code is meant for humans" first.

Re: Tacit programming

#12
Wow, seems pretty obvious what this was written for (even if they didn’t know it): building commands/prompts for LLM ensembles. It’s just too perfect —- the LLMs could easily implement their own combinators. Would be a huge step towards self-improving systems…

Re: Tacit programming

#13
Related. Others?

Tacit Programming - https://news.ycombinator.com/item?id=28413195 - Sept 2021 (1 comment)

What’s the Point of Pointfree Programming? - https://news.ycombinator.com/item?id=25509468 - Dec 2020 (1 comment)

When Does Point-Free Notation Make Code More Readable? - https://news.ycombinator.com/item?id=15365214 - Sept 2017 (73 comments)

Programming in the Point-Free Style - https://news.ycombinator.com/item?id=14077863 - April 2017 (101 comments)

Point-Free style: What is it good for? - https://news.ycombinator.com/item?id=1175946 - March 2010 (22 comments)

Re: Tacit programming

#14
post #4

Why not translate your code to pointfree style automatically? Using[0], you can go from quad a b c = let d = b * b - 4 * a * c in ((-b + sqrt d) / 2 * a, (-b - sqrt d) / 2 * a) to ghci> import Control.Monad ghci> quad = ap (ap . ((.) .) . ap (ap . (liftM2 (,) .) . flip (flip . ((*) .) . flip flip 2 . ((/) .) . (. sqrt) . (+) . negate)) (flip (flip . ((*) .) . flip flip 2 . ((/) .) . (. sqrt) . (-) . negate))) (flip (…

Apart from "just because we can" or "it's fun", why on earth would someone prefer the second style?

Re: Tacit programming

#15

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 like reading and writing point-free code, I just really hate debugging it. The debuggers/IDEs are (usually? are there exceptions) not really geared up for it and so the debugging experience is basically one of just having 1 call. This goes for more lambda style calling mechanisms of course. I end up pulling it apart, but that's only because of bad debug/ide support in my case. I can read/write it fine; in most cases it just works and then I like it better than the (verbose) alternatives.

Re: Tacit programming

#16

I've never found this style readable unless with pipes (bash / elixir), where I love it. With any other syntax, I find it just adds mental overhead. Maybe because you have to read it backwards?

Pipes in both of the languages you specified do function application, not composition, so they’re very much point-ful (you see the arguments you pass/get passed).

I assume they're talking about code like

    x
    |> f a
    |> g b
    …
… where everything after the first |> is essentially in point-free style.

Re: Tacit programming

#17
post #4

Why not translate your code to pointfree style automatically? Using[0], you can go from quad a b c = let d = b * b - 4 * a * c in ((-b + sqrt d) / 2 * a, (-b - sqrt d) / 2 * a) to ghci> import Control.Monad ghci> quad = ap (ap . ((.) .) . ap (ap . (liftM2 (,) .) . flip (flip . ((*) .) . flip flip 2 . ((/) .) . (. sqrt) . (+) . negate)) (flip (flip . ((*) .) . flip flip 2 . ((/) .) . (. sqrt) . (-) . negate))) (flip (…

Apart from "just because we can" or "it's fun", why on earth would someone prefer the second style?

It's a joke.

Re: Tacit programming

#18

I've never found this style readable unless with pipes (bash / elixir), where I love it. With any other syntax, I find it just adds mental overhead. Maybe because you have to read it backwards?

Clojure (and I'm sure other lisps and programming languages) have a nice solution to this, the `->` macro ("threading")

You'd do something like:

  (save (transform (fetch))) ;; calls fetch, then transform, then save

  (-> (fetch)
      (transform)
      (save))
Not that the non-threading version was hard to read, but once the function names start to be a bit longer and involve arguments, the threading version tends to be a lot easier to read.

Re: Tacit programming

#19

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 like reading and writing point-free code, I just really hate debugging it. The debuggers/IDEs are (usually? are there exceptions) not really geared up for it and so the debugging experience is basically one of just having 1 call. This goes for more lambda style calling mechanisms of course. I end up pulling it apart, but that's only because of bad debug/ide support in my case. I can read/write it fine; in most case…

Recent versions of F# can stop on individual function applications in an expression like

    x
    |> f a
    |> g b
    …
(search for "pipeline debugging" on https://devblogs.microsoft.com/dotnet/whats-new-in-fsharp-6/>).

In my experience, these are more common than strict point-free style anyway.

Re: Tacit programming

#20
The broader idea of “pass a value between functions without naming it in the caller” crops up in a few other places outside FP.

In Rust there is the “builder pattern”[0] where the builder isn’t mentioned directly:

    ByValueBuilder::new()
        .with_favorite_number(42)
        .with_favorite_programming_language("Rust")
        .build()
In OO land they are called “fluent interfaces”[1], commonly used when building SQL queries while only mentioning the final query at the end:

    query = translations
 .Where(t => t.Key.Contains("a"))
 .OrderBy(t => t.Value.Length)
 .Select(t => t.Value.ToUpper());
Especially in the query builder example, since it is essentially building up an AST, the type of the top-level object can change in each call, but since it isn’t named it also doesn’t need to be typed, so there’s no issue with variable shadowing etc.

[0] https://blog.logrocket.com/build-rust-api-builder-pattern/ [1] https://en.m.wikipedia.org/wiki/Fluent_interface

Post reply on HN