PicoLisp. Прагматичный язык программирования
Перевод. Оригинал здесь
PicoLisp сильно отличается от других лиспов. Основная причина заключается в его ориентации на данные.
Большинство лиспов фокусируются на коде. Они подчеркивают функции и макросы так или иначе, а также эффективную компиляцию в машинный код. Это приводит к появлению множества различных типов данных, обрабатываемых неортогональными способами, часто с различными наборами функций. И результат компиляции (машинный код) больше не является Lisp и, таким образом, нарушает эквивалентность кода и данных.
В программировании конечной целью является манипулирование данными, а не функциями. Код и данные эквивалентны в Lisp, так что вы в любом случае получаете манипуляции с функциями бесплатно, но фокус должен быть на данных.
На уровне виртуальной машины PicoLisp имеет один-единственный тип данных: “cons-ячейка”.
На уровне языка он имеет только три типа данных: числа, символы и пары cons. Все они построены из ячеек.
То, что может показаться ограничением, на самом деле является большим преимуществом. Простая внутренняя структура обеспечивает высокую скорость запуска и выполнения. Ячейками можно свободно манипулировать любым мыслимым способом, предоставляя полный контроль программисту.
Символы являются “реальными” в PicoLisp. У них есть идентичность, физическое существование. Вы можете фактически захватить символ по его адресу и манипулировать его значением и свойствами (помните, что Lisp раньше был “языком манипулирования символами”).
Ортогональность языка позволяет создавать очень мощный и компактный код. Реализация данного алгоритма часто более выразительна и лаконична, чем в других лиспах.
Вся система открыта. Ничто не “скрыто за кулисами”. Внутреннее состояние может быть проверено (и понято!) в интерактивном режиме, вплоть до уровня ячейки и даже байта.
Интерпретатор PicoLisp реализован в самом PicoLisp. Он записан в подмножестве PicoLisp, которое - при выполнении - генерирует LLVM-IR (промежуточное представление), которое, в свою очередь, собирается LLVM для желаемой целевой архитектуры.
Помимо своего простого механизма, PicoLisp поддерживает пространства имен, сопрограммы, объектно-ориентированная база данных, веб-графический интерфейс, динамический собственные C-вызовы, встроенный редактор в стиле vi и может быть установлен в Android как приложение PilBox.
Таким образом, PicoLisp полезен для выполнения практической работы. С момента своего основания в 1988 году PicoLisp использовался в коммерческих проектах. Автор и его компания на протяжении многих лет выполняли все свои проекты исключительно в PicoLisp.
Факториал:
: (de fact (N)
(if (=0 N)
1
(* N (fact (dec N))) ) )
-> fact
: (fact 6)
-> 720
Нерекурсивный факториал:
: (apply * (range 1 6))
-> 720
: (apply * (range 1 40))
-> 815915283247897734345611269596115894272000000000
Сопрограмма генератора Фибоначчи:
: (co 'fibo
(let (A 0 B 1)
(loop
(yield
(swap 'B (+ (swap 'A B) B)) ) ) ) )
-> 1
: (co 'fibo T)
-> 1
$: (co 'fibo T)
-> 2
$: (co 'fibo T)
-> 3
$: (co 'fibo T)
-> 5
$: (co 'fibo T)
-> 8
Скалярное произведение:
: (sum * (1 2 3) (4 5 6))
-> 32
Объединение списка из 4 байт в 32-разрядное число:
: (sum >> (-24 -16 -8 0) (127 3 4 255))
-> 2130904319
: (hex @)
-> "7F0304FF"
Объединение нескольких списков в один список:
: (mapcan list '(a b c) (1 2 3) '(X Y Z))
-> (a 1 X b 2 Y c 3 Z)
Группировка одинаковых символов независимо от регистра:
: (by lowc group '(Abc dEf ghI DeF GHI abc))
-> ((Abc abc) (dEf DeF) (ghI GHI))
Сортировка символов по длине имени:
: (by length sort (all))
-> (NIL ! $ % & * + - / : ; < = > ? @ A B C ...
В других лиспах and
, or
и т.д. являются макросами и, следовательно, не могут быть применены в функции apply
. В PicoLisp они являются нормальными функциями:
: (apply and (1 NIL 3))
-> NIL
: (apply and (1 2 3))
-> 3
: (mapcar and (1 NIL 3) (1 2 3))
-> (1 NIL 3)
: (mapcar or (1 NIL NIL) '(NIL 2 NIL) '(NIL NIL 3))
-> (1 2 3)
Перечисление всех открытых файловых дескрипторов текущего процесса:
: (dir (pack "/proc/" *Pid "/fd"))
-> ("0" "1" "2" "3") # "3" is from 'dir' itself
Вызов нативного кода для получения текущего имени пользователя:
: (%@ "getlogin" 'S)
-> "u0\_a353"