Hacker News new | past | comments | ask | show | jobs | submit login

> Ignoring include boilerplate and the like leaves us with roughly ten lines of code.

I'm not sure you get to claim a language is a scripting language and then ignore the boilerplate.

The equivalent python is 4 lines, just one more than the number of steps you're performing.

  import sys
  data = open(sys.argv[1]).readlines()
  lines = sorted(data)
  open(sys.argv[2], 'w').writelines(lines)
C++ is good at many things, but quickly creating readable scripts and live-coding with a REPL are not among them.



In Unix shell makes it in 2, with the bang line:

  #!/bin/sh
  sort < $1 > $2
My preferred scripting language ;)


Requisite C# one-liner:

  Main(string[] args) { File.WriteAllLines(args[1], File.ReadAllLines(args[0]).OrderBy(x => x).ToArray()); }
Excludes using statements, .net library references. project file, solution file, framework config file...

I have invented a language called Croml, in which all source code compiles to the same program. This program reads in a file, sorts the lines, and writes it back out to another file. An empty source file accomplishes this task.


You are cheating because of all the menus you had to jump through just to make the project :-)


Use LinqPad then it's not cheating. It becomes:

File.WriteAllLines(args[1], File.ReadAllLines(args[0]).OrderBy(x => x));


I did actually use LINQPad. My comment was in jest :P

However, there's no Main in LINQPad which takes string[] args. Also File.WriteAllLines takes an array as its second parameter, while OrderBy returns an IEnumerable.


Don't forget the quotes...

    sort < "$1" > "$2"


It'll work on files (much) larger than RAM, too.


Absolutely yes, up to the point you're working with text. When objects (either implicit or explicit) start to interact with each other, shell scripting falls short quickly.


'Text' covers a very large domain. Once you get any data to a ordered text form, Unix command line text processing utilities have literally zero competition when it comes succinctness, power and how quickly you can create solutions.

Utility of shell goes down. Not because problems are represented as 'Text', but rather shell languages lack features like exception handling, proper error checking and many other things- Which make it difficult to write large programs in it.

As a next extension, you can learn Perl.

I assure you, after that you will not need anything ever.


> I assure you, after that you will not need anything ever.

I love it when people say things like this. As is their domain is the only domain in all programming.

For surely, you could write a competitive web browser in Perl. Or a first person shooter. Or a telecom system. Or a mars orbiter.

It makes you wonder why anyone ever invented anything else!


I read his post to mean he is talking about the 'Text' domain of things, not everything. He claims you won't want anything beyond Perl if/when you stick to handling text.


Oh. On re-reading, that makes sense. I recant my snark.


I don't actually agree with him but I just wanted to thank you for posting the recant. :)


You know if this kind of thing keeps happening on the internet I might just have to start counting on my toes.


I like perl because of how it looks similar to php, and because it looks similar to php, the structure is somewhat like C. I am not sure how good Python is at text manipulation, but I'll bet it is similar to perl and can do, if not all the things perl can, most things perl can.

Languages I know are: C, Objective-C, Perl, PHP, Javascript, and bash. Languages I played in: Python, Ruby, C++, C#, lua, go.

I want to learn C++ as it has very good cross platform stuff. But don't know when to start. I want to learn python so I can help with mailpile, but don't know when to start. I want to learn go as I want to write my own chat protocol, but don't know when to start.

I am not biased with languages, I just don't know other languages and can't give a pros/cons comparing between them.


> When objects (either implicit or explicit) start to interact with each other, shell scripting falls short quickly.

Not with PowerShell! PowerShell is amazing in how it takes the text pipe model of working and extends it to general purpose objects.

(Having access to all those .NET libraries is a nice bonus!)


you don't need hashbang if you run it the same like python:

  sh script.sh
  python script.py
So one line vs two lines

  import sys
  open(sys.argv[1],'w').writelines(sorted(open(sys.argv[2]).readlines()))
Yep, bash is more readable for small scripts


> Yep, bash is more readable for small scripts

I don't agree with that, in my opinion bash is more coincise while python is far more explicit and thus more understandable.

Python is not meant to be written in one line; the script could be rewritten in a readable way like this:

  import sys
  
  inp = open(sys.argv[1], 'r')
  out = open(sys.argv[2], 'w')
  
  out.writelines(sorted(inp))


This is my favorite python implementation in this thread. I daresay it's beautiful.

Including whitespace it's still half as long as the "11 line" core of the C++ script.

There's an unnecessary 'r'. Combined with the line rhythm established by opening the files in consecutive lines you ensure readers who would have been confused by the 'w' will quickly understand.

And the last line reads like programmer English; by which I mean English with a SVO word order. Not intuitive to the average person but quite parsable by anybody who's used a modern imperative language.

I can't even nitpick your choice of inp instead of input, the rhythm you setup and the contrast with 'out' means it's quite obvious what you mean.

Have an upvote.


English is usually SVO; I assume you meant OVS?


Obligatory functional style:

    import sys

    reduce(lambda i, o: o.writelines(sorted(i)),
           map(lambda args: open(*args),
               zip(sys.argv[1:], ('r', 'w'))))
If Guido didn't despised FP so much maybe we could get a nicer lambda syntax... but here's anyway.


In my opinion using reduce, map and zip is not a good idea in this case. What are they needed for? I don't even think your approach is more functional than the examples above.

I mean, this one line should be equally functional and .. it's shorter and even more understandable:

  open(sys.argv[2], 'w').writelines(sorted(open(sys.argv[1]))
(Btw you're talking about a nicer lambda syntax but imho your example looks ugly because of all the unneeded stuff you've put into it)


faster too

  $ time sort < t > t-sh
  real    0m0.016s
  user    0m0.008s
  sys     0m0.008s

  $ time py -c "import sys; open(sys.argv[1],'w').writelines(sorted(open(sys.argv[2]).readlines()))" t-py t
  real    0m0.088s
  user    0m0.056s
  sys     0m0.012s
BTW also a different result (I curled this page for the data).


It is faster mainly because of the startup time of the python interpreter. You can improve performances using the "-S" on the python interpreter. I get inconsistent results with time, I think maybe because of context switching as stated here [1].

See my results here: http://pastebin.com/HMUErzee

1: http://stackoverflow.com/questions/9006596/is-the-unix-time-...



I may be wrong but I think that this is actually spawning a subprocess and thus is not an exact translation of the python example.

This bash script rewritten in python should be something like this:

  import subprocess, sys
  
  inp = open(sys.argv[1], 'r')
  out = open(sys.argv[2], 'w')
  
  sys.exit(subprocess.call('sort', stdin=inp, stdout=out, stderr=sys.stderr))

(I don't know why but it seems that the performance of this version are worse than the original proposed example with writelines/readlines)


So what? The Unix Shell library consists of all the executables that are on the system - for me this is the beauty. There is not much of abstraction between the Unix Shell and the system under it. And shell is very tolerant to other programing languages as well - as long as they allow to represent data in text form and through streams or files ;)


Yes, I know that this is the correct way of doing it in bash. I posted this because someone might test the speed of the two scripts and conclude "bash is faster" while they actually measured the speed of "sort" probably.


Microbenchmarks are a distraction. Macrobenchmarks matter.

The real problem with bash is the mess you get when you start needing whitespace or arrays or error handling or non tabular objects or a computation not already implemented as a system program.


It doesn't have to spawn a subprocess. Some shells (like those in Busybox and Toybox) reduce common POSIX userland tools to a function call.


Right. And even it was implemented as a subprocess, it's still idiomatic shell code, i.e. what you would Actually Do.


You can even just write

  lines = sorted(open(sys.argv[1]))
since Python files act as iterators over lines.


Well, if you want a REPL for C++, there is always ROOT. Though, for the love of all that is holy in this world, I don't know why they chose to have a REPL for C++. Or why they chose the profoundly ungoogleable name of "ROOT".


If you instead search for 'root CERN' the first result is the following:

http://root.cern.ch/drupal/


It is actually called CINT.

http://root.cern.ch/drupal/content/cint


Or one liners:

import sys; open(sys.argv[2], 'w').writelines(sorted(open(sys.argv[2], 'w').writelines())

(use-package :com.informatimago.common-lisp.cesarum.file) (setf (string-list-text-file-contents outpath) (sort (string-list-text-file-contents inpath) (function string<)))

Indeed, what kills languages like C or C++11 in the scripting domain, is the need for declarations and other kind of boiler plate. That said, with C++11 there are means to write a library requiring less declarations, but it's still a cultural problem (beside the hard work that it would require).


Your first example is erroneous - perhaps a good example of why you shouldn't try to squeeze everything into a single line of code :)

    import sys
    src = open(sys.argv[1])
    dest = open(sys.argv[2], 'w')
    dest.writelines(sorted(src))


It's not really boilerplate in the classical sense, he's just talking about headers and lines that have only a brace on them. I think it's a fair statement.

Plus, he could have reduced lines even further to get down to about 6, like

   vector<string> data;
   string line;
   for (ifstream ifile(argv[1]); getline(ifile, line);)
       data.push_back(line);
   sort(begin(data), end(data));
   copy(begin(data), end(data), ostream_iterator<string>(ofstream(argv[2]), "\n"));
And his `return 0` was superfluous so I removed it.

Unfortunately we work with iterator pairs in C++; if we had ranges like D does, we could turn those last two into

   copy(sort(data), ...)
but alas we cannot.


You could use boost::range to make it even more succinct


Once you remove the redundancy, you'll see it is pure information!




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: