Hacker News new | past | comments | ask | show | jobs | submit login

For example declaring function of the class as const pretty much turns it into pure function and compiler makes sure that it does not modify state of said class. So you are wrong from a practical standpoint. try to modify state of the class inside const function and it'll be compiler error.



That doesn’t prevent you from accessing global variables or reading member variables (which many const functions do). Marking a member function as const doesn’t in anyway guarantee purity, and is actually quite unrelated.

In fact, most const class functions are by definition not pure at all, because they will read internal state, otherwise they wouldn’t even need to be members of the class. So I would be willing to argue that nearly all const class functions are impure.


um, i seriously doubt that many const functions access global variables. if those in your code do, then i suggest your code has problems - the typical use of a const function is doing something like length() does on a std::string. how, or why. would such a function access a global variable?


I agree, but most would access internal state, which is equally impure. A pure function has no access to anything outside of its function parameters, and it changes nothing outside the scope of the function.

In the context of a pure function, a local member variable is no different than a global variable because it’s outside the scope of the actual function. If you can’t take the function away from the class and have it still work perfectly, then it’s not pure.

length() is not pure, but a function like length(string) could be.


the instance of the class is a parameter to the function. As well your definition of pure is not the accepted definition. The definition depends absolutely nothing on the internal implementation as long as some in invariants hold.

1. For the given set of inputs ( including the attached object ) the output is always the same if called again with the same inputs ( including the attached object in the same state ).

2. No side effects. This means that nothing can be observed about the function apart from it's return value.

If you wish to quibble as to whether the object is a parameter or not then observe that in c++23 it will be allowed an explicit this parameter to methods This is not to make the methods more pure but to enable other types of optimizations and reduce duplication of code over const and non const methods.


That's an odd interpretation of purity. As per the article:

> A pure function only looks at the parameters passed in to it, and all it does is return one or more computed values based on the parameters... It doesn’t maintain internal state... Ideally, it isn’t passed any extraneous data

If you send in an entire object state as an argument (or as an attached instance, as you argue), this is not a quintessence of functional purity and strays far from these concepts. Consider: your object can have all sorts of data in it that you are passing to every member function, and it is unlikely all that state needs to be used in every function -- as the article points out, this defeats the purpose as it's akin to passing in a big pointer to a bunch of state.

In a pure function, it accepts only the specific data it needs, nothing else or extraneous, and returns a value based on these specific inputs.

As I mentioned in another comment, you could say for a particular type that since it only has one data member, no harm done -- but in the general sense, most objects have more than one piece of data, and not every function needs every piece of data, so passing all that in is a sloppy approach to purity.


The object state is a parameter passed to the function. The number of arguments passed to a function does not affect it's purity. The feed forward recognition phase of an LLM is pure but has billions of parameters. The purity is defined by it's behavior in relation to again.

1. Does it always return the same result for the same input parameters 2. Does it modify anything other than return a value

These two properties define purity. Simple and not odd at all.


Not sure why you are arguing about this? The issue is about the idiomatic, expected style that surrounds pure functions and functional programming. The posted article goes into this in greater detail (and more elegantly than this thread) as to why the pattern you describe -- passing a big pointer of potentially large composite data to a function (implicitly or otherwise) -- is not in the spirit of FP purity. If you want to be pedantic, you are welcome and you are academically correct, but the tradition of FP in practice is not to do this (as also pointed out in the article). It's not a question how many arguments but rather if there is extraneous data that the function does not need, as would be common with the full object.


Not sure why you are arguing about large classes with extraneous data. If this is how you program your classes and it works for you then great but honestly you should try for small immutable class where possible with pure functions ( methods). It's really liberating.


>"It's really liberating"

What IS really liberating is not being stuck to a single paradigm and let person decide which particular tool use to solve particular problem


why do you think the length member function is not pure?


Member functions have an invisible argument: the pointer to the C++ object. You can access this argument using the 'this' keyword. John Carmack describes pure functions like so:

> Pure functions have a lot of nice properties. Thread safety. A pure function with value parameters is completely thread safe. With reference or pointer parameters, even if they are const, you do need to be aware of the danger that another thread doing non-pure operations might mutate or free the data, but it is still one of the most powerful tools for writing safe multithreaded code.

Emphasis on 'value parameters'. The invisible 'this' argument is not passed by value, it is passed by reference. By Carmack's definition, C++ member functions are not pure.


If you read the article and see what pure functions are, you will understand. The length function has no parameters, by definition it must access data outside of the function if it’s going to do anything. This means it is not pure. Can you take that length function outside of the class and run it and have it do something? No, it is tightly coupled to the class that it is attached to.


A member function must have at least one parameter. Here it's "parameter0":

parameter0.membfun()

It doesn't really matter whether the parameter name is separated from the function name by a dot, or a bracket. In a different syntax, it might have been written as "membfun(parameter0)" without any practical difference.

This means that Foo::length() can be pure no problem, because Foo is its parameter, and, as such, in its scope.


I see your point, but you are still passing the entire state of the entire object to your function if you want to follow that line of thought. This is also discussed in the article, and it’s not really what functional programming is about. What other state is in there that the function has access to? Maybe on a case-by-case basis you can say that particular object only has one piece of data, but in the general case this is definitely not what purity and functional programming is about.


Splitting hairs


It’s not really splitting hairs — you lose the primary benefits of functional programming if you disregard these things.


Incidentally if this has whetted your appetite for functional programming, I encourage you to read a lot more about it and study languages that are truly functional. It could be quite liberating to see this approach to software development. It is not a panacea but it is a very useful perspective to acquire on software engineering, regardless of language, which is what this article discusses.


i find this slightly patronising - i have studied languages such as scheme and haskell. and i don't see how writing a function such as length(string) could be pure if the member function length() was not, as you would pass a copy of the string (ok, pure) and then call a member function (impure, according to you) on it to actually get the length.


No, you would not typically call a member function on anything in a pure language. Instead, you would pass a sequence of characters and the function would return the length, by counting them.

I didn’t mean to sound patronizing, I apologize for that. Your question suggested that you aren’t that familiar with functional programming, so I was just trying to steer you in the right direction. A function that takes no parameters is not a pure function in general, unless all it does is return a constant value, which wouldn’t make much sense. length() does not make sense in a functional programming style.


well, the length function for c++ strings does return a constant object - an integer value.

and passing a sequence of characters? hello, C strlen( const char * s); ! with all the problems that has. and if you don't want to pass some horrible pointer, you have to pass some object containing the characters which must have a length function itself. hello, std::string!

what you are ignoring here is how functional types either ignore functionality under the hood, or sacrifice it for performance.

which is why functional programming will never catch on (look at lisps), imho. programmers really like to know wtf their code is actually doing on a mutable machine.


> the length function for c++ strings does return a constant object -

No, I mean, a standalone function with no parameters can only be functional if it always returns the same value, which is effectively no different than declaring a constant. The function always returns the same value all time (which wouldn't be so useful).

I think you are trying to find C++ examples to match the broader implications of functional programming (which is what I'm talking about), which will be difficult.

As far as whether "functional programming will catch on", I don't think it will for C++ so much, but it certainly has been very successful for many other languages. I earn my living writing only functional code, but most of the time it is not in C++.


Member functions effectively have the object as the first parameter.


Another commenter pointed that out, and you can see my other reply regarding that.


The "pretty much" does all the work here though.

It's not pure if you can modify the state of a global, the file system, the environment, the standard output, etc., and this is half of the reason why purity is desired.


And it’s not just about modification, it’s also not pure if you simply read data that is not passed into the function via parameters. Because in a pure function, you don’t need to access anything, reading or writing, that is outside of the function itself.


certainly desired, but not always possible, seeing as we actually want to do state changes, for example output, unless with much hand-waving monads, which of course really do change state.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: