Programs and modules
A .ki file is a module. Top-level forms run when it loads, as a Python
file’s do on import.
Running
Python
python prog.py
python -i prog.py
python
Koskari
koskari prog.ki
koskari -i prog.ki
koskari
Where do .ki files live?
Beside your .py files, in the same packages and on the same
sys.path. Once import koskari has run, Python’s import mypkg.mod
finds mypkg/mod.ki. Running a script adds its directory to the path,
as Python does.
The shape of a file
Python
"""Process names from argv."""
import sys
def process(name):
print("hello", name)
def main():
for name in sys.argv[1:]:
process(name)
if __name__ == "__main__":
main()
Koskari
"""
Process names from argv
"""
import sys
def process [name]:
print "hello" name
@entry-point
def main []:
for-each [name (item-slice sys.argv 1)]:
(process name)
What is @entry-point?
The mark on the function that runs when the file is executed as a
program and not when it is imported. Where Python guards a block with
if __name__ == "__main__": and runs it while the module is still
loading, Koskari calls the marked function once the module has
finished loading, and its return value is the exit status: None is
0, an int is that status. main is still an ordinary function that
a test or another module can call. Comments are ; to the end of the
line, doubled by custom.
Comprehensions
Python
squares = [x * x for x in range(6)]
Koskari
var squares:
list-each [x (range 6)]:
(* x x)
Python
evens = [x for x in xs if x % 2 == 0]
Koskari
var evens:
list-each [x xs] when: (== 0 (% x 2)):
x
Python
lengths = {w: len(w) for w in words}
Koskari
var lengths:
dict-each [w words] key: w value: (len w)
Python
gen = (x * x for x in xs)
Koskari
var gen:
each [x xs]:
(* x x)
Which one is which?
list-each builds a list, dict-each a dict, each a generator. All
three take the [var seq] binding that for-each takes, and a when:
or unless: clause on the header filters. A for-each loop is for
side effects; the -each family is for values.
Imports
Python
import math
import os.path
from pathlib import Path
from functools import lru_cache as memoize
from mypkg import *
Koskari
import math
import os.path
import-from pathlib Path
import-from functools [lru_cache as: memoize]
import-all-from mypkg
Does import os.path bind os?
Yes, as in Python. import [os.path as: p] binds the leaf module
directly.
Packages
Python
mypkg/
__init__.py
tools.py
Koskari
mypkg/
__init__.py
tools.ki
Does the __init__ have to be Python?
No; __init__.ki works, and so does no __init__ at all, which gives a
namespace package as it would in Python. A Python __init__.py that
runs import koskari is the common choice, since it turns the import
hook on for anyone who imports the package. The rules, including the
one trap, a foo.py beside a foo.ki, are in
Modules and packages.
Run it
Save as squares.ki:
def squares [n]:
list-each [i (range n)]:
(* i i)
@entry-point
def main []:
print (squares 6)
[0, 1, 4, 9, 16, 25]
To ship a .ki program as a pip-installed command, see
Packaging an installed command.