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: useVa
fora
,V*g
forg
, etc.
Syntax
- The Else branch of an If statement begins with
E
, notEL
. - 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). UseFB
or roll your own base-conversion:aFDb
->$+a*b**RV,#a
, or(Ja)FBb
ifb
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
, ora/2
ifa
is known to be an even number.OG
(unary and binary). Use one ofZG
,MC
, orCG
instead:OGa
->1+ZGa
or1MCa
;aOGb
->1+(aZGb)
or1MMaCGb
.RE
(unary). Use an explicit function call instead:REa
->(fa)
.- Unary
R
. UseRV
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
ora**2
.TD
(unary and binary). UseTB
or roll your own base-conversion:aTDb
->^aTBb
ifb
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
, andSG
have higher precedence than binary@
,@>
, and@<
. Use parentheses or another precedence-manipulation strategy as needed:A*s@<3
->A*(s@<3)
orA*Ys@<3
;#l@1
->#(l1)
:
does not support destructuring assignment. For simple cases, use theU
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
, andGE
) 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, useRV
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 binaryCG
withMM
instead, but note thatMM
does not unpack the coordinate pairs:_.s.BMC[ab]
->_@0.s._@1MMaCGb
.N
andNI
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_
andB
if possible:2*$+G
->{2*$+g}
or2*$+{g}
or, if you know there will always be two arguments,2*_+2*B
.VD
andVN
: 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 regex0+(\.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, useMX
.- 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 possiblyA^_
. - 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)
.