Question

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.

Was it helpful?

Solution

#! 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.

OTHER TIPS

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.

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.

The 'trick' works in Python and Perl because # starts a comment in those languages, so the interpreter sees that line as a comment and ignores it. So for them, it's nothing special.

In Haskell, # does not start a comment, so it wouldn't normally work. However, GHC (perhaps also other implementations, if memory serves, hugs did it too) has a special case for shebang lines. If the very first line of a file begins with #!, it is treated as a comment. This deviation from the language specification has been incorporated exactly to make

$ chmod +x hello.hs
$ ./hello.hs

work. It does not work with javac because there's no special case built into that for shebang lines.

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

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.

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).

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top