Live data from Hacker News

Help me sort out the meaning of “{}” as a constructor argument

scottmeyers.blogspot.com

161–170 of 181 posts

Re: Help me sort out the meaning of “{}” as a constructor argument

#161
post #92

Earlier quoted context omitted.

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…

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…

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.

Re: Help me sort out the meaning of “{}” as a constructor argument

#162

Earlier quoted context omitted.

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…

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 mutabilit…

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.

Re: Help me sort out the meaning of “{}” as a constructor argument

#163
post #61

Earlier quoted context omitted.

Any sense of where the C++ refugees are heading? Rust? Go?

Java/C#, though the complexity is now matching C++, especially with all the new fashionable functional "features" most large code bases are a huge mishmash of styles and complexity that is making me wish for sensible C++ developers again.

The problem with Java isn't so much the language. It's the ecosystem and the community. The ecosystem is very rich, so there are many ways of doing pretty much anything, which means it's easy to get lost in the complexity. And the community is fad-prone. Patterns! Injection! Annotations! Something else (for now)!

A certain skepticism is crucial for staying sane.

Re: Help me sort out the meaning of “{}” as a constructor argument

#164
post #134

Earlier quoted context omitted.

Any sense of where the C++ refugees are heading? Rust? Go?

Honestly for me… C++. C++ but with restricted and consistent feature usage at every level of the stack. This means no stdlib, no stl, no boost. Writing your own pared-down standard library is actually not that hard if you make sure none of the calling code hits edge cases. 90% of boost just makes sure it's robust in the face of anything (classes that are movable but not assignable, initializer list constructors that…

The main D people (Walter and Andrei) and/or the forums say that there is work in progress to remove GC dependency from some of the libraries as an option. Not sure of the progress or rate of it though.

Edit: Sorry, should say "main D architects" - there are many other people involved in developing D.

Re: Help me sort out the meaning of “{}” as a constructor argument

#166
post #69
post #66

Earlier quoted context omitted.

Even if C++ have been the way I've earned money the past +20 years, I've programmed quite allot of Scala in my spare time. If find the language beautiful in its compact, expressive syntax, I also like the standard lib and the vibrant community. Being able to mix OO and functional programming, is also something I enjoy very much. So being able to use this language as a system language, I very much look forward to. But…

Sure, I use and like both of them. C++ for 3D graphics, Scala for Big Data. Yet I have seen so many things go wrong in both of them so my perspective is a bit different. Imagine if somebody redefines basic operators to mean something different, starts throwing int as exception in C++ or use templates with template parameters with number parameters and you have to figure out what exactly does this thing do? Or in Scal…

How is that different from using a C function called add_two_ints which deletes the root file system and returns 42?

I don't think it is possible to create a language that can prevent dumb code from being written.

Re: Help me sort out the meaning of “{}” as a constructor argument

#167
post #49

Earlier quoted context omitted.

Most languages have Undefined and Implementation specific behavior. Few languages have so carefully specified their undefined behavior as C++ though.

Undefined behavior is not specified, by definition! It is the absence of requirements, including the requirements to diagnose. C++ has something called "unspecified behavior" also, which is stronger than undefined, because it gives requirements. It denotes some circumstances when an implementation can behave in one of a finite possible ways (none of which fail) and must choose one of them without documenting which ch…

> Undefined behavior is not specified

But it is precisely specified how to invoke undefined behavior. For example when to numbers are added and they overflow the size of the type. This is carefully specified when this is or isn't undefined behavior. The C++ standard goes into excruciating detail but they have not covered everything

Compare that to many of the newer scripting languages. Elsewhere on this page I described how to recover from a segfault by setting string conversion function, which I don't think was specified anywhere. You can break some newer language by overriding innocuous function like #hash on some objects. These languages have at least as many pitfalls as C++ they are just less well described.

Re: Help me sort out the meaning of “{}” as a constructor argument

#168
post #75

Earlier quoted context omitted.

This is how it works in Ruby. In the CRuby/MRI interpretter when a segfault happens it calls the #to_s method on the current execution context, to get the some memory address and technical details. Ruby happens to be flexible enough that you can override that method. Then you can call whatever you want and you have effectly "recovered" from a segfault. The parser is totally in an inconsistent state and could crash at…

You can do the same thing in C++, either by intercepting signals on Linux, or setting up a structured exception handler on Windows. It's useful when you either A) want to attempt a recovery or B) have a complex tear down.

But in C++ you are specifying a signal handler, not overloading a string conversion function.

Imagine your surprise when you discover via dmesg that your have generates hundreds of segfault per second but a string conversion functions hid this bug.

Re: Help me sort out the meaning of “{}” as a constructor argument

#169
post #116
post #99

Earlier quoted context omitted.

I misremembered... So I just went and look this up the C++14 standard, or at least the nNvember draft is 1368 pages and the Ruby ISO standard is 313. I was off by a fair amount. But this made my point more extreme. C++ has mauch smaller feature list than Ruby and the spec is more 4x the size C++ is much more specific and precise. Ruby and many other languages will use the behavior of some de-facto implementation as t…

Is C++ really better specified? Some languages use "the implementation is the spec" and that's bad, sure (though I'd argue it's less bad than "programs that worked on previous versions of the compiler will contain memory safety vulnerabilities on newer versions of the compiler", which is the end result of C++'s approach to undefined behaviour). But compare to e.g. Java, which has a (shorter!) spec with multiple imple…

Memory is specifically hard one for C++ because it tries not to put a layer between the coder and the underlying hardware. Much of the memory model must be implementation defined.

It wasn't that long ago that we had different pointer for small fast memory and large slow memory, back when more that 64k was a real big deal. Kind of like how now video memory is a real big deal. Now we have a bunch of weird C APIs for putting things there (I presume these can be accessed from JNI or something similar), but these are temporary ugly hacks.

When video ram becomes a more common thing to refer to specifically, what will that look like in Java? That weird memory that C++ has is ready, because it has done exactly this in the past a few times. I am also looking forward to C++17 and its newer way to run std algorithms on heterogeneous executors (like GPUs).

Re: Help me sort out the meaning of “{}” as a constructor argument

#170
post #152

Earlier quoted context omitted.

I'm seeing a few people in this thread mention checked exceptions being cruft. I haven't heard this before and was wondering about the reasoning. Why are checked exceptions cruft?

Because in practice they lead to exceptions not being handled properly with a lot of boilerplate try catches. If you can't do anything sensible with an exception (like retry a couple of times) then they shouldn't be caught. The other alternative is chaining throws on function definitions up the call stack. Most new libraries don't use checked exceptions. They were a good idea in theory but not in practice.

What do you think of languages like Rust, Go, or Haskell which return errors as part of the return type? That's somewhat akin to having all exceptions be checked.
Post reply on HN