We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

Pyline

From Esolang
Jump to navigation Jump to search

Pyline is an esoteric subset of Python 3.10 where the whole source file has to be a single expression. The walrus operator is available, making Pyline fairly easy to use. For a challenge, see Pyline Classic.

Idioms

Python Pyline
var = 5
var := 5
if 1 + 1 == 2:
    print("Hello, ")
    print("World! ")
1 + 1 == 2 and (
 print("Hello, "),
 print("World! ")
)
(
    print("Hello, "),
    print("World! "),
) if 1 + 1 == 2 else None
(
    print("Hello, ") and 0 or
    print("World! ")
) if 1 + 1 == 2 else None
if i == 1:
    ...
elif i == 2:
    ...
else:
    ...
(
    ...
) if i == 1 else (
    ...
) if i == 2 else (
    ...
)
for i in range(10):
    print(i)
all(
  (print(i),)
  for i in range(10)
)
[(
    print(i),
) for i in range(10)]
next(
    None for i in range(10)
    if not (
        print(i) and 0 or
        True
    )
)
while cond:
    print(1)
all(
  cond and (print(1),)
  for _ in iter(int,1)
)
[(
    print(1),
) for _ in iter(lambda: cond, False)]
next(
    None for _ in __import__("itertools").count()
    if not (
        print(1) and 0 or
        cond
    )
)
def add(a, b):
    res = a + b
    print(res)
    return res
add := lambda a, b: (
    res := a + b,
    print(res),
    res
)[-1]
add := lambda a, b: (
    (res := a + b) and 0 or
    print(res) and 0 or
    res
)
arr[0] += 1
arr.insert(0, arr.pop(0) + 1)
arr.__setitem__(0, arr[0] + 1)
obj.var = 5
setattr(obj, "var", 5)
import sys
sys := __import__("sys")
class Glass(object):
    _area = 406,
    def getarea(self):
        return self._area
Glass := type("Glass", (object,), dict(
    _area = 406,
    getarea = lambda self: self._area,
)),
raise err
(_ for _ in "_").throw(err)
try:
    print(1 / 0)
except BaseException as err:
    print(err)
(
    CD := (
        __import__("contextlib")
        .ContextDecorator,
    ),
    sml_catcher := type("Catcher", CD, dict(
        __enter__ = lambda self: self,
        __exit__ = lambda self, *err: (
            setattr(self, "err", err)
            or True
        ),
    )),
    
    catch := sml_catcher(),
    catch(lambda: (
        print(1 / 0)
    ))(),
    print(catch.err)
)

Examples

Hello World

print("hello world")

Quine

(lambda s:print(f'{s}({chr(34)}{s}{chr(34)})'))("(lambda s:print(f'{s}({chr(34)}{s}{chr(34)})'))")

A shorter one:

print((s:='print((s:=%s)%%s)')%s)

Or without walrus operator:

print((lambda s:s%s)('print((lambda s:s%%s)(%r))'))

A longer one:

(
s:=[],
s.append(112),
s.append(114),
s.append(105),
s.append(110),
s.append(116),
s.append(40),
s.append(39),
s.append(40),
s.append(39),
s.append(41),
s.append(44),
s.append(10),
s.append(112),
s.append(114),
s.append(105),
s.append(110),
s.append(116),
s.append(40),
s.append(39),
s.append(115),
s.append(61),
s.append(91),
s.append(93),
s.append(44),
s.append(39),
s.append(41),
s.append(44),
s.append(10),
s.append(91),
s.append(10),
s.append(32),
s.append(40),
s.append(10),
s.append(32),
s.append(32),
s.append(112),
s.append(114),
s.append(105),
s.append(110),
s.append(116),
s.append(40),
s.append(39),
s.append(115),
s.append(46),
s.append(97),
s.append(112),
s.append(112),
s.append(101),
s.append(110),
s.append(100),
s.append(40),
s.append(39),
s.append(44),
s.append(101),
s.append(110),
s.append(100),
s.append(61),
s.append(39),
s.append(39),
s.append(41),
s.append(44),
s.append(10),
s.append(32),
s.append(32),
s.append(112),
s.append(114),
s.append(105),
s.append(110),
s.append(116),
s.append(40),
s.append(120),
s.append(44),
s.append(101),
s.append(110),
s.append(100),
s.append(61),
s.append(39),
s.append(39),
s.append(41),
s.append(44),
s.append(10),
s.append(32),
s.append(32),
s.append(112),
s.append(114),
s.append(105),
s.append(110),
s.append(116),
s.append(40),
s.append(39),
s.append(41),
s.append(44),
s.append(39),
s.append(41),
s.append(10),
s.append(32),
s.append(41),
s.append(10),
s.append(102),
s.append(111),
s.append(114),
s.append(32),
s.append(120),
s.append(32),
s.append(105),
s.append(110),
s.append(32),
s.append(115),
s.append(93),
s.append(44),
s.append(10),
s.append(91),
s.append(112),
s.append(114),
s.append(105),
s.append(110),
s.append(116),
s.append(40),
s.append(99),
s.append(104),
s.append(114),
s.append(40),
s.append(120),
s.append(41),
s.append(44),
s.append(101),
s.append(110),
s.append(100),
s.append(61),
s.append(39),
s.append(39),
s.append(41),
s.append(10),
s.append(102),
s.append(111),
s.append(114),
s.append(32),
s.append(120),
s.append(32),
s.append(105),
s.append(110),
s.append(32),
s.append(115),
s.append(93),
s.append(44),
s.append(10),
s.append(112),
s.append(114),
s.append(105),
s.append(110),
s.append(116),
s.append(40),
s.append(39),
s.append(41),
s.append(39),
s.append(41),
print('('),
print('s=[],'),
[
 (
  print('s.append(',end=''),
  print(x,end=''),
  print('),')
 )
for x in s],
[print(chr(x),end='')
for x in s],
print(')')
)

Truth machine

(
	count:=__import__("itertools").count,
	i:=input(":"),
	[
		print('1',end="") for _ in count()
	] if i == '1'
	else (
		print('0')
	)
)

The walrus operator is only used here for readability; the entire expression can be given without it:

[print("1", end="") for _ in __import__("itertools").count()] if input(":") == "1" else print("0")

A version that doesn't use __import__

[print(1,end="")for _ in iter(lambda:0,1)]if input(":")=="1"else print(0)

A shorter one:

input()=="1"and{print(end="1")for _ in iter(set,0)}or print(0)

Rule 110 (Turing-completeness proof)

(
	count:=__import__("itertools").count,
	grb:=__import__("random").getrandbits,
	SIZE:=150,
	board:=[[bool(grb(1)) for _ in range(SIZE)],],
	[
		(
			old_board:=board[0].copy(),
			print("".join('.#'[i] for i in board[0])),
			board.__setitem__(0,[
				(
					l:=old_board[(i-1)%SIZE],
					r:=old_board[(i+1)%SIZE],
					(
						bool(110 & 2**(4*l+2*t+r))
					)
				)[-1]
				for i,t in enumerate(board[0])
			])
		)
		for _ in count()
	]
)

Brainfuck interpreter

Written by User: YufangTSTSU:

(
    brainfuck_inpreter := lambda code: (
        imports := __import__,
        whiler := (type("whiler", (object,), {
            "__init__": lambda s,f: setattr(s,"f",f) if callable(f) else \
                (_ for _ in ()).throw(TypeError(f"{f.__class__.__name__} object is not callable")),
            "__iter__": lambda s:   s,
            "__next__": lambda s:   None if s.f() else next(iter(())),
            "__repr__": lambda s:   f"<whiler object with {s.f}>"
        })),
        code_index := [0],
        tape := [0],
        tape_index := [0],
        input_store := [""], 
        [(
            {
                "+":lambda: tape.insert(tape_index[0], (tape.pop(tape_index[0]) + 1) % 256),
                "-":lambda: tape.insert(tape_index[0], (tape.pop(tape_index[0]) - 1) % 256),
                ">":lambda: (
                    tape_index.append(tape_index.pop() + 1),
                    None if tape_index[0] < len(tape) else tape.append(0)
                ),
                "<":lambda: tape_index.append(tape_index.pop() - 1) \
                           if tape_index[0] > 0 else tape.insert(0, 0),
                ".":lambda: print(chr(tape[tape_index[0]]), end="", flush=True),
                ",":(lambda: (
                    tape.pop(tape_index),
                    tape.insert(tape_index, int.from_bytes(imports("msvcrt").getche()))
                )) if "-getch" in imports("sys").argv else (lambda: (
                    (
                        input_store.pop(),
                        input_store.append(input())
                    ) if input_store == [""] else None,
                    tape.pop(tape_index[0]),
                    tape.insert(tape_index[0], ord(input_store[0][0]) % 256), 
                    input_store.append(input_store.pop()[1:]),
                )),
                "[":lambda: (
                        sml_index := code_index[0],
                        brackets := 1,
                        [(
                            sml_index := sml_index + 1,
                            brackets := brackets + {"[":1,"]":-1}.get(code[sml_index],0)
                        ) for __ in whiler(lambda: brackets != 0)],
                        code_index.pop(),
                        code_index.append(sml_index)
                    ) if not tape[tape_index[0]] else None,
                "]":lambda: (
                        sml_index := code_index[0],
                        brackets := -1,
                        [(
                            sml_index := sml_index - 1,
                            brackets := brackets + {"[":1,"]":-1}.get(code[sml_index],0)
                        ) for __ in whiler(lambda: brackets != 0)],
                        code_index.pop(),
                        code_index.append(sml_index)
                    ) if tape[tape_index[0]] else None
            }.get(code[code_index[0]], lambda: None)(),
            code_index.append(code_index.pop()+1),
        ) for _ in whiler(lambda: len(code) > code_index[0])]
    ),
    None
)

Another written by User:DGCK81LNN; takes both the program and the input from standard input, with the start of the input indicated by a !.

(lambda cod, _, inp:
  (lambda *, _cp = 0, _mp = 0, _ip = 0, _mem = {}, _inp = inp .encode(), _out = b"": next(
    __import__("sys").stdout.buffer.write(_out) and None or None
    for _ in __import__("itertools").count()
    if not (
      _mem.__setitem__(
        _mp,
        ((_mem[_mp] if _mp in _mem else 0) + (1 if cod[_cp] == "+" else -1 if cod[_cp] == "-" else 0)) & 255
      ) and 0 or
      (_mp := _mp + (1 if cod[_cp] == ">" else -1 if cod[ _cp] == "<" else 0)) and 0 or
      (
        (_cp := (lambda si, *, _d = 0:
          next(i
            for i in (range(si, len(cod)) if cod[si] == "[" else range(si, -1, -1))
            if cod[i] in "[]" and ((_d := _d + (1 if cod[i] == "[" else -1)) == 0)
          )
        )(_cp))
        if cod[_cp] in "[]" and bool(_mem[_mp] if _mp in _mem else 0) == bool(cod[_cp] == "]")
        else 0
      ) and 0 or
      (
        (_out := _out + bytes((_mem[_mp],))) if cod[_cp] == "."
        else _mem.__setitem__(_mp, _inp[_ip]) and 0 or (_ip := _ip + 1) if cod[_cp] == "," and _ip < len(_inp)
        else 0
      ) and 0 or
      (_cp := _cp + 1) < len(cod)
    )
  ))()
)(*__import__("sys").stdin.read().partition("!"))

Another written by User: Jan jelo

(
program:=list(input())+['@'],
ltape:=[0],rtape:=[0],
pc:=0,i:=0,state:=0,
INC:=lambda:ltape.append((ltape.pop()+1)%256),
DEC:=lambda:ltape.append((ltape.pop()-1)%256),
IN:=lambda:ltape.append(ord(input())%256),
LS:=lambda:(a:=ltape[-1],
   ltape.pop()
   if len(ltape)>1 else ...,
   rtape.append(a)
),
RS:=lambda:(a:=rtape[-1],
   rtape.pop()
   if len(rtape)>1 else ...,
   ltape.append(a)
),

[(
 (
  (LS(),
   state:=1)
  if program[pc]=='<' else
  
  (RS(),
   state:=1)
  if program[pc]=='>' else

  (INC(),state:=1)
  if program[pc]=='+' else

  (DEC(),state:=1)
  if program[pc]=='-' else

  (IN(),state:=1)
  if program[pc]==',' else
  
  (print(chr(ltape[-1]),end=''),state:=1)
  if program[pc]=='.' else

  (
   (i:=0,state:=2)
   if ltape[-1]==0 else
   (state:=1)
  )
  if program[pc]=='[' else

  (
   (i:=0,state:=3)
   if ltape[-1]!=0 else
   (state:=1)
  )
  if program[pc]==']' else
  
  (state:=4)
  if program[pc]=='@' else...
 )
 if state==0 else
 
 (
  state:=0,
  pc:=pc+1
 )
 if state==1 else

 (
  (
   i:=i-1,
   (state:=0) if i==0 else (pc:=pc+1)
  )
  if program[pc]=='[' else
  
  (
   i:=i+1,
   (state:=0) if i==0 else (pc:=pc+1)
  )
  if program[pc]==']' else (pc:=pc+1)
 )
 if state==2 else
 
 (
  (
   i:=i-1,
   (state:=0) if i==0 else (pc:=pc-1)
  )
  if program[pc]=='[' else
  
  (
   i:=i+1,
   (state:=0) if i==0 else (pc:=pc-1)
  )
  if program[pc]==']' else (pc:=pc-1)
 )
 if state==3 else ...
 )

for _ in iter(lambda:state!=4,0)]
)

Another one, still written by User:YufangTSTSU:

(I:=open(0).read().partition("!"),c:=I[0],I:=[*I[2]],d:={},s:=[],[(s:=s+[i])if c=="["else c=="]"and(d:=d|{i:s[-1],s.pop():i})for i,c in enumerate(c)],p:=0,t:=[i:=0]*30000,s:=t.__setitem__,[(s(p,t[p]+1&255)if c=="+"else s(p,t[p]-1&255)if c=="-"else print(end=chr(t[p]))if c=="."else s(p,ord(I.pop(0)))if c==","else(p:=p+1)if c==">"else(p:=p-1)if c=="<"else(c=="]"and t[p]or c=="["and t[p]<1)and(i:=d[i]),i:=i+1)for c in iter(lambda:i<len(c)and c[i],0)])

Spaced version:

(
    I := open(0).read().partition("!"),
    c := I[0], I := [*I[2]],

    d := {}, s := [],
    [
        (s := s + [i]) if c == "[" else
        c == "]" and (d := d | {i: s[-1], s.pop(): i})
        for i, c in enumerate(c)
    ],

    p := 0, t := [i := 0] * 30000,
    s := t.__setitem__,

    [(
        s(p, t[p] + 1 & 255) if c == "+" else
        s(p, t[p] - 1 & 255) if c == "-" else
        print(end = chr(t[p])) if c == "." else
        s(p, ord(I.pop(0))) if c == "," else
        (p := p + 1) if c == ">" else
        (p := p - 1) if c == "<" else
        (c == "]" and t[p] or c == "[" and t[p] < 1) and (i := d[i]),

        i := i + 1
    ) for c in iter(lambda:i < len(c) and c[i], 0)]
)

Another by User: Jan jelo

(i:=input,p:=i(),c:=0,l:=[0],r:=[0],
 s:=lambda l,i,e:l.__setitem__(i,e),
 a:=lambda l,e:l.append(e),
[(o:=p[c],ll:=len(l)-1,lr:=len(r)-1,
  lf:=l[-1],rf:=r[-1],
  (
   (
    (o=='+')and s(l,ll,(lf+1)%256)),
    (o=='-')and s(l,ll,(lf-1)%256),
    (o=='<')and(a(r,lf),(ll>0)and l.pop()),
    (o=='>')and(a(l,rf),(lr>0)and r.pop()),
    (o=='.')and(print(chr(lf),end='',flush=1)),
    (o==',')and(l.pop(),a(l,ord(i()or chr(lf))%256)),
    c:=c+1
   )
  if not o in '[]'else
  (b:=c,j:=1,m:=[-1,1][o=='['],
   [(b:=b+m,n:=p[b],
      (n=='[')and(j:=j+m),
      (n==']')and(j:=j-m)
     )
    for _ in iter(lambda:j,0)],
    (c:=b)if [lf,lf==0][(m+1)//2] else(c:=c+1)
  )
)
for _ in iter(lambda:len(p)>c,0)]
)

Another by User: Jan jelo, convert bf code into Pyline code then evaluate

(g:='t.get(c,0)',
 s:=lambda x:f't.__setitem__(c,{x}),',
 o:=lambda x:{
  '+':s(f'{g}+1&255'),
  '-':s(f'{g}-1&255'),
  '<':'c:=c-1,',
  '>':'c:=c+1,',
  ',':s('ord((input()or chr(0))[0])'),
  '.':f'print(chr({g}),end="",flush=1),',
  '[':'[(',
  ']':f')for _ in iter(lambda:{g},0)],'
  }.get(x,'...,'),
 eval(f'(t:=dict(),c:=0,{"".join(map(o,input()))})')
)

And another by User:YufangTSTSU, using evals:

(lambda c,_,g,S,G:eval(",".join(f"{S+G}+1&255)|{S+G}-1&255)|print(end=chr({G}))|{S}ord(g[q:=q+1]))|(p:=p+1)|(p:=p-1)|[(0|)for _ in iter(lambda:{G},0)]".split("|")["+-.,<>[]".index(i)]for i in c),dict(t={},p=0,g=g,q=-1)))(*input().partition("!"),"t.__setitem__(p,","t.get(p,0)")