Here document: Difference between revisions

From Rosetta Code
Content added Content deleted
m ({{omit from|GUISS}})
m (omit c)
Line 303: Line 303:
ANARBITRARYTOKEN</lang>
ANARBITRARYTOKEN</lang>


{{omit from|C|No such thing}}
{{omit from|GUISS}}
{{omit from|GUISS}}
{{omit from|Icon}}{{omit from|Unicon}}
{{omit from|Icon}}{{omit from|Unicon}}

Revision as of 06:08, 13 July 2011

Task
Here document
You are encouraged to solve this task according to the task description, using any language you may know.

A here document (or "heredoc") is a way of specifying a text block, preserving the line breaks, indentation and other whitespace within the text. Depending on the language being used a here document is constructed using a command followed by "<<" (or some other symbol) followed by a token string. The text block will then start on the next line, and will be followed by the chosen token at the beginning of the following line, which is used to mark the end of the textblock.

The task is to demonstrate the use of here documents within the language.

ALGOL 68

Works with: ALGOL 68 version Revision 1 - no extensions to language used.
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny.

Algol 68 does not have a "heredoc" feature. It can be crudely achieved using an array of strings: <lang algol68>#!/usr/local/bin/a68g --script #

[]STRING help = ( "Usage: thingy [OPTIONS]", " -h Display this usage message", " -H hostname Hostname to connect to" );

printf(($gl$,help,$l$));

printf(($gl$, "The river was deep but I swam it, Janet.", "The future is ours so let's plan it, Janet.", "So please don't tell me to can it, Janet.", "I've one thing to say and that's ...", "Dammit. Janet, I love you." ))</lang> Output:

Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to

The river was deep but I swam it, Janet.
The future is ours so let's plan it, Janet.
So please don't tell me to can it, Janet.
I've one thing to say and that's ...
Dammit. Janet, I love you.

CoffeeScript

CoffeeScript borrows the triple-quoted string syntax from Python. Note that these strings strip leading whitespace in CoffeeScript, to allow you to neatly align the heredoc string. <lang coffeescript>myDoc =

       Single-quoted heredocs allows no '#{foo}' interpolation.
       This behavior is similar to single-quoted strings.
       

doc2 = """

       However, double-quoted heredocs *do* allow these.
       See it in action:
           Content: "#{myDoc}"
       """

console.log doc2</lang>

The above would output the following:

However, double-quoted heredocs *do* allow these.
See it in action:
    Content: "Single-quoted heredocs allows no '#{foo}' interpolation.
This behavior is similar to single-quoted strings."

Note how the extra indentation in the third line of doc2 is preserved.

D

Works with: D version 2

In D there are delimited strings: a 'q' followed by double quotes and an opening and closing delimiter of choice: <lang d>auto s = q"[a string that you "don't" have to escape]";</lang>

If the delimiter is an identifier, the identifier must be immediately followed by a newline, and the matching delimiter is the same identifier starting at the beginning of the line:

<lang d>writefln(q"EOS This is a multi-line heredoc string EOS" );</lang>

a string you " " don't have to escape

This
is a multi-line
heredoc string

J

<lang j>here=:0 :0

 0 :0 will be replaced by the text on the following lines.
 This is three tokens: two instances of the number 0 and
 one instance of the explicit definition token ':'.
 Any indentation in the here document will be retained in the result.
 There must be a space to the left of : or it will combine with the
 0 on its left to form the token 0: which is something completely 
 different.
 The here document is terminated by a line which contains only a
 single right parenthesis ')' and optional white space.  In J's
 documentation the family of entities which include here documents
 (and verb definitions and so on) are called 'scripts'.
 When several scripts are referenced on the same line, they are used
 sequentially in an order determined by their appearance on the line.
 The leftmost 'script' reference gets the last script and the rightmost
 reference gets the first script.  But this is a rare usage.
 Typically, such values are assigned a name so that they can be
 used later.  However, they may also be discarded and/or ignored, in
 which case they are logically equivalent to multi-line comments.

)

and_here=:noun define

 'noun define' is an alternative and perhaps more "user friendly"
 way of declaring a here document.  It achieves the same thing as
 0 :0 and in fact 'noun' has the value 0 and 'define' has the value :0
 And, of course, there must be a space between the word 'noun' and
 the word 'define'.
 Other useful alternatives include verb (which has the value 3)
 and dyad (which has the value 4), and adverb (which has the value 1).
 In other words 'verb define' (if unquoted) would be replaced by a 
 verb whose definition is provided in the following 'script'.
 However, all of these names are normal variables which can
 be declared to have different values by the developer.  And, of course,
 note that this mechanism is significantly more verbose than using
 the underlying 0 :0 mechanism directly.

)</lang>

Perl

In Perl, there must not be a space between the "<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised. Interpolation is allowed, like a double-quoted string:

<lang perl>$address = <<END; 1, High Street, $town_name, West Midlands. WM4 5HD. END</lang>

If the token string contains spaces, the token after the "<<" must be quoted; otherwise the double-quotes is implicit: <lang perl>$pancake = <<"NO MORE INGREDIENTS"; egg milk flour NO MORE INGREDIENTS</lang>

It is possible to make a here-document that behaves differently than a double-quoted string, by applying a different kind of quoting to the token. For example, if you use single quotes, then the here document will not support interpolation, like a normal single-quoted string:

<lang perl>$x = <<'FOO'; No $interpolation here FOO</lang>

Alternately, you can use backticks to cause the here document to be executed and the result returned, just like a normal backtick operator:

<lang perl>$output = <<`BAR`; ls /home BAR</lang>

Note that in the above examples, that a semicolon was left after the here document's token string. This is because (unlike PHP) the here document does not start immediately at the "<<END" token -- it starts on the next line. The "<<END" is actually an expression, whose value will be substituted by the contents of the here document. The "<<END" must still live inside a valid statement on the line that it's used. To further illustrate this fact, we can use the "<<END" inside a complex, nested expression:

<lang perl>print(<<EOF . "lamb\n"); Mary had

 a little

EOF</lang>

Although, technically speaking, it is also possible to break a statement into two parts, with the here document in the middle (i.e. continue the statement on the line after the terminating token). However, please don't do this.

<lang perl>print(<<EOF Mary had

 a little

EOF

  . "lamb\n");</lang>

Perl 6

Heredocs in Perl 6 use the :to modifier to a quoting operator, such as q or qq. Multiple here docs may be stacked on top of each other.

Works with: niecza

<lang perl6>my $contrived_example = 'Dylan'; sub freewheelin() {

       print q :to 'QUOTE', '-- ', qq :to 'AUTHOR';
         I'll let you be in my dream,
           if I can be in yours.
       QUOTE
               Bob $contrived_example
               AUTHOR

}

freewheelin; </lang>

Output:

  I'll let you be in my dream,
    if I can be in yours.
-- Bob Dylan

PHP

In PHP, the here document symbol is 3 less-than signs, not two: <<<

There must not be a space between the "<<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised, except for a possible semicolon. Interpolation is allowed, like a double-quoted string:

<lang php>$address = <<<END 1, High Street, $town_name, West Midlands. WM4 5HD. END;</lang>

In PHP 5.3+, it is possible to make a here-document that does not interpolate (PHP calls this a "nowdoc"), by surrounding the token with single-quotes (like in Perl): <lang php>$x = <<<'FOO' No $interpolation here FOO;</lang>

PicoLisp

We can use thhe 'here' function: <lang PicoLisp>(out "file.txt" # Write to "file.txt"

  (prinl "### This is before the text ###")
  (here "TEXT-END")
  (prinl "### This is after the text ###") )

"There must be some way out of here", said the joker to the thief "There's too much confusion, I can't get no relief" TEXT-END

(in "file.txt" (echo)) # Show "file.txt"</lang> Output:

### This is before the text ###
"There must be some way out of here", said the joker to the thief
"There's too much confusion, I can't get no relief"
### This is after the text ###

Python

Python does not have here-docs. It does however have triple-quoted strings which can be used similarly. <lang python>print("""\ Usage: thingy [OPTIONS]

    -h                        Display this usage message
    -H hostname               Hostname to connect to

""")</lang>

Ruby

In Ruby, there must not be a space between the "<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised, unless you use "<<-" instead of "<<", in which case indentation before the ending token is allowed. Interpolation is allowed, like a double-quoted string:

<lang ruby>address = <<END 1, High Street,

  1. {town_name},

West Midlands. WM4 5HD. END</lang>

If the token string contains spaces, the token after the "<<" must be quoted; otherwise the double-quotes is implicit: <lang ruby>pancake = <<"NO MORE INGREDIENTS" egg milk flour NO MORE INGREDIENTS</lang>

It is possible to make a here-document that behaves differently than a double-quoted string, by applying a different kind of quoting to the token. For example, if you use single quotes, then the here document will not support interpolation, like a normal single-quoted string:

<lang ruby>x = <<'FOO' No $interpolation here FOO</lang>

Alternately, you can use backticks to cause the here document to be executed and the result returned, just like a normal backtick operator:

<lang ruby>output = <<`BAR` ls /home BAR</lang>

The here document does not start immediately at the "<<END" token -- it starts on the next line. The "<<END" is actually an expression, whose value will be substituted by the contents of the here document. The "<<END" must still live inside a valid statement on the line that it's used. To further illustrate this fact, we can use the "<<END" inside a complex, nested expression:

<lang ruby>puts <<EOF + "lamb" Mary had

 a little

EOF</lang>

Tcl

<lang tcl>set hereDocExample { In Tcl, the {curly brace} notation is strictly a here-document style notation as it permits arbitrary content inside it *except* for an unbalanced brace. That is typically not a problem as seen in reality, as almost all content that might be placed in a here-doc is either brace-free or balanced. The content of the braces is not interpreted at all; no substitutions are performed on it.

The sole exception is that there is limited processing of backslashes; a single backslash at the end of a line causes the end-of-line plus all whitespace at the start of the next line to be compressed to a single space. }</lang> If substitution is desired within the document, it should either be written inside "double quotes" (instead of {braces}) or it should be passed through the subst command, which performs another round of substitutions.

UNIX Shell

In the shell, here document act as input to the command, rather than providing a string definition.

Works with: Bourne Shell
Works with: Bourne Again SHell

<lang sh>#!/bin/sh cat << ANARBITRARYTOKEN The river was deep but I swam it, Janet. The future is ours so let's plan it, Janet. So please don't tell me to can it, Janet. I've one thing to say and that's ... Dammit. Janet, I love you. ANARBITRARYTOKEN</lang>