views:

441

answers:

8

I can do something like this in Haskell:

#!/usr/bin/runghc
main=putStrLn "Hello World"

Then I can run it with ./hello.hs

My question is, why is the first line ignored? Comments in haskell start with -- but the first line still seems to be ignored. It even loads in ghci. The trick also works with Python and Perl.

But when I do something similar in Java:

#!/usr/local/jdk1.6.0_13/bin/javac
...

Javac gives me a compiler error.

So how does this work and how would I get it to work with Java?

Thanks.

+3  A: 

If your file is hello.hs, and the first line is "#!/usr/bin/runghc", then the shell will execute:

/usr/bin/runghc hello.hs

That first line basically tells the shell what to use to run the script.

As for the java example, the first line should be the executable that runs the script, not that compiles the script.

Tom Dalling
substitute "shell" for "terminal" and you got it right
ennuikiller
+1  A: 

The shebang only works with interpreted languages....it generally means nothing to a compiler which will error out in most cases

ennuikiller
A: 

The reason that this works is because Python, Perl, and apparently Haskell, are all interpreted languages. It is the standard Unix way to designate the interpreter that will run the script. Java is a compiled language, and can't be run with an interpreter.

bluejeansummer
A: 

Javac is a compiler, not an interpreter.

It lacks interactive mode which I believe is what is causing the 'magic'. The same will not work with GCC since it lacks the same feature.

dmd (The D compiler) for example, is an example of a compiler that supports interpertation has this kind of interactive editing (#!/usr/bin/dmd -run).

LiraNuna
+1  A: 

On interpreted languages it tells the terminal what kind of script it is, (and so what program to run it through to execute it)

It is probably a special case in the Haskell interpreter, I know it is in the PHP interpreter.

It won't work in Java because it is not interpreted, you must compile the code before you can execute it, so telling the terminal what kind of script it doesn't make sense, so Java does not have a special case for it.

asperous.us
A: 

It is the location of the executable on your computer to interpret your script. Java is a compiled language, thus it does not need such a statement.

Furthermore, the point is that it is a special comment, the construction in Java would not be legal in that way as a # is not a legal comment marker. If a construction like that would make sense... which it doesn't... it would look like:

//!/usr/local/jdk1.6.0_13/bin/javac

NomeN
+10  A: 

#! is named "shebang" and is a Unix way of executing scripts. When you ask the OS to execute a file it'll figure out that this is not a normal .exe file, and the #! at the start serves as a magic marker which instructs the OS to execute the command after the #! and wiring up that command so this file becomes an argument of that command

if myfile.py contains

#!/usr/bin/python

executing that file is not very different from running

$ /usr/bin/python myfile.py

My Haskell knowledge is poor. But for your particular case it seems the runghc command simply reads the first line, parses any arguments given on that #! line, writes the rest of the file to a temporary file and runs ghc on that temp file(which will have the first lien stripped out - see runghc.hs in the ghc sources for more info.)

If you wanted to do the same thing with javac you could use the same approach as runghc. Write a wrapper, that eats the first line of the file, writes the rest of the file to a temp file and runs javac on that file.

nos
The text file does not become standard input. The original command line (possibly with path information added to the name of the text file) is appended to the command found on the shebang line. The original standard input remains the standard input for the expanded command.
Dave Hinton
Yea, sorry. corrected that.
nos
Disclaimer: I know little Java. But is #foo a comment in Java? I know it is (purposely so) in most of the scripting languages on *nix so that you don't have to worry about stripping off the first line.
Matthew Scharley
# is not a comment in Java, java follows the C/C++ style with /**/ and // comments
nos