For an example, look at GHC versus some toy-Haskell whipped up in Common Lisp. Now, with those two implementations to hand, is Haskell 'fast' or 'slow'?
For an example, look at GHC versus some toy-Haskell whipped up in Common Lisp. Now, with those two implementations to hand, is Haskell 'fast' or 'slow'?
Theoretically, maybe. But it is nearly impossible to come up with an implementation for Ruby, that is as performant as a compiled C program (and retains the characteristics of Ruby).
So, it is definitely true that it easier to compile some languages to fast machine or byte code than other languages. As a consequence, people will call Ruby slow, and C fast.
PyPy is getting there.
JIT, Runtime type detection and path optimization go a long way. And it's much easier to write correct Ruby than correct C.
When I went to college, the HP-41 was HP's top-of-the-line calculator and all the rich kids had them. I had a BASIC-programmable CASIO PB-700. In the end, I was able to finish tests in less time than it took the HP guys to program their calculators to spit the answer. I think it was the first time (1986 or so) I realized a more expressive programming language could be a decisive advantage over your competition.
No, it isn't. C may be spartan, but its failure modes are predictable and manageable. A ruby program can be incorrect for a host of reasons completely unrelated to the program (interpreter bugs, garbage collection problems, etc.) and the language as a whole provides features (dynamic typing, method injection, exceptions) that make it harder to write correct programs.
Ruby may make it easier to write programs, but it definitely doesn't make it easier correct programs.
...on some be benchmarks. It's not near the stage when it beats C or C++ in general.
And it's much easier to write correct Ruby than correct C.
C is not very type safe, but there are languages that are and have comparable performance to C (Ada, C++, etc.).
That's not entirely true. A language semantic limits the possible implementations.
And yes, I know about the sufficiently smart compiler. ;)
The languages mentioned in this blog post present an interesting sort of in-between case though, since at some level you could almost regard them as being a collection of implementations of the same language (Lisp), rather than as actually distinct languages. I realize that's stretching some definitions a bit, but I think there's kind of a continuous spectrum there between "different language" and "different implementation of the same language". I mean, GCC implements extensions to C that aren't in the C standard and aren't (to my knowledge) supported in, say, MSVC; some refer to this as "GNU C", though I'd guess most non-language-lawyers looking at it would probably still call it "C" anyway.
On the whole though, I agree with you.
main = putStrLn . show . sum . take 3000000 $ repeat 1
(Ignoring the random generation, that does not play a role here, does it?)What if random generation played a role, how would that look and what times do you get, just curious?
putStrLn =<< show . sum . take 3000000 . randomRs (0, 100::Int) `fmap` newStdGen
::Int is necessary to nail down exactly which numeric type we're dealing with, as nothing else in the expression nails down an exact type.Personally I prefer loading Control.Applicative and using <$> where the `fmap` is, but I thought I'd keep the dependencies low. This demonstrates both how adding IO to an expression can be a bit of a pain, and that Haskell has come up with tools to deal with this without turning it into the naive "do" block with three or four lines a newbie would turn out.
I wouldn't expect miracles on the random number generation speed. Also in this context you may not be getting the best optimizations that you would get if you really cared. It so happens that Real World Haskell uses a virtually identical example in its optimization chapter, where by the end they get down to what is essentially the optimal non-SIMD assembler, if you're really interested in the dirty details: http://book.realworldhaskell.org/read/profiling-and-optimiza...
putStrLn =<< show . sum . take 3000000 . randomRs (0, 100::Int) `fmap` newStdGen
That is truly beautiful. >> tic;sum(rand(1,3e6));toc
Elapsed time is 0.059096 seconds.However, a language will impose some limitations on the implementation, be it a compiler or an interpreter. Dynamic typing is perhaps the most concrete example of this.