He seems to be operating under 3 main delusions (with a healthy dose of caste-related inferiority complex mixed in):
1. Confusion about the differences (or even the fact that they are different) between copyright, trademark, and patent. He copyrighted some software called "EMAIL", which anyone could do. That doesn't give him any ownership of the term "email" (as a trademark would), nor does it register him as the inventor in any way (as a patent would).
2. A belief that being (maybe) the first to name something X makes him the inventor of X. (At best, he could possibly be described as "one of the first to coin the term 'email'.")
3. A belief that naming something X subsequently defines what X is. Hence, he disregards all predecessors as "not X because they are not exactly the same as what I called X".
Over time, his caste-related inferiority complex seems to have evolved into a strong mistrust of recognised authority ("What does Vint Cerf know?") and then further into a conspiracy about the "military-industrial complex".
He seems more sadly deluded than an intentional charlatan.
Even though I don't like Go's explicit error handling, I think this is a very reasonable comment.
I don't like Go's explicit error handling because (1) I think it clutters up your main code path with error-handling logic, and (2) it forces you to always handle errors locally (even if that local code does not have the context to know how to handle the error) or return the error code through multiple layers of functions (back to where it can be handled).
That said, I completely agree that exceptions are also problematic. As you say, you can never really be sure of what exceptions can be thrown. Some languages have a "throw" keyword, in which you're meant to enumerate the list of possible exceptions; but of course, that's a headache to maintain, and is affected by inner code (such as library code) that might be completely out of your control or review. And when should the "throw" keyword be enforced, at compile time or runtime? And what should happen if the "throw" keyword's list of possible exceptions is violated?
Then of course there is the other problem with exceptions, the flip-side to being forced to handle an error locally: As your exception unwinds the stack, it might obliterate some local context that is needed to decide how to handle the error; or it might obliterate some local context that is needed to continue with your original task after the error has been handled!
I see C++'s `std::set_new_handler` function [0] as C++'s less-capable equivalent to Lisp condition handlers. But the function invoked by `std::set_new_handler` lacks the ability to assess local context to decide how to handle the problem.
EDIT: I would love to see a language like Nim incorporate something like Lisp's condition system. Nim already offers "procedural types" (function pointers) [1] and closures [2] to capture variables from the enclosing scope. Nim even offers "anonymous procs" [3], to avoid the need to define new error-handling functions everywhere.
I've never used the JS backend or C++ backend, so I can only talk about the C backend.
With the C backend, the Nim code is transpiled to C code (surprisingly readable C code, as far as auto-generated C goes), which is then compiled to one of: a binary executable, a shared C library, or a static C library: https://nim-lang.org/docs/nimc.html#compiler-usage
If you want to see a shared C library produced by Nim, have a play with some of the examples provided with Nim-Pymod: https://github.com/jboy/nim-pymod/tree/master/examples
It auto-generates the appropriate Python C API boilerplate functions around your Nim functions, then compiles the whole thing as a shared C library, exposing the auto-generated functions in the shared library.
Regarding runtime type-checking: Again, I can only talk about the C backend. The type checking provided by shared or static C libraries will be whatever the C compiler enforces... I haven't tested whether (or how much) this can be violated.
Nim-Pymod does auto-generate the Python->C type-checking code for you, so you can't (for example) pass in a Python string when an int is expected by your Nim function.
Pizza Photo Editor is still early-stage -- we're still adding features and increasing the coverage of different object classes in our training data set -- but the core tech is there, and it does have an interactive web UI, so it's already fun to play with. :)
Looking at the example inputs & outputs for ObjectCropBot, it's evident that the challenge is not just detecting the object and clipping it approximately, but tracing a tight precise boundary around it. We've found that DNN/ConvNet-based approaches don't offer the necessary precision, so it's necessary to perform some pre- or post-processing using other Computer Vision techniques. At Object AI, we've developed an "object boundary deduction" pipeline that combines ConvNets with other tech. It's interesting that the blog post that you've linked to makes the same observation!
Yes, my startup Object AI uses Nim code in production. We have in-house implementations of machine learning, computer vision & image processing code in Nim, using a library called "Nim-Pymod" to integrate with Python's Numpy: https://github.com/jboy/nim-pymod
(As you can see, I was one of the authors of that library in a previous startup. We haven't worked on Nim-Pymod in a while, alas -- I've been focused on the new startup! -- but Nim-Pymod is sufficient for our needs right now.)
Our webserver main-loops are in Python; our number-crunching ML/CV/img-proc code is Python extension modules written in Nim.
As a C++ & Python programmer, I'm a huge fan of Nim, which to me combines the best of both languages (such as Python's clear, concise syntax & built-in collection types, with C++'s powerful generics & zero-cost abstractions), with some treats from other languages mixed in (such as Lisp-like macros and some Ruby-like syntax). I find Nim much more readable than C or C++, especially for Numpy integration. I also find Nim much more efficient to code in than C or C++ (in terms of programmer time).
And Nim is a very extensible language, which enables Nim-Pymod to be more than just a wrapper. For example:
1. Nim-Pymod uses Nim macros (which are like optionally-typed Lisp macros rather than text-munging C preprocessor macros) to auto-generate the C boilerplate functions around our Nim code to create Python extension modules.
2. Nim-Pymod provides statically-typed C++-like iterators to access the Numpy arrays; these iterators include automatic inline checks to catch the usual subtle array-access errors. Nim macros are themselves Nim code, which can be controlled via globals, which in turn can be set by compiler directives; by compiling the Nim code in "production" mode rather than "debug" mode after testing, we can switch off the slowest of these checks to get back to direct-access speed without needing to make any code changes. (And of course Nim's static typing catches type errors at compilation time regardless of the compilation mode.)
3. Nim exceptions have an informative stack trace like Python exceptions do, and Nim-Pymod converts Nim exceptions into Python exceptions at the interface, preserving the stack trace, meaning you have a Python stack trace all the way back to the exact location in your Nim code.
Earlier on in our development of Nim-Pymod, there were some occasional headaches with Nim due to its in-development status. Occasionally the Nim syntax would change slightly and that would break our code (boo). We've also debugged a few problems in the Nim standard library. I suppose these problems are an unfortunate consequence of Nim having a small set of core devs contributing their time (rather than being supported by Microsoft, Sun, Google or Mozilla). Fortunately, these problems seem to have stabilised by now.
The Nim standard library is reasonably large, somewhere between C++ STL (data structures & algos) & Python stdlib (task-specific functionality). I recall that the stdlib could use some standardisation for uniformity, but I haven't been watching it closely for the last year or so.
I think the parent's point was about whether the AlphaGo AI can generalize to a different board size (as a human player presumably can) rather than about what is the normal Go board size, or what board sizes are easier or harder.
The parent was suggesting that while a human might possess a general understanding of Go, performing comparably regardless of board size ("The human would play on the same level"), the AlphaGo AI in contrast might drop significantly in capability on a board of different size. In effect, the AlphaGo AI might just be a very well-fitted (perhaps even overfitted) machine-learned algorithm on a 19x19 board, lacking a fundamental "understanding" of the game that could generalize to a different board size.
Hi Marcus, have you ever taken a look at Nim? It's quite similar to Swift in several respects, but it has a primarily Python-like syntax (including indentation by blocks rather than braces) with bits of Ruby & others mixed in.
At work, we use Python as our interpreted language & Nim as our fast, strongly-typed, compiled language. We created Nim-Pymod to enable Nim code to be compiled into Python modules: https://github.com/jboy/nim-pymod
There's also a web-framework in Nim called Jester, which describes itself as "a Sinatra-like web framework": https://github.com/dom96/jester
Quite possibly! That's the extra dimension added to the experiment. :)
It would be even more fascinating if you could cluster facial expressions or motions as "more female" or "more male". And for bonus points, work out a way to "filter" or "smooth" the facial signal to reduce/remove these giveaway hints (or insert false hints).
I think it would be amazing if they could combine this voice-modulation technology with a facial motion capture technology (like in Avatar) to display artificial/shifting faces as well as voices. You could effectively create a computer screen-based version of the "scramble suit" used in A Scanner Darkly! http://www.imdb.com/title/tt0405296/mediaviewer/rm1872861440
I think a combined face+voice system would be even more useful in interviews (since a significant amount of human communication is expressed through facial cues). It would also add another dimension to your proposed voice-modulation gender-blinding experiment.
There were two particular points in the article that strongly resonated with me:
> But the problem is not confined to referendums: in an election, you may cast your vote, but you are also casting it away for the next few years. This system of delegation to an elected representative may have been necessary in the past – when communication was slow and information was limited – but it is completely out of touch with the way citizens interact with each other today.
This sounds very much like an area of human communication in need of a technological update. (And I'm not talking about using insecure/rigged voting machines at elections.) I'm not confident that more frequent referenda is the answer (a monthly Brexit/Nobrexit doesn't sound like the best idea for a number of reasons), but surely there's some way to decrease the political communication/feedback latency.
But the real insight for me was this quote from British sociologist Colin Crouch:
> public electoral debate is a tightly controlled spectacle, managed by rival teams of professionals expert in the techniques of persuasion, and considering a small range of issues selected by those teams. The mass of citizens plays a passive, quiescent part, responding only to the signals given them.
There is a double-dissolution (ie, all seats in both houses of parliament are up for re-election) federal election in Australia happening this weekend, and the electioneering over the past few months has been exactly as Mr Crouch described: The leaders of the two major parties have chosen a few uncontroversial campaign issues that fail to address any of the real problems (rising socioeconomic inequality, a vocal minority undercurrent of racial/religious tension & bigotry) in Australia. All the leaders will discuss during their campaigns are these superficial issues. The people are simply expected to react to these few selected issues, agreeing or disagreeing as appropriate for their political party affiliation, without asking for any discussion of broader/deeper issues.
There are a few minor parties & independents that are attempting to broaden the discussion, but the two major parties are openly advising voters to vote "for stability" (ie, them) rather than "instability" that might result in a minority government.
What's better than comments to describe what the code does? CODE that describes what the code does. (Let the code describe WHAT the code does, and if necessary, the comments describe WHY the code does it like that.)
In C++, if I use an intermediate variable to decompose a complicated expression into easier-to-understand sub-expressions, I like to make the intermediate variable `const` to emphasize that it's an intermediate component.
"Sometimes you must bow to existing convention" is indeed a reasonable point, so I suppose I should clarify/refine my position.
If you're implementing an STL-like container in C++, then absolutely -- you should stick with the convention: `empty`, `clear`, `size`, etc. To deviate from that convention would be an exercise in confusing the users of your code. You should make a note in the class comment that it deviates from any other project-wide naming scheme because it conforms to the STL container interface, and move on.
But if you're creating a C++ class that is NOT intended to be an STL-like container (or if you're not working in C++!), then I'd argue that it would be better to go with `is_empty` & `make_empty` (if you're applying this prefix naming scheme across the rest of your codebase) for the benefits I've described above.
Some C++ programmers, perhaps. But I've just explained why `empty` & `clear` are ambiguous. Even if `empty` & `clear` can never be removed from the STL containers, there's no requirement that these ambiguous names must be propagated to new code.
But focusing exclusively on these two names is missing the forest for the trees. These two names are just a particularly striking example that illustrates the benefit of prefixes. A codebase that applies useful prefix naming will be an easier codebase to understand.
And applying prefix naming consistently will also make it easier for a new developer to contribute to a codebase, since there will be no ambiguity about what to name new functions, nor what to expect them to be named. `is_empty` & `make_empty` would simply be part of that consistency.
This article is a good start, but I found it much too light on detail. Each section ended just when I was ready for it to dive into details! For example, in the final section "Make it easy to digest":
> Using prefixes in names is a great way to add meaning to them. It’s a practice that used to be popular, and I think misuse is the reason it hasn’t kept up. Prefix systems like hungarian notation were initially meant to add meaning, but with time they ended up being used in less contextual ways, such as just to add type information.
OK, great, I agree -- but what are some suggestions/examples of good prefixes? What are some examples of bad prefixes that we should avoid?
To illustrate the sort of detail I'd like to read, here is an example of my own of good/bad method names that would be greatly improved by judicious use of prefixes.
My standard go-to example for ambiguous naming is the std::vector in the C++ STL. There is a member function `vec.empty()`: Does this function empty the vector [Y/N]? Answer: No, it doesn't. To do that, you instead use the member function `vec.clear()`. There is no logic a priori to know the difference between `empty` & `clear`, nor what operation either performs if you see it in isolation. You must simply memorize the meanings, or consult the docs every time.
In the C++ style guides I've written, I've always encouraged the prefixing of member function names with a verb. Boolean accessors should be prefixed with `is-`. The only exception should be non-boolean accessors such as `size` (which has its own problems as a name). Forcing non-boolean accessors to be preceded by a verb invariably results in names like `getSize()`, where `get-` adds no useful information, clashes with the standard C++ naming style for accessors, and really just clutters the code with visual noise.
Using these prefixes: (depending upon your project's preference for underscores or CamelCase)
.empty -> .isEmpty() or .is_empty()
.clear -> .makeEmpty() or .make_empty()
As an additional benefit, the use of disambiguating prefixes also enables the interface designer to standardize upon a single term "empty" to describe the state of containing no elements in the vector, rather than playing the synonym game ("empty", "clear", etc.). The programmer should not need to wonder whether "clear" empties a vector in a different way.
1. Confusion about the differences (or even the fact that they are different) between copyright, trademark, and patent. He copyrighted some software called "EMAIL", which anyone could do. That doesn't give him any ownership of the term "email" (as a trademark would), nor does it register him as the inventor in any way (as a patent would).
2. A belief that being (maybe) the first to name something X makes him the inventor of X. (At best, he could possibly be described as "one of the first to coin the term 'email'.")
3. A belief that naming something X subsequently defines what X is. Hence, he disregards all predecessors as "not X because they are not exactly the same as what I called X".
Over time, his caste-related inferiority complex seems to have evolved into a strong mistrust of recognised authority ("What does Vint Cerf know?") and then further into a conspiracy about the "military-industrial complex".
He seems more sadly deluded than an intentional charlatan.