Skip to main content

A functional, array-oriented, tacit programming esolang run via Python interpreter

Project description

dIterLib - write functional, array-oriented, tacit code in Python

dIterLib is not a Python library. It is, instead, an esolang that runs via the Python interpreter. After from diterlib import *, you can use dIterLib in a Python environment, as a functional, array-oriented, tacit-style programming language.

Quick Start

This is an interesting introduction to dIterLib. If you just want to look up the functions, go to the appendix.

The Basics

Every dIterLib expression starts with o(...). It wraps the expression as a dIterLib object. You can do 2 things with it:

  1. Apply a function - the basics of dIterLib! The syntax is delightfully simple: object(function)

    Here's where the magic begins. dIterLib comes with a built-in range function named lrange. Watch this: o(5)(lrange) conjures up the list [0, 1, 2, 3, 4]. Why? Because behind the scenes, lrange(5) does exactly what you'd expect - it generates [0, 1, 2, 3, 4]. The o(5) wraps the number 5 in dIterLib's special sauce, and then (lrange) pipes it through the function. Elegant, isn't it?

    But wait, there's more! dIterLib doesn't stop at custom functions - it gives friendly names to Python's operators too, so you can use them in this functional style. Feast your eyes on this: o(5)(add, 3) evaluates to 8. How? Because add(5, 3) is just 5 + 3 in disguise! The comma syntax lets you pass additional arguments, transforming what looks like a simple addition into a sophisticated functional pipeline. It's like Python operators went to finishing school and learned some manners!

  2. Make iterator - the beating heart of dIterLib! Syntax: object[rank].

    Picture this: you've got your hands on a beautiful list l = [0, 1, 2, 3, 4] (courtesy of o(5)(lrange)), and now you want to add 1 to every single element. In vanilla Python, you'd be stuck writing [i+1 for i in l] or wrestling with map(lambda x: x+1, l). Yawn! Where's the elegance? Where's the joy?

    Enter dIterLib! With one elegant stroke: l[0](add,1). That's it. The [0] is your magic wand - it conjures an iterator over the 0th dimension, and whatever function follows gets applied to each element like a gentle wave washing over pebbles. The result? [1, 2, 3, 4, 5]. Chef's kiss!

    But here's where your eyebrows should start rising. What if the argument itself could be an iterator? Oh yes, my friend. l[0](add,l[0]) produces [0, 2, 4, 6, 8]: element-wise addition, like two dancers moving in perfect synchrony across the floor.

    Now for the grand finale. You want a 5x5 matrix where each cell contains the sum of its row and column indices. In plain Python, you'd descend into the nested list comprehension underworld: [[i+j for j in l] for i in l]. It's readable, sure, but where's the pizzazz?

    dIterLib says: hold my beverage. l[0](add,l[1]).

    Let that sink in. [0] iterates over rows, [1] iterates over columns, and because they have different ranks, dIterLib performs the most natural thing in the world: broadcasting. Every element of [0] meets every element of [1] in a beautiful Cartesian dance, producing your 5x5 matrix without a single nested bracket in sight. It's not just code - it's poetry in motion!

The Stack - dIterLib's secret memory vault, your personal time capsule for values!

Imagine you're in the middle of an epic calculation, and you stumble upon a precious intermediate result that you'll need again later. In lesser languages, you'd be forced to contort yourself with temporary variables, juggling names like a desperate street performer. But dIterLib scoffs at such pedestrian solutions!

Behold the stack - a LIFO wonderland where values go to wait their triumphant return! Here's your arsenal of stack sorcery:

  • ...(push) - The gentle archivist! This delightful operator whispers your current value to the stack's eager ears, while still returning it unchanged to continue your flowing pipeline. It's like having a photographic memory that doesn't interrupt your train of thought! Use it thusly: o(5)(lrange)(push)[0](mul,2) - your list [0,1,2,3,4] is safely stashed AND doubled to [0,2,4,6,8] in one breathtaking motion!

  • peek() - The curious observer! Sneaks a glance at the stack's summit without disturbing its slumber. "What's up there?" it asks politely, receiving the top value without popping it away. Perfect for when you need to check your stash without spending it.

  • pop() - The grand retriever! With a theatrical flourish, it extracts the top value from your stack and presents it for your immediate use. The value emerges from its resting place, ready to join the fray once more!

Picture this masterclass: o(5)(lrange)(push)[0](mul,2)[0](add,pop()[0]) - we stash the original list, double it, then add the original back! The result? [0,3,6,9,12] - a beautiful reunion of past and present, made possible by the stack's temporal magic!

The stack isn't just storage - it's time travel for your data!


Now you know the basics of dIterLib! Time to get more advanced.

Composing Functions

  1. reduce

    The folder of functions! Takes a binary function and collapses your array into one value. Syntax: reduce(function) or reduce(function, start) for a custom starting point. Example: sum = reduce(add) turns [1, 2, 3, 4] into 10. Simple, effective, done!

  2. prefix

    reduce's chatty cousin! Same folding action, but keeps every step. Syntax: prefix(function) or prefix(function, start). Example: o(5)(lrange)(prefix(add)) gives [0, 1, 3, 6, 10] - running totals without the sweat!

  3. fixedpoint

    The relentless iterator! Applies your function until input equals output. Syntax: fixedpoint(function). Example: fixedpoint(lambda x:(x+2/x)/2)(1) yields sqrt(2) - Newton's method in a one-liner!

  4. repeat

    The loop unroller! Apply a function n times. Syntax: repeat(function) needs (base, repetitions, start) to work. Example: o(0)(repeat(add),5,3) ( repeat(add)(0,5,3) ) returns 15 (0+3+3+3+3+3). Iteration made elegant!

  5. train

    APL's legendary "trains" - sequences of functions that work together to transform data. train(l, m, r) hooks three functions into a pipeline: left and right run first, then middle combines their results. Classic example - arithmetic mean: average = train(reduce(add), div, len). On [2, 4, 6, 8]:

    • First left: reduce(add) -> 20
    • Then right: len -> 4
    • Finally middle: div -> 20 / 4 = 5.0

    One expression, zero temps, maximum style!

    • Pro tip: train needs three functions, but sometimes you only have two. Enter iden - the identity-function creator! iden() passes the left operand through unchanged, iden(1) does the same for the right. It's the duct tape of functional composition - not glamorous, but indispensable when you need it.

Composing Functions (2)

Tired of writing long expressions with lambda:s, or just want to use dIterLib's syntax to create functions? Meet c!

c - the composer of dreams, the architect of abstraction!

Syntax: c(functions).f. Think of c as your very own dIterLib object - a blank canvas upon which you paint functional masterpieces! Chain operations upon it with the same elegant syntax you know and love. When your symphony is complete, the grand finale .f seals the deal, transforming your creation into a callable function ready to spring into action!

But wait - what if your masterpiece requires multiple arguments? Fear not, for arg() rides to the rescue! It's the placeholder that whispers "put an argument here, please!"

Behold, the arithmetic mean reborn: c(add,arg())(div,2).f - a function that takes two numbers and returns their average!

Let's peel back the curtain on this magic:

  • c(add, arg()) says: "First, I'll add something to my first argument... and that 'something' is the second argument!"
  • (div, 2) continues: "Then I'll divide the result by 2!"
  • .f cries: "Ta-da! You're a real function now!"

So c(add,arg())(div,2).f(10, 20) dances through: (10 + 20) / 2 = 15.0. Two arguments in, one beautiful average out!

No more lambda x, y: drudgery - just pure, compositional poetry!

Appendix: List of dIterLib's built-in functions

Function Description
o(x) Wrap x as dIterLib object
lrange(n) Generate [0, 1, ..., n-1]
add + operator
sub - operator
mul * operator
div / operator
truediv // operator
mod % operator
pow ** operator
eq == operator
ne != operator
gt > operator
ge >= operator
lt < operator
le <= operator
push Push value to internal stack
peek Peek at top of stack
pop Pop top of stack
slice(a,x,y) Slice array
take(a,x) Take first x elements of array
drop(a,x) Drop first x elements of array
reverse(a) Reverse array
reduce(f, start?) Fold array with binary f
prefix(f, start?) Running fold, keeps intermediates
fixedpoint(f) Iterate f until convergence
repeat(f) Apply f n times
train(l, m, r) APL-style function train
iden() / iden(1) Identity function (left/right arg)
c Function composer
arg() Placeholder for composer arguments

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

diterlib_islptng-0.1.0.tar.gz (8.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

diterlib_islptng-0.1.0-py3-none-any.whl (7.8 kB view details)

Uploaded Python 3

File details

Details for the file diterlib_islptng-0.1.0.tar.gz.

File metadata

  • Download URL: diterlib_islptng-0.1.0.tar.gz
  • Upload date:
  • Size: 8.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for diterlib_islptng-0.1.0.tar.gz
Algorithm Hash digest
SHA256 67cd46e1a5054edff74dd85b8b9ecd4177baeb45ecd792dd109940cce016b9cb
MD5 cba312800b406e76c2e6a1b3c7bc12a9
BLAKE2b-256 13960ad06d1a6cbe1d5a7302fea767b941f3a481a8764a7d9caa087742fc4785

See more details on using hashes here.

File details

Details for the file diterlib_islptng-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for diterlib_islptng-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 900a8ad9242ccae37443c02ca3c203d2e2fcdcfd74d193dfecdb90ec680fbc70
MD5 39a7d6ed3015bd78fcfeb02e87f0806b
BLAKE2b-256 48e8fa434b81e8f06f5229e6a0a287ac54e7bc361aeddf6a9a3f7779b8d771fd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page