News for hackers. Stuff that matters.
Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Wednesday June 24, 2020 @09:11PM (#23635768)
Unix piping is basically functional programming.

If you ever wondered why some people are obsessed with functional programming this is the reason why:

Functional programming forces every primitive in your program to be a Lego Block.

A lot of functional programmers don't see the big picture. They see a sort of elegance with the functional style, they like the immutability but they can't explain the practical significance to the uninitiated.

Functional Programming is the answer to the question that has plagued me as a programmer for years. How do I organize my program in such a way that it becomes endlessly re-useable from a practical standpoint?

Functional programming transforms organ transplantation into lego building blocks.

The "lego" is the "function" and "connecting two lego blocks" is "function composition".

In short, another name for "Point free style" programming is "Lego building block style" programming.

Re:Software reuse is more like an organ transplant than snap... by xvedejas on Wednesday June 24, 2020 @09:21PM (#23635830)
You can't just compose two functions because they're both written in a functional programming language. The programmer has to have the foresight to make their types compatible. I think the novelty of the Unix pipe for interoperability is that they (typically) work on one agreed-upon kind of data: human readable, white-space separated. So a lot of tools "just work" with each other.

There's no reason you can't do this with functional programming, but obviously you can do it with non-functional programming too, and you could certainly fail to do this with functional programming.

Re:Software reuse is more like an organ transplant than snap... by vicda on Thursday June 25, 2020 @02:08AM (#23637387)
Yes, but you write a short function/lambda for connecting them. Just like how you have sed/awk, or the many required flags to make any non-trivial operation "just work".

You're not free from the need to specify how to parse the strings just because your whole human readable system is stringly typed.

Re:Software reuse is more like an organ transplant than snap... by hencq on Wednesday June 24, 2020 @09:59PM (#23636079)
Nicely put. That aligns very nicely with the philosophy behind Clojure and for instance less so with Haskell. In Clojure you usually use only a few data types, often (immutable) hashmaps. A program then simply becomes a series of functions that transform data.
Re:Software reuse is more like an organ transplant than snap... by UK-Al05 on Thursday June 25, 2020 @09:56AM (#23640788)
Don't people clojure try to wrap primative types. Say an Address type? Or is that not a thing?
Re:Software reuse is more like an organ transplant than snap... by platz on Wednesday June 24, 2020 @10:06PM (#23636113)
Anytime someone mentions a nice thing about Haskell, you can be sure a Clojure programmer will appear shortly, without being previously referenced, to try and disparage them.
Re:Software reuse is more like an organ transplant than snap... by adamkl on Wednesday June 24, 2020 @10:17PM (#23636195)
Not sure where the hostility is coming from. I didn’t read anything disparaging about Haskell in hencq’s comment. He/she just made a factual statement about Clojure’s approach to data types being analogous to Unix/strings when it comes to composition.

It comes with the same drawbacks (the lack of static typing is similar to strings with Unix; you have to be aware of the details of the data coming in and out because there is no type system to save you - unlike Haskell), but the benefit is easier composition.

Re:Software reuse is more like an organ transplant than snap... by hencq on Wednesday June 24, 2020 @11:33PM (#23636626)
Yeah, I didn't mean anything disparaging about Haskell at all. I only mentioned Haskell as an example of a functional programming language. I tried to make a point (apparently poorly) about the easy composition that using a limited number of (dynamic) types enables. Of course all the usual dynamic vs static tradeoffs apply. Thanks for doing a better job explaining that :-)
Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Thursday June 25, 2020 @03:53PM (#23644822)
I don't think dynamic typing or static typing really applies.

In either case you have to compose functions With the correct types otherwise you hit an error. The difference with dynamic types and static types is when this error occurs. Run time for dynamic types and compilation time for static types. Either way some type of error will always occur regardless.

Though I agree with you if you have a limited number of types things become easier to deal with.

Re:Software reuse is more like an organ transplant than snap... by mcv on Thursday June 25, 2020 @06:26AM (#23638984)
This is something that also works well in the nicer parts of javascript. Now nobody is ever going to accuse javascript of being a good functional language (disparage away), but at its core, you've pretty have arrays, maps, numbers, strings, booleans and functions. An Object is really just a map of key-value pairs where some values are functions. You can .map() an array of objects to an array of strings by feeding it a function that turns an object into a string. It's really nice to build those little blocks and cobble them together into something that accomplishes something more complex.
Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Thursday June 25, 2020 @03:56PM (#23644866)
I use to be pretty negative about JS, but typescript saves the day. The lego aspect of functional programming always becomes more evident when you have static types.
Re:Software reuse is more like an organ transplant than snap... by mcv on Friday June 26, 2020 @04:33AM (#23649922)
I've been getting more mixed about Typescript lately. Quite often, you end up with everything being `any`, and every time you write something, the compiler makes you hunt down the missing types.

But being able to specify interfaces for lambdas is absolutely fantastic. Something like: "this function takes an object and returns a function that can take either a string or a number and returns a number" is easy to do in Typescript, and useful for figuring out where the lego block fits.

Re:Software reuse is more like an organ transplant than snap... by slifin on Thursday June 25, 2020 @03:41AM (#23637906)
Clojure's static analysis tools can warn you of incompatible types

I.e. this will warn (inc "hello") in clj-kondo

Re:Software reuse is more like an organ transplant than snap... by mrslave on Thursday June 25, 2020 @03:52AM (#23637974)
It was kinda funny, and not nasty at all. Let's assume good faith here?
Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Wednesday June 24, 2020 @10:16PM (#23636190)
I mean what he describes is literally the same thing as haskell. Just untyped.
Re:Software reuse is more like an organ transplant than snap... by monetus on Wednesday June 24, 2020 @09:47PM (#23636003)
The message passing protocol in pure data is white space delimited with semicolons ending commands. FUDI is underappreciated, and enabled 'dynamic' programming of PD despite the available code having been built almost entirely with a mind towards instantiating all memory use ahead of time.

Good interfaces enable unexpected things.

https://en.m.wikipedia.org/wiki/FUDI

Re:Software reuse is more like an organ transplant than snap... by willtim on Thursday June 25, 2020 @02:44AM (#23637590)
If languages adopted structural typing, rather than nominal as the default, then it would be much easier to align the types (e.g. projection/renaming of columns). Most FP languages have a limited form of structural typing with tuples.
Re:Software reuse is more like an organ transplant than snap... by orbifold on Thursday June 25, 2020 @05:39AM (#23638700)
Objects in OCaml are structurally typed as well.
Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Wednesday June 24, 2020 @09:42PM (#23635971)
>You can't just compose two functions because they're both written in a functional programming language.

Obviously not, the types have to be compatible just like how a lego piece must be compatible.

>The programmer has to have the foresight to make their types compatible.

Just like a lego builder needs to have the foresight to see whether two lego components are compatible. The analogy still fits.

> I think the novelty of the Unix pipe for interoperability is that they (typically) work on one agreed-upon kind of data: human readable, white-space separated. So a lot of tools "just work" with each other.

The agreed upon data is just a type. Unix pipes compose functions that take in strings as input and deliver strings as output.

The spaces is just an oversight, the whole thing would have been more clean if the type was designed to represent multiple pieces of data like a tuple of words rather than a single string with words divided by spaces.

>you could certainly fail to do this with functional programming.

Just like how two lego pieces can't compose if they're not compatible pieces facing the right direction. Sockets and plugs must be compatible. A functional program still fits the analogy of legos perfectly.

Take a look at lego pieces here: https://brickarchitect.com/2019/2019-most-common-lego-parts/

There exists lego parts that can never compose with certain other parts. Just like functions and function composition.

What you're not seeing is how other styles of programming such as OOP or procedural programming fail to fit the analogy and literally become like organ transplantation.

Let's take a look at object composition. How does that work in the context of legos? It's like a lego block with a mutating hole in it and once you can put different things in that hole and that changes the overall lego block.

Also with OOP and procedural programming you get lego blocks that can mutate. Lego blocks can transform themselves and other lego blocks. They form an interconnected network of entities that are constantly mutating.

To fit the analogy of a lego block you need unchanging blocks.

The entire field of Procedural programming and OOP is basically the art of building systems with mutating primitives that constantly change. Imagine constructing buildings using bricks that change shape. Now imagine refactoring code that does this.... Organ transplantation.

Also you really just need to try it. Doing the type of grafting and refactoring that's an intrinsic part of programming literally becomes lego-like once you program using the functional style. To really see the big picture I suggest you exclusively try the point free style using Haskell.

That being said. There are still massive tradeoffs to doing functional programming. But if your goal is to program like you're using lego blocks, functional programming is the path.

Re:Software reuse is more like an organ transplant than snap... by DougWebb on Wednesday June 24, 2020 @09:55PM (#23636051)
Also with OOP and procedural programming you get lego blocks that can mutate. Lego blocks can transform themselves and other lego blocks. They form an interconnected network of entities that are constantly mutating.

That kind of sounds like a structure of living cells. They're more complex than a structure of lego blocks, but they can do a lot more too.

Don't take that as an argument in favor of OOP though. Building with legos is a lot easier to get right than building with cells would be.

Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Wednesday June 24, 2020 @10:15PM (#23636181)
You can create building blocks of unlimited complexity or pure simplicity.

The key lies in your choice of primitives. Do you start off with a set primitives that are extremely complex or a set primitives that are simple but complete in the sense that you can build entities of unlimited complexity by composing simpler primitives?

I would say the latter method is easier. But there's no reason why the former method won't work. Biological evolution has built many examples of working machines with primitives of unimaginable complexity.

Re:Software reuse is more like an organ transplant than snap... by ElFitz on Thursday June 25, 2020 @11:33AM (#23641845)
Yes, it did. But it also had a couple billion years of trial and error to do so.

Basically, it's the infinite monkey theorem.

Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Thursday June 25, 2020 @02:45PM (#23644070)
Yeah, I'm just saying it can work and it can work remarkably well and efficiently. It's just probably too complex for our limited intelligence to handle.
Re:Software reuse is more like an organ transplant than snap... by hellofunk on Thursday June 25, 2020 @02:00AM (#23637351)
I think this is a rather simplified and naïve analysis. Getting functional programs and functional APIs to compose well with each other is just as much a challenge as in other language paradigms. Just because the logic is organized as functions doesn’t magically make things fit together. Your APIs need to speak in a consistent way as well, and the arrangement of your data needs to be the same or easily convertible between your “Lego pieces“. Having spent many years of my career writing functional code all day, it is just as easy to make a mess of things in functional programs as it is an object oriented programs. I do not believe either is inherently better at creating the “Lego“–style.
Re:Software reuse is more like an organ transplant than snap... by willtim on Thursday June 25, 2020 @02:25AM (#23637496)
It has to be pure functional programming to get the full benefits of compositionality. Most mainstream "functional programming" is not necessarily pure and side-effects are not controlled/tracked. Analogous to how "mostly secure" is not secure, "mostly functional" does not get the full benefits.

Pure functional programming is complex, one has to compose effectful functions differently to pure functions. But the pieces do really fit like Lego bricks, especially when the same mathematical abstractions are used consistently. The Haskell community has been extremely effective at creating such consistency, by promoting various abstractions using category theory as a guide. The object-oriented community is not so different in this regard with their promotion of "patterns".

I've been writing Haskell professionally for 8 years. The problems with Haskell are the tooling, language stability, the learning curve and the difficulty of reasoning about performance, especially space usage. But composition and re-use works.

Re:Software reuse is more like an organ transplant than snap... by hellofunk on Thursday June 25, 2020 @05:57AM (#23638817)
I'm sorry but this is a lot of shallow hyperbole. It doesn't matter if your functions are pure if they return a unique data type for your API or library that is not understood easily by the caller. So the solution is to make that data easily convertible or generic.. and guess what? That's no different than doing the same in an OO language. In the end, lego pieces are ultimately about the data itself, not how it is manipulated.

The key ingredient in making software reusable and portable is the talent and experience of the engineer, regardless of language.

Re:Software reuse is more like an organ transplant than snap... by willtim on Thursday June 25, 2020 @09:54AM (#23640764)
> It doesn't matter if your functions are pure if they return a unique data type for your API or library that is not understood easily by the caller.

If it's an abstract data type, it doesn't have to be understood by the caller, it just has to be passed to another "lego brick" which understands the abstract interface. If it's a structured data-type, then there's no reason why it shouldn't be understood by the caller, the type should tell you how to consume it. I do not understand your point.

> So the solution is to make that data easily convertible or generic.. and guess what? That's no different than doing the same in an OO language

I guess you mean structured data types here? But you have missed my point completely about side-effects, it is side-effects (coupling via back-channels) that prevent composition, in general, in an OO language. OO languages also typically have an obsession with nominal types that can impede reuse.

> The key ingredient in making software reusable and portable is the talent and experience of the engineer, regardless of language.

You appear to be suggesting that languages/tools don't matter? Why not aspire towards languages that encourage safe composition and re-usable software? Your argument reduces down to "good motorcyclists don't need helmets".

Re:Software reuse is more like an organ transplant than snap... by hellofunk on Thursday June 25, 2020 @12:45PM (#23642635)
All of your points make great sense in theory, but in practice it rarely works out so smoothly.

> If it's an abstract data type, it doesn't have to be understood by the caller, it just has to be passed to another "lego brick" which understands the abstract interface. If it's a structured data-type, then there's no reason why it shouldn't be understood by the caller, the type should tell you how to consume it.

And this is exactly how any well constructed OO API works as well.

You can have really good and really bad APIs in any language, it really is up to the skill of the developers. I firmly believe that, there’s no language or tool that suddenly makes you create better things.

I have in my jobs interacted with high profile robust APIs in C++ as well as functional languages. They can be a joy to use when designed well, regardless of language.

Re:Software reuse is more like an organ transplant than snap... by c3534l on Thursday June 25, 2020 @03:03AM (#23637677)
The goal of OOP is also to be modular and composable. I think the thing that is a good design choice is modular and composible. It's what the industrial revolution / assembly line was based on. It's what vim keybindings are based on. Heck, it's what programming languages themselves are based on. Here are some simple tools that do easily understandable things together, now put something together with it. Lego bricks are fun and useful and it's not the domain of any one area of CS.
Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Thursday June 25, 2020 @03:10AM (#23637722)
>The goal of OOP is also to be modular and composable.

Well it depends on the type of composition you're talking about. Anything when mashed together hard enough can compose.

Re:Software reuse is more like an organ transplant than snap... by czbond on Wednesday June 24, 2020 @11:45PM (#23636689)
You really just turned functional programming around for me. I learned CompSci object oriented (C++) but have always loved how easy data analysis was in unix output. Cheers for making me want to give it another look!
Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Thursday June 25, 2020 @12:21AM (#23636878)
Cool! Glad I was able to convince you. Just note that a lot of people find the functional style kind of unnecessarily mind bending. Like the functional style primarily uses recursion instead of loops for iteration which is harder to reason about (and less performant). I actually agree with them, but I feel that these people got lost in the details and missed the big picture about the benefits of functional programming from the perspective of modules, design and program organization.

I recommend you try building something complex with the point free style using Haskell. It will be a bit mind bending at first but if you get it then you'll see how FP is basically the same thing as using legos to build data pipelines... exactly the style used with unix pipes.

Re:Software reuse is more like an organ transplant than snap... by mpweiher on Thursday June 25, 2020 @02:34AM (#23637536)
> Unix piping is basically functional programming.

Only in the same sense that all computing is Turing Machines or NAND gates.

This is a very common misunderstanding, but there is a reason that FP, which is transformational, had to adopt dataflow in order to sort-of handle reactive systems.

Functions run to completion and return their result. Filters tend to run concurrently and, importantly, do not return their results, they pass them on to the next filter in the pipeline.

It is possible to compose any two filters. It is not possible to compose any two functions, not even close, the default for functions is to not compose (arity, parameter types, return type,...).

Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Thursday June 25, 2020 @10:30AM (#23641152)
>Filters tend to run concurrently and, importantly, do not return their results, they pass them on to the next filter in the pipeline.

Filters are functions. They are one and the same. For unix it's a function that takes in a string and outputs a string. The unix world reduces everything into a singular type. You will note that unix "filters" cannot compose with functions of "other" types either. If unix included types like arrays or ints in stdout you would have the same typing problems as you have with functions.

In the unix world all your types are strings so things seem simpler, but in reality your little unix programs need to deserialize the strings into proper types in order to do anything meaningful. You could achieve the same thing if you used functions that returned strings all the time then did internal deserialization but that's not really a solution.

I do get your point about arity and parameter types. You're referring to the fact that not all functions can compose UNLESS they have compatible types and an arity of 1 in the parameters and an arity of 1 in the return value (Golang for example can have arity > 1 in the return value).

However this arity issue doesn't really exist. A function with Arity of two is isomorphic to a function of arity 1 that takes in a 2-tuple as input.

  f(a, b) -> c
  f'(Tuple[a, b]) -> c

  g(d) -> Tuple[a, b]
Both f' and f are equivalent in theory. Plus you can compose g with f'.

The only compatibility problems with composition among functions in the end is just types (not arity) but this problem still exists even in the unix world... it's just hidden from you because you don't actually watch the programs perform deserialization and serialization.

Re:Software reuse is more like an organ transplant than snap... by mpweiher on Thursday June 25, 2020 @01:20PM (#23643021)
> Filters are functions

As I explained before: no they are not.

They have some similarities, but they also have the important differences I outlined above.

The single type is also a restriction relative to the functional model, and crucial to (syntactic) composability.

> If unix included types like arrays or ints in stdout ...

But it doesn't...

> you would have the same typing problems as you have with functions.

...so you don't.

> Both f' and f are equivalent in theory.

But they are not actually equal (never mind the same), at least not in typed FP, and most FP is typed.

> it's just hidden from you

Exactly. It is hidden in Unix and not in FP. That's a difference.

> You could achieve the same thing if you used functions that returned strings

Two points:

(1) you write that you "could" achieve the same thing. Meaning that, once again, they actually are not the same. Otherwise the "could" wouldn't make sense (and it does).

(2) returning strings would not be the same at all, because filters do not "return" their results. They return status codes. The result is not returned, it is passed directly to the next filter, continuously.

So: it is good to recognize that 'X is similar to Y', but that doesn't imply that 'X is just Y'.

Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Thursday June 25, 2020 @02:10PM (#23643676)
>Functions run to completion and return their result. Filters tend to run concurrently and, importantly, do not return their results, they pass them on to the next filter in the pipeline.

Let me address this point so it is more clear. Functions by definition do not need to "run" at all. The underlying implementation of a programming language may "run" a function lazily, eagerly or concurrently but that is not what the Definition of a function is describing.

A function is simply a relation between two sets, one set called a codomain, another set called a domain is deterministic. That is all.

So within unix piping the domain is stdin, the codomain is stdout, the function is the unix program. This paradigm fits the definition of a function and as long as that "function" remains deterministic and compose-able it fits within the paradigm of functional programming BY definition. there is no need to discuss "similarities" here, because it fits the definition therefore it is functional programming. Of course we can get pedantic about certain non-functional use cases but in basically you are fully aware of the generality I'm describing. No point in getting pedantic.

Also keep in mind when you "execute" these functions it does not matter HOW these functions are executing whether concurrently, lazily or eagerly. The only important thing is the relation between the domain and codomain. That is all.

>The single type is also a restriction relative to the functional model, and crucial to (syntactic) composability.

Every unix program must internally deserialize this string type and serialize it again for output. The typing must be handled regardless. It seems like you don't need to deal with it but it's dealt with regardless. You also get inevitable deserialization problems of incorrect types. You do not escape typing in the unix world.

>But they are not actually equal (never mind the same), at least not in typed FP, and most FP is typed.

A relation that takes a string from a domain and returns a string that is from a codomain is a function that is part of functional programming. This is EXACTLY what a unix program does when relating stdin to stdout and therefore it IS a function and it is FP By definition.

You can look at it from another direction. A function that returns an Array does not fit the definition of what a unix program should output to stdout therefore a function IS NOT a unix program. BUT a unix program IS a function.

Formally unix programs are just the set of all functions where the domain and codomains are strings.

>>Both f' and f are equivalent in theory. >But they are not actually equal (never mind the same), at least not in typed FP, and most FP is typed.

The mathematical term is "isomorphic" meaning you get the EXACT same properties going one way vs. the other way. It's the syntactic sugar that prevents composition. Using multi-arity functions and single arity functions with tuples only involves two additional parenthesis:

   f(a, b)
   f'((a, b))
It's just syntactic sugar that causes a difference to occur.

Arity and tuple types are well described to be isomorphic in category theory. I'm not making this up.

One way to think about an isomorphism is that if two things are isomorphic then they are just different perspectives of the exact same thing. Any differences are superficial or illusory.

>Exactly. It is hidden in Unix and not in FP. That's a difference.

Exactly what? If you're not dealing with the type conversions someone else has too. Just because it's hidden from you doesn't mean it doesn't need to be dealt with. Someone has to serialize things and deserialize it. Even from the command line level you cannot escape types. Let's say you have a unix program that can only take numerical strings from stdin. Let's say you pipe english letters to it... if you do then you will have still triggered a sort of type error despite everything being typed as strings in unix. It's just not handled explicitly as a system error.

You cannot escape typing even in the unix world because it is in the end just FP.

>So: it is good to recognize that 'X is similar to Y', but that doesn't imply that 'X is just Y'.

Except we're not talking about similarity. Like I said above X is just Y BY definition.

Re:Software reuse is more like an organ transplant than snap... by mpweiher on Thursday June 25, 2020 @05:39PM (#23646049)
You keep claiming things are the same and then describing differences.

Not sure what else I can do to make you understand this.

As such, I am bowing out as I can only repeat what I’ve written.

Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Thursday June 25, 2020 @09:20PM (#23647783)
No I did not do what you wrote.

Here's what I did: I defined what a function is, then I described how a unix program fits the definition of what a function is...

In short a unix program with stdin as domain and stdout as a codomain is a function but a function is not necessarily a unix program.

I think what's actually going on is you didn't read what I wrote very carefully. You sort of just skimmed over it. I can't blame you, it is rather long and detailed...

But if you want to have a meaningful discussion you need to read it and ask questions about things you don't understand.

Re:Software reuse is more like an organ transplant than snap... by mpweiher on Friday June 26, 2020 @01:26AM (#23648958)
As I wrote before:

> > Unix piping is basically functional programming.

> Only in the same sense that all computing is Turing Machines or NAND gates.

Yes, you can map and analogize long enough until you reach a point where you find what you perceive to be equivalences.

However, what you've done at that point is rediscover that all these mechanisms are computational and thus at some level equivalent and transformable into each other, just like yoo can implement all of this with just NAND gates.

You have not shown what you claim. ¯\_(ツ)_/¯

Re:Software reuse is more like an organ transplant than snap... by EGreg on Wednesday June 24, 2020 @09:43PM (#23635978)
Want to build web apps from reusable blocks? Reason at a higher level about chatrooms, roles and permissions, credits? That was the thinking behind our open source project:

https://qbix.com/platform

Reusability on the web. Here is where we are going:

https://qbix.com/QBUX/whitepaper.html#Distributed-Operating-...

Re:Software reuse is more like an organ transplant than snap... by adamsea on Wednesday June 24, 2020 @09:58PM (#23636067)
Is there a sample project somewhere on Github? Would be helpful to see a concrete example of use to get a better idea of it.
Re:Software reuse is more like an organ transplant than snap... by BiteCode_dev on Thursday June 25, 2020 @01:40AM (#23637267)
> Unix piping is basically functional programming

Except you litterally use side effects to communicate. Not really FP, that part.

Re:Software reuse is more like an organ transplant than snap... by schoen on Thursday June 25, 2020 @01:58AM (#23637346)
How so? While programs themselves could have side effects, the pipe -- if its elements are deterministic which is indeed not true of everything -- is just a series of composed transformations of text.

In a pipeline like

seq 100 | number | grep '[a-z]' | sort | tr -d '.' | tr a-z A-Z

every component is a pure function (byte strings -> byte strings) and the pipeline's results are totally deterministic [if you don't change the locale or collation order with environment variables]. No component of the pipeline makes any change to the filesystem¹.

¹ although both stat(2) and inotify(7) mechanisms could allow other processes to detect the interactions with the filesystem that are caused by running the pipeline, among other process-related mechanisms that system as a whole could use to detect how many times the pipeline has been run, so Unix itself is definitely not side-effect-free for almost any operation

Re:Software reuse is more like an organ transplant than snap... by BiteCode_dev on Thursday June 25, 2020 @02:43AM (#23637578)
> [if you don't change the locale or collation order with environment variables]

Or any other state change.

Because it's not stateless.

Hence not FP.

Re:Software reuse is more like an organ transplant than snap... by schoen on Thursday June 25, 2020 @03:35AM (#23637868)
Most of those changes might be seen as akin to going in to your Haskell interpreter and changing definitions in the standard library or something. (Environment variable changes are weird because they are so local and ephemeral, but you still have to do them deliberately.)

Clearly not all command lines you can type in the shell are stateless (reading the disk, network, stdin, clock, or system RNG, among other things, isn't, and none of those things are rare or hard to do) and the shell doesn't specifically encourage you to write stateless code and it doesn't have a formal way to verify whether or not a particular command like is stateless or not. All of these properties are pretty similar to most popular FP language interpreters except for the last two. I guess it is a relevant distinction that your FP interpreter would typically know (as a matter of static inference) whether an expression is stateless, while your shell would typically not know.

Re:Software reuse is more like an organ transplant than snap... by crimsonalucard5 on Thursday June 25, 2020 @03:03AM (#23637680)
Unless you use some stateful program or you're writing to a file typically a unix expression that uses purely reads and pipes is deterministic meaning you run the same expression twice you get the same result.

If you want to get pedantic fine, but the majority of use cases is stateless.

Re:Software reuse is more like an organ transplant than snap... by schoen on Thursday June 25, 2020 @04:48PM (#23645521)
It's kind of an interesting pattern to think of having the pipeline as a whole be purely deterministic, but its initial input be something from the environment (kind of like the Haskell IO monad, right?).

Probably most complex shell pipelines follow this pattern in practice, but the first counterexample I thought of was shuf, or sort -R. Also, many pipelines that include any kind of interpolation or variable substitution also don't follow it.

A different insight about reasoning about pipelines might be that the byte string (or ASCII string) type is too weak to catch most kinds of errors, and it's not uncommon for one pipeline component to not, in fact, be a total function with respect to the actual data type that you're trying to capture (I don't know the right terminology for this). This most famously happens when you do regular expression substitutions but your regular expression doesn't actually match the full grammar that you're looking for. Then the pipeline can be incorrect as a whole for some inputs, but earlier and later stages don't notice. It can also happen anywhere that different tools have a different implicit understanding of the relevant grammar or structure.

That connects up with all sorts of other ideas which are actually about type safety and parsing more than FP. For example, PowerShell has tried to take the pipeline concept in a different direction, to the consternation of us Unix purists. Its use of typed objects in this context makes more explicit what the contract between programs in the pipeline is supposed to be. There is also a LANGSEC connection in terms of the risks of informal or underspecified parsers and grammars.

I know I've personally written lots of Unix pipelines that were correct for all the inputs that I personally threw at them, but definitely not correct for every possible input. I like to use ! in vim frequently to shell out to a command line to perform a text editing task, and vim has an associated undo and redo which means that sometimes I'm trying several variants until I find the one that successfully appears to do the edit that I intended. Sometimes I do this at an almost preconscious level, which is really strange in terms of thinking about the concept of the correctness of a program (in this case, where the program is literally only going to be used once, with the programmer looking over its shoulder).

Re:Software reuse is more like an organ transplant than snap... by c3534l on Thursday June 25, 2020 @03:05AM (#23637691)
Haskell hates side effects, but not functional programming. FP has been fine with side effects for decades - even SML, the precursor the Haskell, has them, although forwned upon.
Re:Software reuse is more like an organ transplant than snap... by heavyset_go on Thursday June 25, 2020 @02:47PM (#23644085)
One can say similar things about interfaces in object-oriented programming.
Re:Software reuse is more like an organ transplant than snap... by AnimalMuppet on Thursday June 25, 2020 @03:28PM (#23644529)
Not really. OOP interfaces are usually much more intricate than FP interfaces. You might say that they are less like a lego interface and more like electronic connectors. There are several different electronic connectors types, and they are designed so that you physically can't plug the wrong things together. OOP is like that - a more complicated interface that makes it impossible to connect anything-to-anything the way legos can.

On the other hand, if you're trying to build something large (a house, say - a real house, not a toy one), you don't want the lego interface. Sure, you can plug anything to anything, but not all of those connections make sense. Also, for building something that large, legos are too small a building block to be convenient. You want some larger things - beams and sheets of wood and particleboard, pipes, air ducts. You don't want to have to build all of those out of tiny blocks.

In the same way, I wonder if building larger applications out of FP is going to be similarly tedious. I have never done it, so I will admit that I don't know.