`

Synopsis
` list
Description

Outputs a list equal to its input list but with certain substitutions. This is useful when some items of a complex list structure are known in advance—at the time you're programming—and other items must be evaluated at runtime. If all items are known in advance, then you're better off using square brackets to define a list literal (for example, [a b c]). If all items must be evaluated at runtime, then you're better off using LIST.

The backquote is also useful when defining macros with .MACRO because macros must output an instruction list and the backquote is good at creating instruction lists.

The backquote is also useful for partial evaluation.

The substitution rules for backquote are:

  • If a member of the input list is the word , (comma) then the following member should be an instruction list that produces an output when RUN. That output value replaces the comma and the instruction list. This is called substitution.

  • If a member of the input list is the word ,@ (comma atsign) then the following member should be an instruction list that outputs a list when RUN. The members of that list replace the ,@ and the instruction list. This is called splicing.

  • A word starting with , or ,@ is treated as if the rest of the word were a one-word list. For example, ,:foo is equivalent to ,[:foo].

  • A word starting with ", (quote comma) is replaced with a word beginning with " followed by the result of running the substitution on what comes after the comma. If what comes after the comma is a list it must contain exactly one item that is a word. This word is used in the substitution.

  • A word starting with :, (colon comma) is replaced with a word beginning with : followed by the result of running the substitution on what comes after the comma. If what comes after the comma is a list it must contain exactly one item that is a word. This word is used in the substitution.

These substitutions happens at any depth within the list structure of the list input. However, if a backquote appears within the list input, then the substitution is partially blocked. Considering only the backquotes and the substitution expressions and not the overall list structure, the substitution rules only apply at a substitution-depth that matches the backquote-depth of its nearest backquote. The nested backquotes and the outer substitution sequences appear in the output. The idea is that, with the outer-most backquote removed, the next level of backquote can be evaluated later, at which point another level of nested substitution will happen.

Nested backquotes are very difficult to use well in Logo and, due to their counter-intuitive semantics, should be avoided, even by experts.

To visualize the nesting behavior, consider the following example:

SHOW `[ ,[1*10] `[ ,[2*10 ,[3*10]]  `[ ,[4*10 ,[5*10 ,[6*10]]] ] ] ]
[10 ` [, [2*10 30] ` [, [4*10 , [5*10 60]]]]]

The ,[1*10] is at substitution-depth 1 in backquote-depth 1, so it is evaluated and replaced with 10.

The next substitution expression is ,[2*10 ,[3*10]]. It is within a backquote at backquote-depth 2. As a result, the outer part of the substitution retained as-is and the nested substitution at substitution-depth 2 ,[3*10] is evaluated and replaced with 30.

The next substitution expression is ,[4*10 ,[5*10 ,[6*10]]]. This is within a backquote at backquote-depth 3, so only the substitution at substitution-depth 3 ,[6*10] is evaluated and replaced with 60. The first two levels of substitution are retained, resulting in , [4*10 , [5*10 60]] being included in the output.

When considering the behavior of nested backquotes, remember that the nesting level of the list structure itself is irrelevant. A single backquote can perform substitutions at any depth of its list input.

SHOW `[ [[[ ,[1*10] ]]] ]
[[[[10]]]]

Also keep in mind that you cannot nest substitutions deeper than the nesting level of the backquotes. This is because the substitution sequences are not procedure names and so are invalid when evaluated. So if you try, you'll get an error.

SHOW `[ ,[PRINT 1*10 ,[2*10] ] ]
10
I don't know how to , in backq.unquote

By the way, the PRINT is needed above because something must be done with the output of 1*10 before the ,[2*10] instruction will be run. Without it, the instruction above would fail with a different error.

These examples illustrate how backquote nesting works but are not useful Logo instructions. To be useful, you would need a way to later evaluate the backquotes (and the substitution expressions) that remained in the output. Furthermore, those substitution expressions would need to run without error.

Example

The first example shows the difference between substitution and splicing. Observe that the substitution expressions are the same, but one is given with , (substitution) and the other is given with ,@ (splicing).

SHOW `[a b ,[BUTFIRST [1 2 3]] c ,@[BUTFIRST [1 2 3]] d]
[a b [2 3] c 2 3 d]

The next example shows how to create an instruction list that restores the turtle's position to whatever it was when the instruction list was created.

SETPOS [111 222]
MAKE "gohome `[ PENUP SETPOS ,[ LIST XCOR YCOR ] PENDOWN ]

This inserts the turtle's location into the :gohome instruction list as numbers, as seen below:

SHOW :gohome
[PENUP SETPOS [111 222] PENDOWN]

You can later use this instruction list to draw an 8-armed spiral shape with:

REPEAT 8 [ RUN :gohome FORWARD 100 LEFT 45 FORWARD 100]

No matter where the turtle is, the spiral will be centered at the location where the turtle was when :gohome was created.

If you don't want to use RUN, you could use DEFINE with a backquote to define a procedure instead of an instruction list.

DEFINE "GOHOME `[ [] [PENUP] [SETPOS ,[ LIST XCOR YCOR ]] [PENDOWN]  ]
REPEAT 8 [ GOHOME FORWARD 100 LEFT 45 FORWARD 100 ]


SourceForge.net Logo