23
\$\begingroup\$

The Challenge

Write a program that outputs Hello World, from line X!, where X is the line number, in the source code, of the actual print statement itself.

The Rules

  • In this context, we want the first line number of the statement which outputs the string to be displayed to stdout
  • You should avoid simply searching through your source code as a string (either file or quine) to find the line number
  • If any additional whitespace or statements (which do not interrupt the flow of the code) is added to the source code, it should be reflected at run-time (after compiling if applicable)

Recommendations

If provided by the language, you may use exceptions/stack traces to accomplish this goal. Try your best to use code that is portable across different systems/implementations, but note that this is not a requirement. Using defined variables like __LINE__, although allowed by the rules, are discouraged.

The Winner

  • This is a popularity contest (ended on June 10, 2014), where the answer voted highest by the community will be declared the winner based on the current votes at the time

  • When voting, please consider the creativity of someone's answer, how elaborate or interesting it is. and the difficulties/constraints of the programming language being used

\$\endgroup\$
10
  • \$\begingroup\$ What do you mean by "the first line number"? Are you talking about what should happen if the statement spans multiple lines? \$\endgroup\$ Commented Jun 4, 2014 at 1:34
  • \$\begingroup\$ @user2357112 yes, just to resolve any ambiguity if anyone needed to use a milti-line statement. \$\endgroup\$ Commented Jun 4, 2014 at 1:58
  • \$\begingroup\$ The title is very explicit, but perhaps a bit long. \$\endgroup\$
    – primo
    Commented Jun 4, 2014 at 5:11
  • 1
    \$\begingroup\$ The answers to this are all boring because it is such a bad question. It is like the asker didn't know of the existence of LINE. In fact I signed up specifically to down vote this I thought it was so bad. \$\endgroup\$
    – dave
    Commented Jun 4, 2014 at 14:26
  • 1
    \$\begingroup\$ @Markasoftware if a line was added before it, the output wouldn't change to reflect that. \$\endgroup\$
    – primo
    Commented Jun 6, 2014 at 1:00

44 Answers 44

1
2
2
\$\begingroup\$

Inspired by @squeamish ossifrage's answer with BASIC.

What's in a line number?

In, for instance, IBM COBOL there are (can be) arguably three source line numbers.

The first (if used, it is optional), in columns 1-6 of the punched-card, are sequence numbers for the card deck. If the deck is dropped, the otherwise-hapless programmer has some chance to get things back in order. OK, starts to go slightly floppy as soon as the program has lines added, but that's what different coloured cards are (can be) for.

The second is on the compiler listing, generated by the compiler. The compiler diagnostic messages use this line number, else no-one would have much of a clue (unless the diagnostics are embedded, which they can be) which line any particular diagnostic referred to*. These numbers for various reason (copybook code, let alone anything else) will be different from the first.

The third line number is of course the line number of the actual source file (optional, columns 73-80 if present). Other than actually reading the source file, or hard-coding a reference to a particular source line-number, it would not be possible to get this number in a program***.

So:

999999     DISPLAY "Hello, world, from line 999999!"

This can appear anywhere in the PROCEDURE DIVISION of the program, since those line numbers have no affect on the program, and are only even flagged as out of sequence (not ascending, can be gaps) if requested by compiler option.

** With compiler options SEQUENCE and NUMBER, the column 1-6 numbers will be used (modified by the compiler if necessary) for the diagnostic messages, and other data requiring source line numbers.

* OK, possible in limited circumstances. No copybooks. Then you get the editor to put the sequence numbers of the source program (yes, we have actual sequence numbers, not just counting the lines) in columns one to six, and use compiler options SEQUENCE and NUMBER and then have a DEBUG DECLARATIVE, have the DISPLAY on the same physical line as the paragraph/SECTION which is going to cause the DEBUG DECLARATIVE to execute.

\$\endgroup\$
2
\$\begingroup\$

Nimrod

template lineno(): expr = instantiationInfo().line
echo "Hello, world, from line ", lineno(), "!"

It uses Nimrod's templates to generate a call to instantiationInfo, whose information is only valid when used from within a template.

Output:

Hello, world, from line 2!
\$\endgroup\$
2
\$\begingroup\$

C#

using System;
using System.Runtime.CompilerServices;
namespace LineNumber
{
    class Program
    {
        int getLn([CallerLineNumber] int x){ return x; }
        public static void Main()
        {
            Console.WriteLine ("Hello World, from line " + getLn() + "!");
        }
    }
}
\$\endgroup\$
2
\$\begingroup\$

There is more than one way to do it (Perl 5)

The boring way:

print "Hello World, from line ", __LINE__, "!\n";

A fancier way:

sub println { print @_, ", from line ", (caller)[2], "!\n" }

println "Hello World";

A sneaky way:

eval {
    die "Hello World";
};

print $@ =~ s/ at .* (line \d+)\./, from $1!/r;

An even sneakier way:

$SIG{__DIE__} = sub { exit print $_[0] =~ s/ at .* (line \d+)\./, from $1!/r };

die "Hello World";

The really sneaky way:

package Magic {
    use Filter::Simple sub { s/42/\${\\__LINE__}/g };
}
BEGIN { import Magic }

print "Hello World, from line 42!\n";
\$\endgroup\$
1
\$\begingroup\$

PHP

Shamelessly stolen from gnibbler

<?php
printf("Hello World, from line %d!", __LINE__);

Working example

\$\endgroup\$
1
\$\begingroup\$

ECMAScript (JavaScript):

alert('Hello World, from line ' + Error().lineNumber + '!');

Hello World, from line 1!

Note: I've only tested this in Firefox and Opera 10.


This should work in all current browsers:

alert('Hello World, from line ' + /^.*?@.+?:(\d+)(:\d+)?\r?\n/.exec(Error().stack)[1] + '!');

Hello World, from line 1!

\$\endgroup\$
1
\$\begingroup\$

POSIX SHELL:

I was going to do $LINENO but it's been done. So I'll ask an interactive POSIX-compatible shell to printout its current history line number instead:

HISTFILE= PS1='${hi}$(printf "${hi:+\!!!\n}> ")' sh -i
> hi=${on='Hello World, from line '}${off=}
Hello World, from line 2!
> hi=$off
> hi=$on
Hello World, from line 4!
>

Though it may not look like it, the shell is actually reevaluating and printing anew that $PS1 variable for every command it receives - else it wouldn't even work - so the print statement actually is printing its own line number every time it prints and not just the first.

\$\endgroup\$
1
\$\begingroup\$

x86 Assembly

.data
LC0:
    .ascii "hello, world! from address %x\n\0"
.text
    .global main
main:
    pushl   %ebp
    movl    %esp, %ebp
    call pop

pop:
    popl    %ebx
    leal    22(,%ebx,1), %ebx
    subl    $8, %esp
    movl    %ebx, 4(%esp)
    movl    $LC0, (%esp)
    call    printf
    movl    $0, %eax
    leave
    ret

This prints the memory address where the call to printf is located. This doesn't really work for rule 3, but I feel it's much more interesting than using __LINE__ or a stacktrace.

I should add how it works. Normally you can't get the address of the current instruction pointer by moving it into a register, so what I do is call a function "pop" which really means that the return address of the next instruction is pushed onto the stack and then a jump is executed. I pop this return address into ebx and add 22 to get the address of the printf call. The reason this won't work for rule 3 is that if you insert code before the printf call the address will not be 22 away from the address of the pop ebx.

\$\endgroup\$
1
\$\begingroup\$

Befunge 98

This code snippet assumes that the IP comes downward into the upper left n. Otherwise, it fails.

n
>v>" enil morf ,dlroW olleH"bb+k,.@
^>:'^\1\p1+
 ][

The n (and newline) can be removed if I can assume that the stack is empty when it enters this snippet.

There is one discrepancy between this output and the one requested: instead of a ! at the end of the printed statement, this outputs a space because Befunge automatically appends a space to numbers that are outputted. I could easily add a ! after that. Fixing this would require a mess of ugly code.

You may add extra newlines anywhere and the code will still work. Spaces are more restricted, but may be added in several places. For instance, they cannot be added as the first character in any line.

Sample program:

v









n
>v>" enil morf ,dlroW olleH"bb+k,.@
^>:'^\1\p1+
 ][

Output:

Hello World, from line 12 
\$\endgroup\$
0
\$\begingroup\$

Haskell

{-# LANGUAGE CPP #-}
main = putStrLn $ "Hello World, from line " ++ show __LINE__ ++ "!"

Hello World, from line 2!

\$\endgroup\$
0
\$\begingroup\$

PHP

echo "Hello world, from line " . __LINE__ . "!";
\$\endgroup\$
0
\$\begingroup\$

Batch Script

@echo off
set /a %line%==10
echo Hello world at %line%
pause
exit
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Can you please explain how "Hello world at 10" points to the 3rd line in the script? Or, maybe there's some non-obvious batch syntax behind this? \$\endgroup\$
    – ysap
    Commented Jun 7, 2014 at 3:29
0
\$\begingroup\$

JAVASCRIPT - NON-Standard

console.log('Hello World, from line %d!', (new Error).lineNumber);

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/lineNumber

\$\endgroup\$
0
\$\begingroup\$

Python 2.7

# Any number of whitespace, code, etc.

# In this case, when greet() is called, it will output "Hello world, from line 4!"
def greet():print "Hello world, from line " + str(greet.func_code.co_firstlineno) + "!"

Originally I wanted to implement an overkill compiled code parser, but gave up, this is still a good one tho.

\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.