News for hackers. Stuff that matters.
Re:C++ has become a scripting language by stinos on Wednesday October 16, 2013 @08:02AM (#6559098)
Would be great if somebody could post Python/Ruby/.. code here that achieves the same, just to compare. Even with all the C++11 additions it never felt like scripting to me, and I use it practically every day.

Small nitpcik to the author: please define variables when you're going to use them, not C-style all at the beginning of the function. It makes code easier to understand. It doesn't make the reader wonder 'hey what's this variable going to be used for' then having to crawl through all code underneath it. It creates code that's easier to refactor. Also, but more arguably for such a small sample: http://stackoverflow.com/questions/1452721/why-is-using-name...

Re:C++ has become a scripting language by crntaylor on Wednesday October 16, 2013 @08:21AM (#6559186)
Haskell:

  import System.Environment
  import Data.List

  main = do
    infile:outfile:_ <- getArgs
    input <- readFile infile
    writeFile outfile . unlines . sort . lines $ input
Re:C++ has become a scripting language by dmytrish on Wednesday October 16, 2013 @10:53AM (#6559965)
It's a bit odd way of matching items of a list, I'd prefer to specify it without any possible trailing items:

    [infile, outfile] <- getArgs
Also, the last two lines may be squeezed into one (though less readable):

    writeFile outfile =<< (unlines . sort . lines) `fmap` readFile infile
Re:C++ has become a scripting language by crntaylor on Wednesday October 16, 2013 @12:56PM (#6560734)
On your first point; I was matching the behaviour of the C++ program in the blog post, which allows any number of command line arguments but only uses the first two.

On your second point, I actually thought about writing the whole thing as

  getArgs >>= \a -> readFile (a!!0) >>= writeFile (a!!1) . unlines . sort . lines
but decided that that's exactly the kind of thing that gets Haskell programmers a bad reputation.
Re:C++ has become a scripting language by nightski on Wednesday October 16, 2013 @06:58PM (#6562610)
Agreed, it does and you made the right choice. But in reality once you know Haskell - bind is a very common operation and reading this version is very natural.
Re:C++ has become a scripting language by jackmaney on Wednesday October 16, 2013 @08:20AM (#6559177)
Here's a Perl example. This isn't optimally compact, but this is more or less how I would write a script like this if I had to put it into production at $work (maybe with an extra check to make sure that exactly two command line arguments were provided).

  use strict;
  use warnings;

  open my $read,"<",$ARGV[0] or die $!;
  my @lines = <$read>;
  close $read;
  open my $write,">",$ARGV[1] or die $!;
  print $write $line foreach my $line(sort @lines);
  close $write;
Re:C++ has become a scripting language by prakashk on Wednesday October 16, 2013 @05:56PM (#6562362)
Perl5 v12 and up:

    use v5.12;    # enables strictures
    open my $in,  "<", $ARGV[0];
    open my $out, ">", $ARGV[1];
    print $out sort <$in>;
Perl6:

    sub MAIN( $in, $out ) {
        spurt( $out, open($in, chomp => False).lines.sort.join )
    }
[EDIT: fixed typo in first example]
Re:C++ has become a scripting language by draegtun on Thursday October 17, 2013 @05:49AM (#6564385)
Here's a couple of interesting Perl alternatives:

  my @files = map { IO::File->new($_->[0], $_->[1]) || die $! } 
              ([shift, 'r'], [shift, 'w']);
  $files[1]->print( sort $files[0]->getlines );
  $_->close for @files;
And...

  use autodie;
  open my $out, '>', $ARGV[1];
  print {$out} sort do {open my $in, '<', $ARGV[0]; <$in>};
Re:C++ has become a scripting language by hsmyers on Wednesday October 16, 2013 @02:24PM (#6561258)
If version >= 5.10 you can drop the 'or die' and for that matter neither of the close statements are necessary(in any recent version).
Re:C++ has become a scripting language by danmaz74 on Wednesday October 16, 2013 @08:07AM (#6559111)
Ruby:

  array = IO.readlines ARGV[0]
  array.sort!
  File.write ARGV[1], array.join("\n")
edit: get input and output file names from command line
Re:C++ has become a scripting language by ollysb on Wednesday October 16, 2013 @08:28AM (#6559221)
If we want to golf it, it would probably just be

  lines = IO.readlines ARGV[0]
  File.write ARGV[1], lines.sort.join('\n')
certainly more readable than the C++ even if you're unfamiliar with ruby.
Re:C++ has become a scripting language by danmaz74 on Wednesday October 16, 2013 @08:33AM (#6559250)
Well, if you really want to golf it, you can just write:

  File.write ARGV[1], IO.readlines(ARGV[0]).sort.join('\n')
;)
Re:C++ has become a scripting language by Freaky on Wednesday October 16, 2013 @08:37AM (#6559278)
You're fired.

    IO.write(ARGV[1], ARGF.lines.sort.join)
Re:C++ has become a scripting language by Aaronneyer on Wednesday October 16, 2013 @08:53AM (#6559349)
Here's the shortest I've gotten after looking at some of the comments:

  IO.write$*.pop,ARGF.lines.sort.join
And yes, it does work even without the space between `write` and `$*`.

Also after testing, I realized the ('\n') is not required for join. When you call 'lines', it still has the '\n' character in the string, and when you join, it defaults to join without a delimiter, so it's putting them back together with the newline still there.

Re:C++ has become a scripting language by danmaz74 on Wednesday October 16, 2013 @08:48AM (#6559333)
Wow, this is really sweet and esoteric (didn't know about ARGF) - but, reading the docs for ARGF, wouldn't it also try to ready from ARGV[1]?

Maybe this would fix it:

  IO.write(ARGV.pop, ARGF.lines.sort.join('\n'))
Re:C++ has become a scripting language by Freaky on Wednesday October 16, 2013 @09:54AM (#6559620)
Yes, good catch. join('\n') is wrong though - IO#lines preserves newlines, the default join is the empty string, and you meant "\n" :)
Re:C++ has become a scripting language by danmaz74 on Wednesday October 16, 2013 @11:14AM (#6560089)
:)
Re:C++ has become a scripting language by Aaronneyer on Wednesday October 16, 2013 @08:48AM (#6559332)
I believe you still need to join on newline, the default is space. However you can save a couple characters by using `$*` instead of ARGV.

Also, trim out the space between the arguments and kill the parenthesis for the optimal golfing.

Re:C++ has become a scripting language by trentmb on Wednesday October 16, 2013 @08:38AM (#6559284)
Is

> File.write ARGV[1], (IO.readlines ARGV[0]).sort.join('\n')

not valid Ruby?

Re:C++ has become a scripting language by rofrol on Wednesday October 16, 2013 @12:14PM (#6560461)

  File.open(ARGV[1], 'w') { |file| file.write(File.read(ARGV[0]).lines.sort.join) }
http://stackoverflow.com/questions/8278680/ruby-undefined-me...
Re:C++ has become a scripting language by hamidr on Wednesday October 16, 2013 @08:25AM (#6559210)
The thing is in ruby you are already in main method so there's no need to declare main function as an entry point. The main reason that the c++ version the code is longer has some historical/performance related issues! In c++11 it could've been with smaller standard library at design but that could break the old codes! Although obviously, "Little code =! Better code". What you want to achieve is actually more important. Btw, C++ as a scripting language? at first you might think that way but truly that's a big lie :)
Re:C++ has become a scripting language by danmaz74 on Wednesday October 16, 2013 @08:31AM (#6559233)
I'm not arguing with that ;)

BTW, I would never use Ruby for anything that needs performance, but for ease of use and readability it's really great.

Re:C++ has become a scripting language by stinos on Wednesday October 16, 2013 @08:11AM (#6559127)
Now that's the succinctness I'd expect from an actual scripting language
Re:C++ has become a scripting language by adestefan on Wednesday October 16, 2013 @08:17AM (#6559165)
Except that's not what the C++ code does. The C++ reads and writes from files given as command line arguments.
Re:C++ has become a scripting language by danmaz74 on Wednesday October 16, 2013 @08:23AM (#6559197)
Fixed
Re:C++ has become a scripting language by adestefan on Wednesday October 16, 2013 @08:35AM (#6559265)
Thanks. I know enough ruby to be dangerous so didn't know if more needed to be done than that simple substitution.
Re:C++ has become a scripting language by vjoel on Wednesday October 16, 2013 @04:17PM (#6561894)
Or:

   ruby -e 'puts ARGF.sort' file.txt
Also, this reads stdin if the argument is omitted.
Re:C++ has become a scripting language by ctz on Wednesday October 16, 2013 @08:20AM (#6559183)
> Would be great if somebody could post Python/Ruby/.. code here that achieves the same, just to compare.

It's actually really hard to completely rewrite that program in most scripting languages: they tend not to have the same concept of undefined behaviour.

'sys.argv[2]' in python (with sys.argv = ['thing.py']) is fully defined (raises an IndexError). 'argv[2]' in C++ (with argv = (char*[2]) { "./thing", 0 }) is undefined.

If you scripting language has an FFI library (ctypes in python, say) then you could probably do something equivalent.

Re:C++ has become a scripting language by stinos on Wednesday October 16, 2013 @08:28AM (#6559220)
good point about the UB. Together with shin_lao's comment about the error/exception handling bascially sums up why the author's claim only makes some sense, but not a lot.
Re:C++ has become a scripting language by mikeash on Wednesday October 16, 2013 @05:46PM (#6562331)
Defined behavior is a subset of undefined behavior. Specifically, "raises an IndexError" is a perfectly legal thing for a C++ implementation to do in this case. Approximately zero real world implementations do this, but nothing says they can't.
Re:C++ has become a scripting language by MereInterest on Wednesday October 16, 2013 @08:13AM (#6559138)
Python:

    import sys

    data = open(sys.argv[1]).readlines()
    data.sort()
    open(sys.argv[2],'w').write(''.join(data))
Re:C++ has become a scripting language by benhoyt on Wednesday October 16, 2013 @07:29PM (#6562727)
Not bad, however with the ''.join(data) you're effectively doubling the amount of memory needed for large files, because it will build the entire output string in memory (and you've already got the list in memory). Better to use writelines(). You can also use sorted() to iterate over and sort the input lines automatically:

   sorted_lines = sorted(open(sys.argv[1]))
   open(sys.argv[2]).writelines(sorted_lines)
Re:C++ has become a scripting language by ygra on Wednesday October 16, 2013 @08:21AM (#6559187)
PowerShell:

  function Sort-File ($Path, $Destination) {
    Get-Content $Path | Sort-Object | Out-File $Destination
  }
Granted, shells are probably at an advantage when it comes to file management. I'd think a bash variant would be quite short as well.

Aiming for succinctness by using aliases and using redirection instead of cmdlets for writing the file (shorter, but less flexible):

  function sf { gc $args[0] | sort > $args[1] }
That's not code anyone should write outside code golfing, though ;-)
Re:C++ has become a scripting language by MereInterest on Wednesday October 16, 2013 @08:26AM (#6559214)
Yeah, the bash variant is obscenely short as well. Short enough that it isn't worth having as a separate program.

    cat in.txt | sort > out.txt
Re:C++ has become a scripting language by femto on Wednesday October 16, 2013 @08:36AM (#6559269)
Curious, in case I'm missing something. Is what you've written equivalent to the following, or is there a reason for the pipe?

sort in.txt > out.txt

Re:C++ has become a scripting language by Someone on Wednesday October 16, 2013 @02:38PM (#6561321)
For those that don't know: there is/was an ancient meme called the "Useless Use of Cat Award" about that subject. See for instance http://en.wikipedia.org/wiki/Cat_(Unix)#Useless_use_of_cat, http://partmaps.org/era/unix/award.html, or http://unix.stackexchange.com/questions/16279/should-i-care-...
Re:C++ has become a scripting language by MereInterest on Wednesday October 16, 2013 @08:43AM (#6559310)
From the other comment, it is completely equivalent, and I will admit that the pipe is due purely to my ignorance. I usually use `sort` for sorting the output of other commands, and so I forget that it can open a file on its own.
Re:C++ has become a scripting language by reycharles on Wednesday October 16, 2013 @12:45PM (#6560665)
That usage of cat is "wrong" in general:

    cat file | command > out
is the same as

    command < file > out
Re:C++ has become a scripting language by rat87 on Thursday October 17, 2013 @03:13AM (#6564037)
Don't worry about the cat it does have a purpose: portability. cat in.txt | sort > out.txt works in powershell(cat is an alias for Get-Content and sort is an alias for sort-object)(without the sort it wouln't work).
Re:C++ has become a scripting language by 1_player on Wednesday October 16, 2013 @08:32AM (#6559244)
No need for cat!

    sort in.txt > out.txt
Re:C++ has become a scripting language by skriticos2 on Wednesday October 16, 2013 @08:43AM (#6559313)
We are talking about a script, so it should be:

cat $1 | sort > $2

Re:C++ has become a scripting language by z92 on Wednesday October 16, 2013 @08:19AM (#6559173)
PHP:

    <?
    $lines=file($argv[1]);
    sort($lines);
    file_put_contents($argv[2],implode("\n",$lines));
Re:C++ has become a scripting language by rlpb on Wednesday October 16, 2013 @08:31AM (#6559240)
Unix shell:

    sort
Re:C++ has become a scripting language by Vodurden on Wednesday October 16, 2013 @06:12PM (#6562431)
Another way to do it in C++ is:

  #include <iterator>
  #include<vector>
  #include<algorithm>
  #include<fstream>

  using namespace std; // Bad but shorter!

  int main(int argc, char** argv) {
      ifstream infile(argv[1]);
      ofstream outfile(argv[2]);
      ifstream_iterator<string> start(infile), end;
      vector<string> lines(start, end);
      sort(lines.begin(), lines.end());
      copy(lines.begin(), lines.end(), ostream_iterator<char>(outfile, "\n"));
  }
Re:C++ has become a scripting language by lzman on Wednesday October 16, 2013 @08:41AM (#6559304)
>Small nitpcik to the author

ifile, line and data have to be defined before the loop. ofile could be defined closer to usage, but I think it's much clearer where it is, grouping in and out defs together making it obvious how argv is used for each.

Re:C++ has become a scripting language by draegtun on Thursday October 17, 2013 @05:15AM (#6564311)
In Rebol:

  Rebol []

  files: map-each n system/options/args [to-file n]
  write/lines files/2 sort read/lines files/1
Re:C++ has become a scripting language by ptx on Wednesday October 16, 2013 @08:28AM (#6559223)
Python (assuming that the last line ends with a newline):

  import sys
  open(sys.argv[2], "w").writelines(sorted(open(sys.argv[1])))