http://www.perlmonks.org?node_id=286887

mnc has asked for the wisdom of the Perl Monks concerning the following question:

Can anyone think of a nicer way to do this?
:) Tnx.
eval('0 and eval(\'def length(x) end\')'); 0 and length <<2; """ #" 2 BEGIN{ eval('$stdin') ? "" : eval('package _X;use Filter::Simple sub { s{^(.*?\n__END_OF_RUBY__[^;]+;)}{do{my $x="$1";$x=~ tr/\n/ /c;$x}}se; s{(\n#__END_OF_PERL__.*)}{do{my $x="$1";$x =~ tr/\n/ /c;$x}}se;}; package main;import _X;'); } # END OF CRUFT def hello() print "Hi there ruby!\n"; end hello(); __END_OF_RUBY__ = <<'#__END_OF_PYTHON__'; sub hello { print "Hi there perl!\n"; } hello(); #__END_OF_PERL__ """ #" def hello() : print "Hi there python!" hello(); #__END_OF_PYTHON__
which yields
$ perl -w x.ppr; ruby -w x.ppr; python x.ppr Hi there perl! Hi there ruby! Hi there python!
at least with perl 5.6.0, ruby 1.6.4, and python 1.5.2. All rather old.

An afternoon hack.
zSyUK3 zat vendian org

Replies are listed 'Best First'.
Re: Source files which work with perl, python, and ruby
by sgifford (Prior) on Aug 27, 2003 at 04:00 UTC
    This program compiles and runs under all three:
    print "Hi there!\n";
    results in:
    [sgifford@sghome sgifford]$ perl -w /tmp/t91 Hi there! [sgifford@sghome sgifford]$ ruby -w /tmp/t91 Hi there! [sgifford@sghome sgifford]$ python /tmp/t91 Hi there!

    :-)

      I believe the trick was to have the source code auto-detect which compiler was compiling it and do specific behavior as a result. In this case, the different print statements.

      ------
      We are the carpenters and bricklayers of the Information Age.

      The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: Source files which work with perl, python, and ruby
by BooK (Curate) on Aug 27, 2003 at 12:06 UTC
Re: Source files which work with perl, python, and ruby
by Fletch (Bishop) on Aug 27, 2003 at 02:00 UTC

    That's pretty cool, but now you just need to get a trilingual quine . . . :)

Re: Source files which work with perl, python, and ruby [webpage]
by mnc (Beadle) on Aug 28, 2003 at 16:20 UTC
    There is now a webpage for the hack.

    And

    eval('0 and eval(\'def length(x) end\')'); 0 and length <<2;
    has been simplified to
    0 and eval('false') and length <<2;
    Perl and python consider 0 false, so "0 and" is a test for ruby. There is no point in ruby actually executing length, we just need the heredoc, so we add an always failing test for ruby's false. To avoid a perl unquoted string warning, we wrap it in an eval. Which may or may not be faster than ruby actually calling a do nothing "def length(x) end" ruby function, but it avoids namespace pollution. The core concept is that the token length is serving both as a variable in a bitshift for python, and as a function with a heredoc argument for perl and ruby. The heredoc jumps over pythons """ multi-line string token, which the perl parser doesnt like. The name "length" was chosen because perl needs to have seen the function declared in order to parse the line correctly, and length() seemed innocuous. So that's the thinking behind this fragment.

    Still more work to be done.

    Thanks for the comments.