Live data from Hacker News

C++: Is It Really a Cruel Joke? (2003)

webhome.phy.duke.edu

141–150 of 155 posts

Re: C++: Is It Really a Cruel Joke? (2003)

#141

Earlier quoted context omitted.

I find that strange, but I concede you know your use case better. I work on a very similar type of application that manages async workers who process large distributed NLP tasks. Writing it in Cython was extremely easy, because for the modules that have zero need for static typing, such as the part using async/await in Python 3, or when we supplement with gevent, I can just write those parts in plain Python and it’s…

Hi - thanks for outlining your case. My Cython know-how is limited to qualify any kind of comparison with Cython. Its just that my attempt with Nim went surprisingly smooth for me. Coming from some of the older languages I use and love, the reliability of the newer Nim is pleasing and coding is fun. I ended up eliminating all Python code from my back-end. Because Nim is statically compiled I can deploy pieces of it a…

> "the reliability of the newer Nim is pleasing and coding is fun."

Can you elaborate on the reliability part? I've spent a lot of time grokking Nim specifically to be able to make good judgments about whether there are use cases in which it would be a better choice than Cython, and from a reliability point of view I have not noticed anything that would distinguish Nim from any other language. I can agree that Nim's syntax is nicer than many other statically typed languages, though the language design has some warts with `result` and `discard`, etc. But I can't see any reason to believe it is 'more reliable.'

> "I ended up eliminating all Python code from my back-end."

While I can't know the reason for this in your exact case, generally this seems like a very suboptimal thing to do. Python has a much richer set of libraries, testing utilities, etc. It is a language with a huge community of users and developers, and much more likely to be a known language for someone new who joins the project. If a system was working well and someone proposed to refactor away a solid base language like Python, that would almost always be a crazy choice, regardless of any positive aspects of the targeted new language. It's similar to why you should rarely throw away old code that has meaningful tests. You can slowly refactor it little by little, but wholesale switching to something else is usually evidence of wrong engineering priorities, especially when the something else is a 'latest and greatest' kind of new language or tool, like Nim is.

> "Because Nim is statically compiled I can deploy pieces of it anywhere just like a compiled C program, without dependencies, and it means a lot in my particular situation."

This can also be done with Cython, using the options to embed an interpreter... and there are various other third party tools that allow you to create thick binaries for combined Python programs as executables, including runtimes and dependencies. To boot, you definitely should be managing the deployment of some binaries with proper dependency management practices. So really, if you're already using dependency management techniques for the binaries, the minor extra work to maintain Python environments and dependencies would almost always be pretty trivial, with a huge family of tools (pip, conda, pipenv, virtualenv, etc.) and endless tutorials on the community-developed and mature best practices for packaging Python programs.

I would be curious to know more details about a project where it was truly advantageous from a productivity and deliverability point of view to rewrite the backend to move from a stable and mature ecosystem like Python to a relatively younger and less mature system with Nim specifically to gain a benefit somehow related to ease of deploying pieces of the code to different locations. The details just don't sound like they could possibly be in favor of using Nim in a case like that.

Re: C++: Is It Really a Cruel Joke? (2003)

#142

Earlier quoted context omitted.

Hi - thanks for outlining your case. My Cython know-how is limited to qualify any kind of comparison with Cython. Its just that my attempt with Nim went surprisingly smooth for me. Coming from some of the older languages I use and love, the reliability of the newer Nim is pleasing and coding is fun. I ended up eliminating all Python code from my back-end. Because Nim is statically compiled I can deploy pieces of it a…

> "the reliability of the newer Nim is pleasing and coding is fun." Can you elaborate on the reliability part? I've spent a lot of time grokking Nim specifically to be able to make good judgments about whether there are use cases in which it would be a better choice than Cython, and from a reliability point of view I have not noticed anything that would distinguish Nim from any other language. I can agree that Nim's…

I won't comment on Cython as I haven't personally used it much, but:

> though the language design has some warts with `result` and `discard`, etc.

Why do you consider these to be warts?

Re: C++: Is It Really a Cruel Joke? (2003)

#143
post #142

Earlier quoted context omitted.

> "the reliability of the newer Nim is pleasing and coding is fun." Can you elaborate on the reliability part? I've spent a lot of time grokking Nim specifically to be able to make good judgments about whether there are use cases in which it would be a better choice than Cython, and from a reliability point of view I have not noticed anything that would distinguish Nim from any other language. I can agree that Nim's…

I won't comment on Cython as I haven't personally used it much, but: > though the language design has some warts with `result` and `discard`, etc. Why do you consider these to be warts?

For `result`, the basic description from Nim’s example pages highlights why it’s a severe problem.

https://nim-by-example.github.io/variables/result/ >

Even just needing to account for that mental gymnastics about declaring a new result variable is, I think, not forgivable.

The bigger issue though is that initialization of the return variable is implicit, which is inherently problematic. This is especially troublesome because type constructors in Nim are essentially always separate factory functions. So you have to remember to manually call a particular constructor or else `result` might be just an improperly initialized skeleton of your data type.

For example, I might have some type called MyType and a proc with return type of MyType. I explicitly don’t want the proc to initialize `result` to an empty MyType behind the scenes, for whatever implementation reasons about MyType (a common example is a type that ought to be initialized with the acquisition of a resource and should never exist in a partially initialized state in which the resource acquisition hasn’t been attempted yet, and could possibly fail later).

If I only want it to be initialized from a special constructor like mkMyType(), then in Nim, I have to code around this limitation by making it a void proc, and passing in an appropriately mutable reference.

In other words, to avoid possibly inappropriate return type initialization, I am forced to revert to poor C-style void functions all over that mutate placeholder inputs by convention, which undermines a lot of things Nim tries to do to improve clarity about pure vs impure procs.

I don’t have time to go into why discard is a bad design idea right now, but hope to come back and add more later.

Re: C++: Is It Really a Cruel Joke? (2003)

#144

Earlier quoted context omitted.

Hi - thanks for outlining your case. My Cython know-how is limited to qualify any kind of comparison with Cython. Its just that my attempt with Nim went surprisingly smooth for me. Coming from some of the older languages I use and love, the reliability of the newer Nim is pleasing and coding is fun. I ended up eliminating all Python code from my back-end. Because Nim is statically compiled I can deploy pieces of it a…

> "the reliability of the newer Nim is pleasing and coding is fun." Can you elaborate on the reliability part? I've spent a lot of time grokking Nim specifically to be able to make good judgments about whether there are use cases in which it would be a better choice than Cython, and from a reliability point of view I have not noticed anything that would distinguish Nim from any other language. I can agree that Nim's…

> Can you elaborate on the reliability part?

What I meant by reliability is personal. The stuff I learned when reading and experimenting with Nim in one day sufficed to do practical things in my daily work. Any new information was found easily and I could keep developing (vs. some years ago when I was learning Haskell, after the first joy with the "cleanness" of the syntax, the systems programming part down the road became a bear. I had to go through yet another learning curve to digest that). May be reliability is not the word, but its just that Nim didn't let me down even though only a very limited time was invested to learn it for my purposes.

> Python has a much richer set of libraries, testing utilities ..

Yes indeed. If an off-the-shelf numpy package sufficed I would have stuck with it. For recent numerical work (this is where I tried Nim first, graph theory, matrices where you have observed non-standard sparseness, ie. not a Toepiltz kind "standard" sparseness, and these you use to your advantage by coding it yourself). Even if I find an exactly needed package from the community, I have to read the sources to know how it is coded. Subtle details in implementation cannot be fathomed from verbal documentation as it impacts rate of convergence, memory consumption etc. or perhaps a bug your use case uncovered! So during prototyping and validation you use python or whatever to help with the exploring, test cases etc. Once you know exactly how you need to structure the algorithms, I code With Nim and I will know exactly whats in it. Nim coding has been easy, and the performance unusually good.

> with a huge family of tools (pip, conda, pipenv, virtualenv, etc.)

In my point of view, I'd rather not carry these many things to develop and deploy to maintain and manage processes at many distributed sites. On my local machine, yes. The initial development install of Nim anywhere (takes 3 minutes, no admin) has all the tools for the build, unit test, package, integration test, and you can run compiled binary anywhere, on systems supporting just the key data/network dependencies that the application demands...traveling light.

Re: C++: Is It Really a Cruel Joke? (2003)

#145

Earlier quoted context omitted.

#include int main(){ printf("Hello World"); return 0; } >5649591 -rwxr-xr-x 1 user user 8288 Jul 5 21:49 a.out What am I doing wrong?

Did you use -O3 or some other optimizations?

No, just `gcc a.c`.

Re: C++: Is It Really a Cruel Joke? (2003)

#146
post #142

Earlier quoted context omitted.

I won't comment on Cython as I haven't personally used it much, but: > though the language design has some warts with `result` and `discard`, etc. Why do you consider these to be warts?

For `result`, the basic description from Nim’s example pages highlights why it’s a severe problem. https://nim-by-example.github.io/variables/result/ > Even just needing to account for that mental gymnastics about declaring a new result variable is, I think, not forgivable. The bigger issue though is that initialization of the return variable is implicit, which is inherently problematic. This is especially troublesom…

> For `result`, the basic description from Nim’s example pages highlights why it’s a severe problem.

This is simply an explanation for newcomers. It's really not something that's a "severe problem", just something to be aware of.

> The bigger issue though is that initialization of the return variable is implicit, which is inherently problematic. This is especially troublesome because type constructors in Nim are essentially always separate factory functions. So you have to remember to manually call a particular constructor or else `result` might be just an improperly initialized skeleton of your data type.

This really isn't an issue when you can do this:

    import options

    type
      MyFile = Option[int]

    proc getFile(): MyFile =
      # Oh no, I didn't initialise it...
      discard

    echo(getFile()) # -> none[int]
You can also use `ref T` and achieve a similar effect: an explicit "empty" state. So there is no weird semi-empty state problem here.

I would really like to hear why you think `discard` is a bad design idea. I honestly cannot even imagine a reason as I consider this to be one of the best features of Nim.

Re: C++: Is It Really a Cruel Joke? (2003)

#147
post #146

Earlier quoted context omitted.

For `result`, the basic description from Nim’s example pages highlights why it’s a severe problem. https://nim-by-example.github.io/variables/result/ > Even just needing to account for that mental gymnastics about declaring a new result variable is, I think, not forgivable. The bigger issue though is that initialization of the return variable is implicit, which is inherently problematic. This is especially troublesom…

> For `result`, the basic description from Nim’s example pages highlights why it’s a severe problem. This is simply an explanation for newcomers. It's really not something that's a "severe problem", just something to be aware of. > The bigger issue though is that initialization of the return variable is implicit, which is inherently problematic. This is especially troublesome because type constructors in Nim are esse…

This is not a reasonable answer regarding initialization, because you may not want to wrap everything in an Option type. Especially not for an obscure side effect reason like initialization, and then need to litter Option handling all over, which destroys a lot of information in your types. It would be like misusing Maybe in Haskell as if it was for exception handling. You could never write pure functions that get lifted to utilize Maybe. Instead you’d be forcing people to manually use Maybe everywhere, for all signatures. I had also already pointed out the Ref option in my original comment, as an example of exactly the type of anti-pattern that makes it a bad thing you constantly have to code around in Nim.

It’s not reasonable to suggest you have to code past this intrinsic limitation everywhere by muddying all your function signatures to take Option types and adding extra logic to pack or unpack values from Option types all over... to solve an initialization problem!

Re: C++: Is It Really a Cruel Joke? (2003)

#148
post #146

Earlier quoted context omitted.

For `result`, the basic description from Nim’s example pages highlights why it’s a severe problem. https://nim-by-example.github.io/variables/result/ > Even just needing to account for that mental gymnastics about declaring a new result variable is, I think, not forgivable. The bigger issue though is that initialization of the return variable is implicit, which is inherently problematic. This is especially troublesom…

> For `result`, the basic description from Nim’s example pages highlights why it’s a severe problem. This is simply an explanation for newcomers. It's really not something that's a "severe problem", just something to be aware of. > The bigger issue though is that initialization of the return variable is implicit, which is inherently problematic. This is especially troublesome because type constructors in Nim are esse…

Briefly re: discard — since void is not a proper type like say Unit in Scala, it makes void functions (especially with type parameters) very awkward in general. Adding the additional confusion that you can treat a value-returning function as if it was a void function with discard, and it further destroys clarity of the meaning of types, encouraging developers to shoe-horn side-effectful computation into value-returning procs assuming it will just be used with discard (so there becomes weird convention based designs where you think you’re supposed to use something for its return value, but actually the “intent” is for you to use discard).

Basically, discard & result make Nim a nice language if you are programming alone, and you know & intuitively understand the conventions being used or you can control manually wrapping stuff in Option for a bunch of type signatures or whatever and you can enforce it how you like it.

But when writing code for other people to interact with, the implicit return type initialization creates weird ways of coding around it that are not clear or common sense for other people, and then mixing void and the use of discard makes it super unclear when or why it’s useful to ignore the return type in some context, instead of it having been actually designed as a void function (and for this to have a proper type).

This comment on this Nim issue gives a good example of what I mean, https://github.com/nim-lang/Nim/issues/7370#issuecomment-376... >.

But generally, I think it just speaks badly of discard-style thinking. Write void functions to communicate side-effectfulness. Don’t mix concerns about a side effect and an optional return value and assume people will get your meaning and know when to use discard. That is more like coding for the function author’s benefit instead of coding for readers, users or other contributors.

Re: C++: Is It Really a Cruel Joke? (2003)

#149
post #146

Earlier quoted context omitted.

> For `result`, the basic description from Nim’s example pages highlights why it’s a severe problem. This is simply an explanation for newcomers. It's really not something that's a "severe problem", just something to be aware of. > The bigger issue though is that initialization of the return variable is implicit, which is inherently problematic. This is especially troublesome because type constructors in Nim are esse…

This is not a reasonable answer regarding initialization, because you may not want to wrap everything in an Option type. Especially not for an obscure side effect reason like initialization, and then need to litter Option handling all over, which destroys a lot of information in your types. It would be like misusing Maybe in Haskell as if it was for exception handling. You could never write pure functions that get li…

That's true and I wouldn't use the Option type for that either. There is a switch that warns about variables that are not initialized explicitly (including the 'result' variable) and an RFC to make this switch non-optional. https://github.com/nim-lang/Nim/issues/7917

Re: C++: Is It Really a Cruel Joke? (2003)

#150
post #146

Earlier quoted context omitted.

> For `result`, the basic description from Nim’s example pages highlights why it’s a severe problem. This is simply an explanation for newcomers. It's really not something that's a "severe problem", just something to be aware of. > The bigger issue though is that initialization of the return variable is implicit, which is inherently problematic. This is especially troublesome because type constructors in Nim are esse…

Briefly re: discard — since void is not a proper type like say Unit in Scala, it makes void functions (especially with type parameters) very awkward in general. Adding the additional confusion that you can treat a value-returning function as if it was a void function with discard, and it further destroys clarity of the meaning of types, encouraging developers to shoe-horn side-effectful computation into value-returni…

I'm not following you really. 'discard' is an enforced, explicit statement about that you throw away information/the result of a computation. That's against "nice if you are programming alone" as much as it can get.
Post reply on HN