# Differences from Pip Classic

The 2018-10-25 commit of Pip is known as Pip Classic. This is the version of Pip available at Try It Online! If you’re trying to run a Pip program on TIO and something isn’t working the way it should, you might be using a language feature that isn’t in Pip Classic. Here is a catalog of the differences between the versions and how to work around them.

Note: “lhs” = left-hand side argument of an operator and “rhs” = right-hand side argument (including the single argument of a unary operator).

## Flags

- The
`-x`

flag is not supported. Evaluate the arguments explicitly: use`Va`

for`a`

,`V*g`

for`g`

, etc.

## Syntax

- The Else branch of an If statement begins with
`E`

, not`EL`

. - For loops do not support destructuring assignment. Switching to a functional programming approach will usually be shorter anyway:
`F[ab]lPaRb'_`

->`P{aRb'_}MUl`

with the appropriate list-formatting flag. - The Swap and Unify statements exist.
- Arbitrary-length variable names starting with
`$`

are not supported. - There is no block comment syntax.

## Data types

- The str/repr of a Block is a stringified Python list representing a parse tree (with the outer
`[]`

delimiters changed to`{}`

) rather than a string that evaluates to the same Block. Don’t use the str or repr of a Block for anything except debugging purposes.

## Missing operators

- Unary
`%`

. Mod by 2 explicitly:`%a`

->`a%2`

. - Unary
`**`

. Raise 2 to the power explicitly:`**a`

->`2**a`

. `::`

(binary). Use the swap command instead:`a::b`

->`Sab`

.- Unary
`<>`

. Group into size-2 chunks explicitly:`<>a`

->`a<>2`

. `\?`

(ternary),`\|`

and`\&`

(binary), and`\!`

(unary). Use a curly-brace function instead of a lambda, or look for another way to express the formula:`_\|'x`

->`{a|'x}`

;`\!_`

->`_=0`

if the argument is guaranteed to be a number.`AD`

(binary). Subtract and take the absolute value instead:`aADb`

->`AB(a-b)`

.`D`

(unary). Use`--`

instead, but note the slight difference in precedence:`Da`

->`--a`

;`Da@<2`

->`--(a@<2)`

.`DB`

(unary). Multiply by 2 explicitly:`DBa`

->`a*2`

.`E`

(unary and binary). Use`**`

instead:`Ea`

->`2**a`

;`aEb`

->`a**b`

.`EE`

(unary and binary). Use the full formula instead:`EEa`

->`10**a`

;`aEEb`

->`a*10**b`

.`FD`

(unary and binary). Use`FB`

or roll your own base-conversion:`aFDb`

->`$+a*b**RV,#a`

, or`(Ja)FBb`

if`b`

is 36 or less and all digits are less than 10.- Unary
`FI`

. Filter by the identity function instead:`FIa`

->`_FIa`

. `H`

(unary and binary). Use`@<`

instead, but note the difference in precedence:`Ha`

->`@<a`

;`aHb`

->`a@<b`

;`a.bHc-2`

->`(a.b)@<(c-2)`

.`HV`

(unary). Divide by 2 explicitly:`HVa`

->`a//2`

, or`a/2`

if`a`

is known to be an even number.`OG`

(unary and binary). Use one of`ZG`

,`MC`

, or`CG`

instead:`OGa`

->`1+ZGa`

or`1MCa`

;`aOGb`

->`1+(aZGb)`

or`1MMaCGb`

.`RE`

(unary). Use an explicit function call instead:`REa`

->`(fa)`

.- Unary
`R`

. Use`RV`

instead:`Ra`

->`RVa`

. `S`

(unary and binary). Use`@>`

instead (with a negated second argument if binary), but note the difference in precedence:`Sa`

->`@>a`

;`aSb`

->`a@>-b`

;`a.bSc-2`

->`(a.b)@>(2-c)`

.`SQ`

(unary). Multiply the number by itself or use`**`

instead:`SQa`

->`a*a`

or`a**2`

.`TD`

(unary and binary). Use`TB`

or roll your own base-conversion:`aTDb`

->`^aTBb`

if`b`

is 10 or less.`U`

(unary). Use`++`

instead, but note the slight difference in precedence:`Ua`

->`++a`

;`Ua@<2`

->`++(a@<2)`

.

## Operators with different behavior

- Unary
`#`

,`A`

,`AB`

,`C`

,`FB`

, and`SG`

have higher precedence than binary`@`

,`@>`

, and`@<`

. Use parentheses or another precedence-manipulation strategy as needed:`A*s@<3`

->`A*(s@<3)`

or`A*Ys@<3`

;`#l@1`

->`#(l1)`

`:`

does not support destructuring assignment. For simple cases, use the`U`

statement:`[xyz]:a`

->`UxyzWa`

. More-complex cases may need to use a series of assignments and/or unifications:`C:[xyz]`

->`C:xC:yC:z`

;`[[wx][yz]]:a`

->`UwxW@aUyzWa@1`

.- Numeric and string equality operators (
`=`

,`<=`

,`>=`

,`Q`

,`LE`

, and`GE`

) always return falsey when their arguments are not comparable, rather than returning truthy if the arguments are identical. (In particular, nil is not equal to nil, and a Pattern is not equal to itself under numeric comparison.) If this becomes a problem, you can explicitly check for exact equality first:`a<=b`

->`a==b|a<=b`

. `<>`

does not work with a negative rhs. To group from right to left, use`RV`

twice:`a<>-4`

->`RV*(RVa<>4)`

.`<>`

does not accept a List or Range as rhs. To return a list of different groupings, map a lambda function:`a<>[2 4]`

->`a<>_M[2 4]`

.`MC`

does not accept a height/width List as rhs. Use binary`CG`

with`MM`

instead, but note that`MM`

does not unpack the coordinate pairs:`_.s.BMC[ab]`

->`_@0.s._@1MMaCGb`

.`N`

and`NI`

do not accept a List/Range lhs with a Scalar rhs. Map a lambda function instead:`[1 2 4]Na`

->`_NaM[1 2 4]`

.

## Missing variables

(These still act as variables, but their initial values are nil rather than the useful values they have in current Pip.)

`p`

: use`"()"`

instead.`G`

: use`{g}`

instead, or rework your lambda function using`_`

and`B`

if possible:`2*$+G`

->`{2*$+g}`

or`2*$+{g}`

or, if you know there will always be two arguments,`2*_+2*B`

.`VD`

and`VN`

: not supported, but not particularly useful for golf anyway.

## Bugs

- Using
`<>`

with a rhs of 0 or a negative number results in an infinite loop. Only use`<>`

with positive rhs. See above for how to group from right to left. - A Scalar with leading whitespace in a numeric context evaluates to
`0`

, rather than ignoring the whitespace. If leading whitespace is a possibility, strip it explicitly using`|>`

. - A non-integer rhs to
`\,`

crashes the interpreter. Only use`\,`

with integer rhs. If a non-integer rhs is a possibility, int-divide it by 1 to truncate it to an integer. - Using
`A`

with a Scalar rhs matching the regex`0+(\.0+)?`

results in nil rather than 48. Concatenating space or some other character to the end of the Scalar is one possible workaround. `<`

returns 1 when given two Lists that are equal. Swap the arguments and use`>`

instead.`#`

and the length-comparison operators crash the interpreter when given infinite Ranges. Try to avoid taking the length of infinite Ranges. If you need to test the upper bound of a Range, use`MX`

.- Iterating over an infinite Range with a lower bound of nil crashes the interpreter. Use a lower bound of 0 instead.
- Indexing into an empty iterable and then attempting to assign a value to that expression crashes the interpreter. Make sure iterables are nonempty before attempting to assign to their items.
- Indexing into a variable whose value is a Range gives nil. Convert to a List first (e.g. by multiplying by 1) or use math instead of indexing into a Range.
- Applying an operator with the
`*`

meta-operator to a Block crashes the interpreter. Use a curly-brace delimited function instead of a lambda function, or find a way not to use the meta-operator:`A*_`

->`{A*a}`

or possibly`A^_`

. - Weaving a List containing nil crashes the interpreter. If this ever becomes an issue, one potential workaround is to filter the List before weaving it:
`WVl`

->`WV(#_FIl)`

.