Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

My god c++ is atrocious.


Like "Wargames", the best way to win is not to play.

Between moving from MS to POSIX environments in the 90s, and the "death" of Borland, this left me with few options other than another Faustian deal with Java-land, alas.

I'm actually liking Javascript nowadays, though. Especially as more of an FP-capable language than an OOP-mandatory language.


That said... if you are grinding out games on a $200 piece of console hardware (a "toaster emulator"), C/++ is your gig. Possibly with a thin patina of scripting over the top of it, I suppose.


I'm loving the fact fact that languages seem to be moving towards some of the better parts of FP and away from some of the worse parts of OOP. I'm not particularly fond of fully FP languages but they have some really nice ideas that I've been enjoying using.


I agree. And for myself at least, I could also say:

I'm not particularly fond of fully OOP languages, but they have some nice ideas that I've been enjoying using.

If a thing I want to make is a stateless process, modeling it as a function seems nicest. If that function can be truly a function (i.e. pure), that's best. If it can be semi-pure, in the sense that its only access to mutation is via its arguments (e.g. it takes in a DB handle explicitly), that's alright. If it has other access to global state, perhaps reconsider.

If a thing I want to make is a container for state, and its state transitions have some structure to them, then I hear there's this thing called an ADT, and OO seems pretty nice.

Neither of those statements is an architectural manifesto, and OO design and functional design both seem like bad ideas to me. That is, requiring modules to be instances of language-syntax-level functions or language-syntax-level objects seems like a bad idea to me. I guess if you go read the plain-English descriptions of Smalltalk objects, that matches my idea of how modules should work, except when they should be functions in a plain-English sense.


FP and OO are completely orthogonal in my eyes. I can utilise immutable data with referential transparency just as well with Objects as I can with Modules + Structs, but only the latter is called "FP".

I think because Java and C++ championed a very impure OO, based around C-like imperative semantics, people regard huge bundles of mutable state as canonical OO. To me that's not the big idea, the big idea is Objects vs Modules + Structs.

But I think I'm on the fringe here.


I'm confused that you seem to think that "FP" means immutability. I think that most lisps and schemes, for example, have had mutable state. ML does. I think APL does? I think Erlang does, even though it says it doesn't? It's just a few Johnny-come-lately languages that do this immutability-is-the-default thing. Heck, even Clojure doesn't commit to it. Although I agree that lots of them discourage the use of mutability (including ML, APL, and Erlang).

To my way of thinking, OO means "big bundles of state, with really aggressive encapsulation". And FP means first-class functions, and more pipelining/chaining with less encapsulation. Smart data, vs functions-plus-dumb-data.

And so I think that OO isn't technically incompatible with immutability, but it fits better with FP. And OO isn't technically incompatible with purity, but it fits a LOT better with FP.


Functional Programming as I've always heard the term defined is the style of programming that avoids mutable state in favor of computation over immutable data structures. From Wikipedia:

> In computer science, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. https://en.wikipedia.org/wiki/Functional_programming

See also "total functional programming", which takes the concept a step further, and only permits programs that provably terminate (limiting the kind of state that can be manipulated even locally within functions).

My two pence: FP contrasts with the procedural style of programming, which focuses on mutating state, working with functions that have side-effects.

For example, in a procedural program it would be perfectly normal to call an operation on a file object, passing it a buffer object as input, while expecting it to fill the buffer with the file contents, and while returning no value and throwing an exception on error. In functional program this would be discouraged, in favor of something like an operation on the file that reads the file contents, returning a buffer as output.

I would consider both of these styles properly orthogonal to object oriented style, which is a style which permits there to be many different instances of a particular interface with different behavior. OOP focuses on identifying abstractions and implementing code in terms of abstractions. For example, both the file object and the buffer might provide the abstraction of being sequences of bytes. OOP allows a form of generic programming where I can write an algorithm that operates on all instances of the sequence-of-bytes interface without concern to which particular implementation the code is interacting with at the time. Code can be written in both an OOP and FP style if object methods avoid modifying object state.

In practice, however, a lot of object oriented code choose to assign objects local state that is manipulated via side effects from method calls. For example, a method on a string that modifies the string by appending to it is a method that follows procedural style. By comparison, a method that concatenates the original string with the input string and returns a new string is a method following FP style. Both approaches have tradeoffs. Object orientation means that there can be multiple different concrete string implementations complying with the string interface, that can be passed interchangeably to code written against the interface. The Unix file descriptor pattern is a form of object orientation, since file descriptors may refer to several different resource types supporting similar methods via syscall. Object systems tend to allow the creation of new implementations later without mandatory coordination with existing code using that object interface.


I've seen the WP page. If that's what FP is, then I think that means that either

  * think Lisps and Schemes aren't true FP, or
  * think that Lisps and Schemes avoid mutable state
Which one of those is your belief? I'm not a serious user of any allegedly-FP language, so maybe I misunderstand the history of FP. Note that I concede that Lisp seems to be less obsessed with mutating state than most procedural languages, but I think saying that it "avoids" it is an overreach.

Of course, some people could claim that "old" FP languages like Lisp and Scheme aren't truly FP.

As for your definition of OO, I think the word that describes abstraction across various instance-types is "polymorphism". That's when code can be written that handles multiple types, either because the typing system allows it, or because the typing system is so flexible that it fails to forbid it. Functional code is usually highly polymorphic, whether it's an aggressively static type system (Haskell with type classes) or an aggressively late-binding dynamic type system (typical Lisp, before anyone bothered to invent the phrase "duck typing").

Again, the central concept of OO, at least according to Alan Kay (the inventor/definer of the term), who said in 2003 (later than other definitions of his I could find) "OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things." I think it's pretty clear that statefulness is pretty essential to that definition.

http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay...


Popular is not always (or even often???) the best way to go ;-) Being on the fringe usually means you've thought about it more than most people.

I'm an OO guy who has been moving more and more in the FP direction. I look at it a bit differently that you, but basically have the same conclusion (I think).

Rather than saying OO and FP are orthogonal, I tend to feel that OO and FP are essentially the same, but that popular OOP misses the point completely.

If I have a struct and a set of functions, where the first argument of the function is always the struct, how is that different than having an object with a set of methods? It might (or might not) be implemented under the hood differently, but whether I write the object on the left, or as the first parameter, it's all the same.

With respect to mutability, most FP languages don't allow mutable data structures. I can likewise restrict myself to immutable data structures in OO languages. Most people don't. Unless you have a specific performance issue in mind, I think this is usually a mistake. I think the fact that mutable data structures are popular, is not equivalent to saying the OO encourages mutable data structures. It's equivalently bad in both camps (which I suppose is the meaning of "orthogonal" ;-) ). Immutability has memory management considerations which I will discuss in a minute.

WRT polymorphism, with OO languages, ad-hoc polymorphism (operator overloading) is essential, while parametric polymorphism (generics) is optional. With FP, it tends to be exactly the opposite. But if you consider that both ad-hoc polymorphism and parametric polymorphism are useful tools in both approaches, I think it's kind of a moot point.

The rest of it boils down to coupling and cohesion. In OO, you have encapsulation which forces you to reduce your coupling in certain ways. You tend to have cohesive code in that all functions dealing with a particular data structure are grouped with that data structure. In FP, you have cohesive code in that all your functions doing a particular operation are grouped together. Coupling is not strictly enforced, but writers of good FP code enforce it themselves. But it's not like you can't do both styles in both systems. It's just that the language implementations make one style easier than the other.

The only place that I see which is very different is in garbage collection. If you are using immutable data structures, it is hard to know when to deallocate the memory. So you need some kind of garbage collection (even if it is just reference counting). Having it built in to the language makes it very convenient, but it is hardly a show stopper if you have to write your own (or use a library).

With C++ there is an idiom (which I still think is a good one) where you try to only allocate memory on the stack. Everything is a local variable and you send those local variables to functions that fill in the data for you. That way you can explicitly understand the lifetime of every data structure in the system. I've done a lot of embedded code where I needed to keep track of every byte of code and to know exactly where it is allocated and deallocated. Techniques like this help, but it is obviously not immutable. I don't know how to do this kind of thing with traditional FP languages.

But really, it's only the very last thing that strikes me as being particularly different. The rest is syntax and how much typing I need to do. It's more that the language designers have idioms that they prefer and make those idioms easier. FP and OO seem to share the same pool of idioms, though.


I miss Delphi, it was awesome for rapid GUI development :(


You can check out the cross-platform OSS equivalent if you are feeling particularly nostalgic!

http://www.lazarus-ide.org/


Yeah, I bought a copy, but never really used it. Too much work on unix systems for me by that time. TP for Win and (DOS) TP before that were pretty good, though.


Similar path, I ended up in a mix of JVM and .NET lands, project wise.

I still enjoy using C++ on personal projects, but at work only if there isn't any other way.


C++ is hard. If one sticks to a strict subset it is a nice language. The problem is the code one didn't write. Even the STL is ugly to use. They are trying to fix the language by adding features but it's like Javascript, the old ugly ones are still part of the spec.


The worst part of the JS "enhancements" is trying to make it more like Java, rather than bringing it back to its Lispy + Smalltalky roots.

I guess the assumption nowadays by The Management is that programmers are too stupid to learn anything new delimited by other than curly braces, or learn how to backtrace data flow between functions, rather than debugging by property-setter breakpoint.


Can you give me an example of a "JS enhancement" you are talking about? Its not that I don't believe you I just am curious. I haven't changed the way I, personally, written Javascript since jQuery came out so I'm not up with the new stuff.



Yep. TypeScript !== JavaScript, but it's along a similar misdirection.

Then there's "let". I guess it's not hurting anything, but how useful an addition is it, really? How many nested, non function, blocks you got in your code, buddy, that you need a new scope for your nested for-loops and else-ifs?!?

Between things like forEach, map, filter, etc, I don't actually write very many manual loops anymore, and often use an IIFE for something that outgrows a ternary. Most of my "blocks" are functions.


The problem is that even if all team members across the company agree on the subset, it might change its meaning depending on which language version (ANSI) and compiler vendor/version is being used.


And it might change meaning without changing language versions. Example proposals include N3922 and P0136R1.


Yes you are absolutely right. C++ compiler ecosystem is far from being monolithic.


please, if you had 10 years of experience in the language, read every article on C++11/14/17, followed closely the evolution of the language, the answer would have been obvious...

... ok, even I can't say that with a straight face.


Back in the 90's I was working on an operating system kernel that was written in C++. I had read up on the language and had done a lot of compiler work, so I was kind of a local tutor. I'll never forget my boss' reaction when he overheard me tell a coworker "look, if you want to expose your private parts here, you'll need to make a friend."


The old idiom I learn in college a long time ago was "only your friends can see your privates."


I would not go so far to call it atrocious, but it has demonstrated how a collection of rules, each (for the most part) well thought out, can lead to a combinatorial explosion of complexity, together with some highly unintuitive corner cases. The strong desire for backwards compatibility all the way to C, together with some expedient principle-breaking, has made things more difficult. All of this has been thoroughly investigated and well-documented by Mr Meyers, and I would like to thank him for all his books and articles on the language.


So was this comment. Please take the negativity to r/programming.


There is no need to smear another site.




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

Search: