Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Пітер Норвіг подарував мені Схему :)

with 2 comments

Для тих хто не знає, Пітер Норвіг це не Миколай, а director of research (керівник дослідженнями) в Google. А також автор грубезної книжки зі штучного інтелекту, і класичної статті Як вивчити програмування за 10 років?.

Але якось випадково блукаючи інтернетом я набрів на статтю: (How to Write a (Lisp) Interpreter (in Python))

Я прочитав, мене поперло, взяв код, перевірив, додав ще функцій, сподобалось ще більше, відкрив SICP, а там:

(define (square x) (* x x))

А в Норвіга define обчислюється так:

elif x[0] == 'define':         # (define var exp)
        (_, var, exp) = x
        env[var] = eval(exp, env)

І якщо var – список, то воно як ключ в env не лізе. Вирішив замінювати

(define (square x) (* x x))

на

(define square (lambda (x) (* x x)))

І переписав так:

        elif x[0] == 'define':         # (define var exp)
            (_, var, exp) = x
            if isa(var, str):
                env[var] = eval(exp, env)
            elif isa(var, list):
                env[var[0]] = eval(['lambda', var[1:], exp])
            else:
                RuntimeError('Cannot assign to constant!')

А потім ще додав до стандартних функцій print, input, а потім getattr, та import, за допомогою яких можна доступитись до всієї стандартної бібліотеки Python.

Потім я за допомогою функцій (ага!) і рекурсії описав цикли while та for і намалював дві пентаграми черепахою:

Але писати цикли функціями коли це повинні бути спеціальні форми (як і cond, та напевне define) – це трохи збоченння. Я почав гуглити про то як реалізовують макроси, і о яке щастя, я знайшов ще другу частину: (An ((Even Better) Lisp) Interpreter (in Python))

А потім може я на цій реалізації пройду SICP і напишу компілятор в байт-код Python. І зроблю про це презентацію до наступного performance appraisal…

Advertisements

Written by bunyk

Грудень 18, 2013 at 01:37

Оприлюднено в Кодерство

Tagged with , ,

Відповідей: 2

Subscribe to comments with RSS.

  1. Я перелякався, коли побачив for, визначений як неледача функція 🙂

    В принципі, досить цікава і відносно нескладна вправа — додати в інтерпретатор прості макроси (якщо їх там ще немає), які можуть робити те, що в нормальних мовах робиться ледачими функціями або на продовженнях. По суті, це просто додати крок перед eval, в якому перевіряється, чи форма — це макрос, а далі застосувати прив’язану до цього імені функцію-трансформацію до тіла макроса, eval’ити уже трансформовану функцію. Правда, також бажано додати квазіквоутинг (який від квоутингу відрізняється тим, що всередині «цитати» можна виділяти вирази, які таки будуть обчислюватись), без нього більшість макросів пишеться туго.
    Тоді можна написати «правильні» цикли без лямбд (які тут грають роль відкладеного вручну обчислення, саме так у SICP реалізовується примітиви ледачості delay/force, якщо не помиляюсь).

    dmytrish

    Грудень 18, 2013 at 10:50

  2. А, і щодо define, то він у моєму SECDScheme визначений також як макрос, який трансформує визначення і ініціалізацію в виклик вбудованої функції secd-bind! приблизно так:

    (define x 42) => (secd-bind! 'x 42)

    Функції так само легко переписуються в таку форму (втім, я ледачий і ще такого не зробив):

    (define (sqr x) (* x x)) => (secd-bind! 'sqr (lambda (x) (* x x)))

    dmytrish

    Грудень 18, 2013 at 11:00


Залишити відповідь

Заповніть поля нижче або авторизуйтесь клікнувши по іконці

Лого WordPress.com

Ви коментуєте, використовуючи свій обліковий запис WordPress.com. Log Out / Змінити )

Twitter picture

Ви коментуєте, використовуючи свій обліковий запис Twitter. Log Out / Змінити )

Facebook photo

Ви коментуєте, використовуючи свій обліковий запис Facebook. Log Out / Змінити )

Google+ photo

Ви коментуєте, використовуючи свій обліковий запис Google+. Log Out / Змінити )

З’єднання з %s

%d блогерам подобається це: