June 5, 2013

C++ rants (continued)

(link)

>Care to write an explicit example of a deep problem? (Except memory management - you already mentioned garbage collection.)

Concurrency, for example.

My point being, that C++ adds absolutely nothing interesting.

>All right. Then why do you think C should have support for structures (struct {...})?

That's just singularly stupid.

C is a good language. It's complete enough (and yes, the ability to handle structured data is very much required for any serious language) to be supremely useful, while at the same time being quite simple.

A language without structured data types would not be a powerful language the way C is. You do need data structures, and you need pointers (to both data and code) to be at all interesting.

But where do you draw the line?

I know that you as a C++ proponent you probably won't really "get" this simple argument, but try:

- read the K&R book on C (the ANSI edition), and be enlightened.

Notice how the language is basically described by one rather thin book. Readably.

So what C does so well is to do that whole "make it as simple as you can, but no simpler". And that is what makes it great. The language is powerful, yet fairly minimal.

There really aren't many features you could remove from the C language without crippling it. Sure, there's
three different looping constructs, and you could make trivial (syntactic) changes to the language, but that's
really not the point. The language is simple, but without being too simple.

Now, that's not what you always want. I understand very well why people want less system-oriented languages with more built-in functionality. As mentioned, support for both garbage collection and concurrency are quite real problems, and they are both things you can do in C, but that you cannot do well with library interfaces, which is how you normally would extend on C.

And garbage collection and concurrency are way more than just syntactic extensions. You can still do them very badly, of course, so it's not a trivial path to go down, and I'm not saying hat a language magically becomes "good" just from supporting one or the other.

But again: C does what it does very well, and with a clarity of thought and design that is entirely and utterly lacking from C++.

And yes, I happen to think that clarity of thought and design is a good thing. It's why I liked UNIX, even though I was initially introduced to other things (VMS - ugh).

C++ is a mess. There's no design. It's just "add crud on top of C". And the crud isn't even meaningful, much less does it have a design. It's totally and utterly random.

It started out random, now it's randomness that gets added to by a committee.

>For example, namespaces and function overloading are *not*
>useless. They *do* solve a real problem that C is incapable
>of solving.

You're full of it.

>For example, if you want in your source code to define a
>function called "connect" and you also want include
>"sys/socket.h", you cannot do that in C.

So to prove how it's not just a syntactic feature, you start talking about syntax?

What drugs are you on?

The name overloading is a total syntactic feature. In C, the way you fix your problem is by a totally trivial syntactic change: you call your function "my_connect()".

Wow. It's like magic. I added three characters, and made your whole reason for the crap that is C++ go away.

The thing is, the above is a really good example of why C++ is horrible, and why C is so simple.

Yes, the C solution is really simple. It's so simple that it looks downright stupid. But it's actually so simple that it is smart because quite frankly, it's a lot easier to get confused in C++ code, when the same function name means totally different due to overloading.

Of course, you're not "supposed" to overload things in confusing ways, but the thing is, just do what C does: just make your function names unique. It's not that hard, and by avoiding the overloading mess, you make it a lot easier to search for (hey look! "grep -w my_connect" just works!), and you avoid ambiguity.

(Same exact thing goes for your other example: just add a module prefix or have some other trivial naming rules for your functional split-up, and be happy)

Linus

C++ rants

By Linus Torvalds:

On Wed, 5 Sep 2007, Dmitry Kakurin wrote:
>
> When I first looked at Git source code two things struck me as odd:
>1. Pure C as opposed to C++. No idea why. Please don't talk about portability,
>it's BS.

*YOU* are full of bullshit.

C++ is a horrible language. It's made more horrible by the fact that a lot of substandard programmers use it, to the point where it's much much easier to generate total and utter crap with it. Quite frankly, even if the choice of C were to do *nothing* but keep the C++ programmers out, that in itself would be a huge reason to use C.

In other words: the choice of C is the only sane choice. I know Miles Bader jokingly said "to piss you off", but it's actually true. I've come to the conclusion that any programmer that would prefer the project to be in C++ over C is likely a programmer that I really *would* prefer to piss off, so that he doesn't come and screw up any project I'm involved with.

C++ leads to really really bad design choices. You invariably start using the "nice" library features of the language like STL and Boost and other total and utter crap, that may "help" you program, but causes:

 - infinite amounts of pain when they don't work (and anybody who tells me that STL and especially Boost are stable and portable is just so full  of BS that it's not even funny)

 - inefficient abstracted programming models where two years down the road you notice that some abstraction wasn't very efficient, but now all your code depends on all the nice object models around it, and you cannot fix it without rewriting your app.

In other words, the only way to do good, efficient, and system-level and portable C++ ends up to limit yourself to all the things that are basically available in C. And limiting your project to C means that people don't screw that up, and also means that you get a lot of programmers that do actually understand low-level issues and don't screw things up with any idiotic "object model" crap.

So I'm sorry, but for something like git, where efficiency was a primary objective, the "advantages" of C++ is just a huge mistake. The fact that we also piss off people who cannot see that is just a big additional
advantage.

If you want a VCS that is written in C++, go play with Monotone. Really. They use a "real database". They use "nice object-oriented libraries". They use "nice C++ abstractions". And quite frankly, as a result of all these design decisions that sound so appealing to some CS people, the end result is a horrible and unmaintainable mess.

But I'm sure you'd like it more than git.

Linus

=====

Heath Provost (galvanash@hotmail.com) on 6/5/10 wrote:
>
>As for C++ exceptions - the same thing really applies here.
>They are trying to write explicit code. Exceptions are the
>poster child for implicit magic...

Yes, exceptions is a good example. The Linux kernel actually does its own exception mechanism, exactly because that way we control what is going on (and do it much more targeted to the actual need in question while giving much better performance and avoiding the crazy unwinding issues).

And I really do dislike C++. It's a really bad language, in my opinion. It tries to solve all the wrong problems, and does not tackle the right ones. The things C++ "solves" are trivial things, almost purely syntactic extensions to C rather than fixing some true deep problem.

(The C++ objects, templates and function overloading are all just syntactic sugar. And generally bad syntax at that. And C++ actually makes the C type system actively worse.)

In non-systems programming, you should almost certainly use a language that offers garbage collection. That will possibly make a real difference in the complexity of your application. The C++ features? Largely useless, and just helps you screw up more.

And in systems programming, you're simply better off with C. You'll have a way easier time using all the existing code and libraries out there (re-using C++ code? Good luck). Fewer headaches, fewer opportunities to mess up the design and pick some unstable template library.

So in neither case is C++ likely the right choice.

Linus


June 4, 2013

excerpt from "effective c++"

   
Cpp is like some stubborn old man, who always says "i have lots of obscure habits, dealing with it"......

Lesson 4: the initialization is different from assignment, as well as their representations respectively. It is better to write the constructor as the form of initialization, named "initialization list", rather than just simply give the variables first assignment.

To avoid using objects before they're initialized, then, you need to do only three things. First, manually initialize non-member objects of built-in types. Second, use member initialization lists to initialize all parts of an object. Finally, design around the initialization order uncertainty that afflicts non-local static objects defined in separate translation units.

Lesson 7: declare destructors virtual in polymorphic base classes. C++ specifies that when a derived class object is deleted through a pointer to a base class with a non-virtual destructor, results are undefined. What typically happens at runtime is that the derived part of the object is never destroyed. Eliminating the problem is simple: give the base class a virtual destructor. Then deleting a derived class object will do exactly what you want. It will destroy the entire object, including all its derived class parts.

The purpose of virtual functions is to allow customization of derived class implementations. Any class with virtual functions should almost certainly have a virtual destructor. The implementation of virtual functions requires that objects carry information that can be used at runtime to determine which virtual functions should be invoked on the object. On the other hand, if a class does not contain virtual functions, that often indicates it is not meant to be used as a base class. When a class is not intended to be a base class, making the destructor virtual is usually a bad idea.

Lesson 9: Never call virtual functions during construction or destruction. Because during base class construction of a derived class object, the type of the object is that of the base class. Not only do virtual functions resolve to the base class, but the parts of the language using runtime type information (e.g., dynamic_cast (see Item 27) and typeid) treat the object as a base class type.

The same reasoning applies during destruction. Once a derived class destructor has run, the object's derived class data members assume undefined values, so C++ treats them as if they no longer exist. Upon entry to the base class destructor, the object becomes a base class object, and all parts of C++ treat it that way.

Since you can't use virtual functions to call down from base classes during construction, you can compensate by having derived classes pass necessary construction information up to base class constructors instead.

February 19, 2013

Set up Racket for Vim and mac Terminal

   
Racket is fairly great:), though the setting up procedure is kind of twisted. There is a .dmg installation file in the official website, which makes it quite straightforward to install in the Application folder. And, of course, the DrRacket app is awesome when I accidentally put mouse in one of the variables in the code, and then all its dependencies reveal via arrows.

But I am still used to writing code in vim and testing it in a parallel split window of iterm. I googled the solution, but cannot find a comprehensive one. So, I just list my solution here, which come from either stackoverflow or other persons' blogs.

1) vim syntax and highlight are out there ready for use.

2) Adding one command line to ~/.vimrc
 au BufRead,BufNewFile *.rkt set filetype=racket
3) Adding the path of executable racket to ~/.bach_profile.
export PATH=$PATH:/Applications/Racket\ v5.3.3/bin/
4) If using the existing file, one should delete the first line of code "#lang racket" if existed.

5) Optional. Installing rlwrap to make the repl more user friendly.

That is much of it.


cheers,

February 14, 2013

1st update in 2013

   
The issue came from my question in stackoverflow. Basically, it was a misplaced question, because the reason why my program would hit the "RuntimeError: maximum recursion depth exceeded" was that I just passed the sorted array by the first scenario to the second scenario. This caused the second one hit the "worse case" and exceed the "maximum recursion depth". Well... it was embarrassing to admit that I forgot dereferencing the variable...

But, anyway, the question concerning recursion in Python has been in my head for a while, even since I started learning Scheme. This time, the kind answer below my question shed lights on how to solve this kind of problem. Then I dug a little deeper and find more about tail recursion in Python.

The following is an example with problematic way to implement a recursion function:

def fac(n):
    return 1 if n < 2 else n * fac(n - 1)

> fac(3000)
> RuntimeError: maximum recursion depth exceeded

The right way to do this is to make a local helper function "tail recursive" with the help from anonymous function.

def fac(n):
    def f(n, acc):
        return acc if n < 2 else lambda: f(n - 1, acc * n)

    t = f(n, 1)
    while callable(t):
        t = t()
    return t

And an even elegant way is to use built-in function "reduce":

def fac3(n):
    return reduce(lambda x,y:x*y, xrange(1,n))
The latter two could deal with any input number. Tada~

A little extended reading about this topic:
Origins of Python's "Functional" Features
Tail Recursion Elimination
Tail Recursion Elimination in Python

Besides, studying Standard ML does give me much much more insights into both programming itself and programming in Python. Except the attractive tail recursion, Python has quite a few amazing features of functional programming.  In retrospect, now I appreciate more about what was listed in the "progression path", and of course, cannot wait to progress to Haskell.





cheers,

October 4, 2012

Install opencv in mac osx

The most straightforward way is via homebrew.
brew update
sudo brew install opencv

Then, all of the dependencies will be install with opencv. The reason to use "sodu" is because there will be twice "brew link" used in the process which could not link certain libraries without permission.

Finally, the brew gave a wrong file to update. Instead of updating .profile, the correct destination should be .bash_profile. Add this line:
export PYTHONPATH=/usr/local/lib/python2.7/site-packages/:$PYTHONPATH<\code>

That is it.


cheers,

September 17, 2012

missing you


小葛儿转眼安排好纽约面试就登飞机了。因为GPS的缘故,在机场周围转了好几圈,结果弄的再见都匆匆忙忙。送完她回到寝室——是的,没有了她,这里还是叫寝室合适——空荡荡的,安安静静。一分钟都不想多停留,背着书包就去了实验室。

晚上也不想回去,因为想到又是空空的房间就不自在。

一个人在这里。忽然一下安静了。多出了好多时间来想你,似乎一切记忆瞬间无比清晰,触手可及。你的肩膀软软的,抱在怀里的时候,还要告诉自己小心别把你弄疼了。你哭的时候,撅着嘴,鼻子里些许呜哝呜哝的声音,眼泪扑簌扑簌就落下来了。你笑的时候,眼睛眉毛嘴角都弯弯的,咯咯咯的,清脆悦耳。每到这个样的时候,我都在反问自己,为什么要和你吵架啊,有什么气好生呢。

可无论怎么吵架,我都还是爱你的,比每一次吵架前还要爱你,比每一次生气之前还要更想和你在一起。有时候会想,也许我太把你说的每句话当回事儿了,才会又好多的弄巧成拙。但翻回头来,我仍就欠你好多在一起的时光。

小葛儿啊。你的一举一动,一颦一笑,我都记在心里呢。欠你的那些时光,我也一定要都好好还你。快回来吧。有你在的地方,我就认为是家了。

我想你。

Days of our lives

Daisypath Anniversary tickers