Code Length Measured in 14 Languages
blog.wolfram.com
blog.wolfram.com
Consider that a few years ago, Reddit switched from Lisp to Python, not because they thought the latter was in any way a better language, but (in their own words) because of Common Lisp's "lack of widely used and tested libraries."[1]
How does Mathematica's ecosystem compare to those of the popular languages in this comparison?
--
http://reference.wolfram.com/mathematica/guide/Mathematica.h...
The Mathematica 'ecosystem' doesn't benefit much from OSS, but it does benefit from hundreds of smart engineers with diverse backgrounds who work on it full-time. And SW as benevolent dictator, vetting every design decision for consistency and elegance.
Don't write a web server in Mathematica -- it's not particularly well suited to that. But if you're writing natural language parsing, knowledge base infrastructure, and algorithmic content for something like Wolfram|Alpha, I can't imagine anything better to use.
Mathematica is too different from the rest. Or mathematically speaking, the intersection between the capabilities of Mathematica and Python for example is smaller than Python and C#
You can't have Mathematica serving a web site (for any non trivial amount of users) (WA has a lot of infrastructure to make it happen)
On the other hand try to calculate an integral over the gamma function in the complex domain, that's one line in Mathematica and how many I don't know in Python even using some libraries.
APL, has ratios of between 1 and 2 (IE a little longer than Mathematica, but over only 32 comparisons which is too few to be reliable).
Julia was also asked about, but there are only 9 comparisons which is certainly too few to be meaningful.
This is everything that's wrong with 'Java lovers' (even though it's in C#)
But then again more lines of code and function points to bill your customer
Upvotes to you if you clean up that example.
If you space a few lines of very expressive code out, you don't want that to penalize the results. Similarly, you don't want someone to cheat by just having one huge line.
Edit: I stopped reading when he started describing the fetching/parsing process. My objection is covered later on. Thanks to carlob for pointing this out.
I'll also note that being the best may actually be a bad thing. Perl can be quite succinct, but also quite noisy at times.
Similarly, while I'm a fan of K/J (and I pretty much guarantee that K is more succinct than Mathematica), I think that the code can be very difficult to read sometimes.
While the “Large tasks – Line count ratio” gives the most impressive result for Mathematica, I think that the “Large tasks – Character count ratio” is the really the fairest comparison.
You can be as terse or as verbose as you want in many languages (think forth, perl, apl).
If you want to do a meaningful comparison pick a non-toy problem and write a full sized application, something that in the worst language is a few thousand lines with a proper UI, a web app, a desktop application and a large simulation of something or other. You will still have to account for language gifts such as libraries or built-ins somehow.
And you tell the devs they get points for producing short code.
Then you can compare along several axis, performance, code maintainability (closely related to how easy it is to read) and so on.
That's useful data. This isn't, regardless of whether mathematica looks good.
edit: ok. point taken.
See this[0] for more info
[0] http://reference.wolfram.com/legacy/v5/Tour/MathematicaAsAPr...
There is no reason to think this looking at the website.
Since he uses median ratios, then a single spectacular ratio will not skew the results.
The part of the test set that people have actually provided Mathematica solutions for. There is every reason to believe that people are more likely to provide Mathematica solutions for problems that Mathematica is likely to be good at.
That I think is owed to Mathematica being an heir of LISP that implemented m-expressions so cleanly that M doesn't even feel like a homoiconic language. Most other LISP-derivates (like Clojure) stuck to s-expressions, which are historical baggage more than anything else. Some day I'm sure we'll get an m-expression version of Clojure.
Of course in practice one defines new DSLs quite often in Mathematica. And it comes with a variety of DSLs "built-in", mainly for user interface construction, vector graphics, mathematics, and statistical computations.
Disclosure: I too work for WRI.
Most of these apps come from people in the target market, but it's similar to the number of Excel spreadsheets that end up running surprisingly large companies. A "non-programmer" develops a bunch of macros and VBA code to make their job easier, and those "DSL" type capabilities become critical core aspects of the system.
One takeaway I didn't expect: Clojure is, on average, nearly as terse as Mathematica.
Also, has anyone actually used Mathematica for something aside from data processing? Like, any of the tasks you would normally use Ruby, C++, or Clojure for?
Definitely a confusing table.
I might not surprise you to know that most of the code in Wolfram|Alpha is Mathematica code. I don't know what kind of examples you have in mind when you talk about "Ruby, C++, or Clojure", but Alpha is probably the largest Mathematica based project in production.
Edit: Even if Mathematica isn't technically a DSL, it certainly seems to be geared heavily towards symbolic mathematics and data processing/visualization. My question is really, how does it fare outside its element?
As I said in response to mumrah, Mathematica is not a DSL. You might argue that a lot of 'library' counts as language in Mathematica, but not that you can't write general purpose applications.
You may be unfamiliar with the term "DSL." It refers to a language designed for solving a specific computational task.
This was, in fact, the stated goal of Mathematica. DSL does not mean the language cannot solve other tasks, only that it was meant for solving a specific one.
in this respect i think the name "Mathematica" does a disservice to the system. originally it may have been intended for math, but in its current form it's more like a general prototyping/presentation/construction system that makes thorough use of its capacity as a research platform
I think you reveal different things comparing line count and character count, and both miss what I'm looking for in a terse language: scanability.
A lot of the verbosity that annoys me with Java isn't really about number of lines -- it's bad, not particularly worse than any of the other languages descended from ALGOL. No, what makes Java worse than its cousins is the propensity to use English words, and often really long ones, in places where symbols would be easier to scan. "public class Foo extends Bar" is a lot of English text, and I have to read it all to separate out the tokens. "@interface Foo : Bar" makes it easier for me to see at a glance what's going on.
And don't get me started on wading through rotation.multiply(other_rotation).multiply(velocity).add(rotation.multiply(other_velocity)). That's technically one line, but that doesn't make it easy to read.
So winning on line count doesn't capture everything.
On the other hand, measuring characters biases you toward symbol heavy languages like perl or APL, and '$\="\n"' takes some picking apart, too.
I did think APL would win an outright terseness competition, though, by either metric. It's a shame it isn't on the list.
I agree with you about Java. I have a line on my screen that has 6 identifiers and is 99 characters long and it's not even a constructor call. One of many problems is long identifiers with similar names.
"public class Foo extends Bar" is a lot of English text, and I have to read it all to separate out the tokens. "@interface Foo : Bar" makes it easier for me to see at a glance what's going on.
I know it's a "throwaway" example in a comment, but the first example makes it quite clear what is requested. The second example, less so.Never mind the @interface declaration. If you're going to be writing or maintaining objc, you have to understand that. However, the x : y notation often leads to confusion. Does x extend y? Does y extend x?
It's probably not a big deal for someone who lives in one or two languages, as the knowledge is refreshed frequently. However, when you swing between, say, Haskell, Python, Ruby, C++, Java, or whatever, and maybe only touch objc when you need to update your iOS app to match your web app, then there's a cognitive hurdle because ':' doesn't have a clear interpretation.
Given its Smalltalk heritage and model of message passing, "@interface y subclass: x" (or "@interface x subclasses: y") would carry less of a cognitive load while perhaps being less verbose.
Again, this is only a superficial example, but choice of names or symbols is important in the language UI.
The organization of this post is strange -- a result, a long section about how to write a web crawler in Mathematica, and then about a dozen more different results. If you (like me) are inclined to tune out when you hit code, keep scrolling.
I'm mainly a Common Lisp user, does anyone who has used both care to share an opinion?
Clojure's combination of declarative idioms and highly functional idioms (to a greater extent than CL) lead to it being able to by default express certain things in a more terse fashion.
http://rosettacode.org/wiki/Factors_of_an_integer
Compare Common Lisp and Clojure here.
Common Lisp:
(defun factors (n &aux (lows '()) (highs '()))
(do ((limit (isqrt n)) (factor 1 (1+ factor)))
((= factor limit)
(when (= n (* limit limit))
(push limit highs))
(nreconc lows highs))
(multiple-value-bind (quotient remainder) (floor n factor)
(when (zerop remainder)
(push factor lows)
(push quotient highs)))))
Common Lisp in this case is relying heavily on mutation with push. It's not that much better than a typical loop in an iterative language like Python.Clojure solutions:
; Trivial version
(defn factors [n]
(filter #(zero? (rem n %)) (range 1 (inc n))))
Initial version just does a filter and a lambda across the sequence produced by range. inc so that it includes the final result. Pretty functional. ; Less trivial
(defn factors [n]
(into (sorted-set)
(mapcat (fn [x] [x (/ n x)])
(filter #(zero? (rem n %)) (range 1 (inc (sqrt n)))) )))
Now we're getting a little more clever, relying on mapcat, filter, a lambda, and range. ; Now with a for-comprehension.
(defn factors [n]
(into (sorted-set)
(reduce concat
(for [x (range 1 (inc (sqrt n))) :when (zero? (rem n x))]
[x (/ n x)]))))
http://clojure.github.com/clojure/clojure.core-api.html#cloj...Take a look at the other things that work across the seq'able data structures. Pretty powerful base set of idioms.
Okay, but lets provide a second opinion on these idioms. What about Haskell?
import HFM.Primes(primePowerFactors)
import Data.List
factors = map product.
mapM (uncurry((. enumFromTo 0) . map .(^) )) . primePowerFactors
Using a primes module for finding prime factors. Okay, isn't that kinda cheating Rosetta Code though? I was kinda hoping to find the equivalent of the Clojure code.And Mathematica?
Factorize[n_Integer] := Divisors[n]
FFS.I give up. These are dumb comparisons. Don't listen to this Wolfram post. At least the Common Lisp/Clojure code wasn't pointless.
Another thought from my experiences:
The only way I've seen to scale up the "expressiveness" in a programming language in a way that's generally applicable is to make it more declarative. I have mixed feelings about this.
Two primary ways of doing so are functional idioms for "iteration" and concatenative programming.
Things like juxt, mapcat, et al have their equivalents in languages like J, K, Factor, etc.
The only way to elevate yourself above loops and manually assigning intermediates is to flow the data through high-level descriptions of what you want.
Whether that takes the form of a concatenative or functional langauge depends on the coder.
OOP is more about scaling up procedural idioms so that state management and code reuse aren't a total Vietnam. They aren't really more "expressive" with the exception of some of the idioms Smalltalk tossed about.
All that's left otherwise is "ecosystem leverage" such as Mathematica exhibits here. That's not really about the semantics of the programming language, but it's still worth noting if the leverage is relevant to the problem you're solving.
(defun factors (n)
(loop for r upfrom 1 to n when (zerop (remainder n r)) collect r))
Clojure doesn't have much advantage in conciseness over CL here. It's just a matter of what approach the contributor chose to use.I'd like to see how much Mathematica code it'd take to write a compiler or web server.
the reason you don't see more general-purpose code written in Mathematica is simply because it's a proprietary environment. you can't share general-purpose programs that are written in Mathematica
Admittedly, there are bugs, and the performance is not as good as Mathematica, but a lot of progress has been made (For example, PyPy compatibility is planed for the upcoming release). Give it some time, and I think (hope) it will grow to fill this niche.
Also, The fact that Mathics is open, allows you to extend it (in Python for example) with minimal effort.
Disclaimer: I contribute to Mathics development in my free time. We are hoping to get more people involved!