<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <atom:link rel="self" type="application/rss+xml" href="http://breys.ru/rss"/>
    <language>ru</language>
    <copyright>Copyright 2008,2009 breys.ru</copyright>
    <title>Заметки на breys.ru</title>
    <link>http://breys.ru/blog/</link>
    <description>Заметки по теме: Scheme, Брейс - дизайн студия</description>
    <item>
      <link>http://breys.ru/blog/225.html</link>
      <guid>http://breys.ru/blog/225.html</guid>
      <title>О языке программирования Scheme. Часть вторая.</title>
      <pubDate>Tue, 31 Mar 2009 09:14:07 +0400</pubDate>
      <description>&lt;p&gt;1. И так, посмотрим, что можно сделать с помощью замыканий. В стандарт ANSI Common Lisp включена Common Lisp Objective System, реализующая полноценная ООП система. Станадрт же Scheme (R5RS как я понимаю текущий) описан значительно более меньший функционал, который должен быть реализован в интерпретаторе/компиляторе Схемы и поддержка ООП в нем не декларирована. Но поскольку считается, что Лисп позволяет реализовать любую парадигму программирования без измененния базового интерпретатора/компилятора, попробуем реализовать простую ООП систему с помощью замыканий.&lt;/p&gt;
&lt;pre&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;;(module object)  ;;; required by bigloo&lt;br /&gt;&lt;br /&gt;;(require-extension syntax-case)  ;;; required by chicken&lt;br /&gt;&lt;br /&gt;(define-syntax define-object&lt;br /&gt;  (syntax-rules (:)&lt;br /&gt;    ((_ name : class)&lt;br /&gt;     (define name (class &amp;#039name &amp;#039class)))))&lt;br /&gt;&lt;br /&gt;(define (error-class name class)&lt;br /&gt;  (let* ((name name)&lt;br /&gt;	 (class class)&lt;br /&gt;	 (errors (list &amp;#039type-mismatch &amp;#039unknown-action))&lt;br /&gt;	 (actions (list &amp;#039get-errors &amp;#039get-actions &amp;#039msg))&lt;br /&gt;	 (msg (lambda (args)&lt;br /&gt;		(for-each display args)&lt;br /&gt;		(newline)))&lt;br /&gt;	 (error (lambda args &lt;br /&gt;		  (msg (cons "* ERROR: " (cons name (cons ": " args)))))))&lt;br /&gt;    (lambda (action . value)&lt;br /&gt;      (cond ;-- GET-actions:&lt;br /&gt;	((eq? action &amp;#039get-errors) errors)&lt;br /&gt;	((eq? action &amp;#039get-actions) actions)&lt;br /&gt;	;-- OTHER-actions:&lt;br /&gt;	((eq? action &amp;#039msg) (msg value))&lt;br /&gt;	;-- ERROR-actions:&lt;br /&gt;	((eq? action &amp;#039type-mismatch)&lt;br /&gt;	 (if (pair? value)&lt;br /&gt;	     (error "wrong type of `" (car value) &lt;br /&gt;		    "&amp;#039 must be " (cadr value))&lt;br /&gt;	     (error "not enough parameters in &amp;#039type-mismatch message")))&lt;br /&gt;	(else (error "unknown action `" action "&amp;#039") &lt;br /&gt;	      &amp;#039unknown-action)))))&lt;br /&gt;&lt;br /&gt;(define (base-class name class)&lt;br /&gt;  (let ((name name)&lt;br /&gt;	(class class)&lt;br /&gt;	(error (error-class name class))&lt;br /&gt;	(actions (list &amp;#039get-name &amp;#039get-class &amp;#039msg &amp;#039get-actions)))&lt;br /&gt;    (lambda (action . value)&lt;br /&gt;      (cond ;-- GET-actions:&lt;br /&gt;	((eq? action &amp;#039get-name) name)&lt;br /&gt;	((eq? action &amp;#039get-class) class)&lt;br /&gt;	((eq? action &amp;#039get-actions) (cons actions (error &amp;#039get-actions)))&lt;br /&gt;	;-- OTHER-actions:&lt;br /&gt;	(else (apply error (cons action value)))))))&lt;br /&gt;&lt;br /&gt;(define (parent-class name class)&lt;br /&gt;  (let ((name name)&lt;br /&gt;	(class class)&lt;br /&gt;	(parent (base-class name class))&lt;br /&gt;	(actions (list &amp;#039get-int-field &amp;#039set-int-field))&lt;br /&gt;	(int-field 0))&lt;br /&gt;    (lambda (action . value)&lt;br /&gt;      (cond ;-- GET-actions:&lt;br /&gt;	((eq? action &amp;#039get-int-field) int-field)&lt;br /&gt;	((eq? action &amp;#039get-actions) (cons actions (parent &amp;#039get-actions)))&lt;br /&gt;	;-- SET-actions:&lt;br /&gt;	((eq? action &amp;#039set-int-field)&lt;br /&gt;	 (if (integer? (car value))&lt;br /&gt;	     (set! int-field (car value))&lt;br /&gt;	     (parent &amp;#039type-mismatch &amp;#039int-field &amp;#039integer)))&lt;br /&gt;	;-- OTHER-actions:&lt;br /&gt;	(else (apply parent (cons action value)))))))&lt;br /&gt;&lt;br /&gt;(define (child-class name class)&lt;br /&gt;  (let ((name name)&lt;br /&gt;	(class class)&lt;br /&gt;	(parent-obj (parent-class name class))&lt;br /&gt;	(base-obj (base-class name class))&lt;br /&gt;	(actions (list &amp;#039get-str-field &amp;#039set-str-field))&lt;br /&gt;	(str-field ""))&lt;br /&gt;    (lambda (action . value)&lt;br /&gt;      (cond ;-- GET-actions:&lt;br /&gt;	((eq? action &amp;#039get-str-field) str-field)&lt;br /&gt;	((eq? action &amp;#039get-actions)&lt;br /&gt;	 (cons actions (parent-obj &amp;#039get-actions)))&lt;br /&gt;	;-- SET-actions:&lt;br /&gt;	((eq? action &amp;#039set-str-field)&lt;br /&gt;	 (if (string? (car value))&lt;br /&gt;	     (set! str-field (car value))&lt;br /&gt;	     (parent-obj &amp;#039type-mismatch &amp;#039str-field &amp;#039string)))&lt;br /&gt;	;-- OTHER-actions:&lt;br /&gt;	(else (apply parent-obj (cons action value)))))))&lt;br /&gt;&lt;br /&gt;;-- TESTING:&lt;br /&gt;&lt;br /&gt;(define-object base-obj   : base-class)&lt;br /&gt;(define-object parent-obj : parent-class)&lt;br /&gt;(define-object child-obj  : child-class)&lt;br /&gt;&lt;br /&gt;(define (test-base-obj)&lt;br /&gt;  (let ((obj base-obj))&lt;br /&gt;    (obj &amp;#039msg "  ---- base-obj ----"&lt;br /&gt;              "\nclass   : " (obj &amp;#039get-class)&lt;br /&gt;	      "\nname    : " (obj &amp;#039get-name)&lt;br /&gt;              "\nactions : " (obj &amp;#039get-actions)&lt;br /&gt;              "\nerrors  : " (obj &amp;#039get-errors))&lt;br /&gt;    (newline)&lt;br /&gt;    (obj &amp;#039action)&lt;br /&gt;    (newline)))&lt;br /&gt;&lt;br /&gt;(define (test-parent-obj)&lt;br /&gt;  (let ((obj parent-obj))&lt;br /&gt;    (obj &amp;#039msg "  ---- parent-obj ----"&lt;br /&gt;              "\nclass     : " (obj &amp;#039get-class)&lt;br /&gt;	      "\nname      : " (obj &amp;#039get-name)&lt;br /&gt;	      "\nactions   : " (obj &amp;#039get-actions)&lt;br /&gt;              "\nerrors    : " (obj &amp;#039get-errors)&lt;br /&gt;              "\nint-field : " (obj &amp;#039get-int-field))&lt;br /&gt;    (newline)&lt;br /&gt;    (obj &amp;#039set-int-field 12)&lt;br /&gt;    (obj &amp;#039set-int-field "df")&lt;br /&gt;    (obj &amp;#039msg "\nint-field : " (obj &amp;#039get-int-field))&lt;br /&gt;    (newline)))&lt;br /&gt;&lt;br /&gt;(define (test-child-obj)&lt;br /&gt;  (let ((obj child-obj))&lt;br /&gt;    (obj &amp;#039msg "  ---- child-obj ----"&lt;br /&gt;              "\nclass     : " (obj &amp;#039get-class)&lt;br /&gt;	      "\nname      : " (obj &amp;#039get-name)&lt;br /&gt;              "\nactions   : " (obj &amp;#039get-actions)&lt;br /&gt;	      "\nerrors    : " (obj &amp;#039get-errors)&lt;br /&gt;              "\nstr-field : " (obj &amp;#039get-str-field) &lt;br /&gt;	      "\nint-field : " (obj &amp;#039get-int-field))&lt;br /&gt;    (newline)&lt;br /&gt;    (obj &amp;#039set-str-field "abc")&lt;br /&gt;    (obj &amp;#039set-int-field 5)&lt;br /&gt;    (obj &amp;#039some-action)&lt;br /&gt;    (obj &amp;#039set-str-field &amp;#039abc)&lt;br /&gt;    (obj &amp;#039msg "\nstr-field : " (obj &amp;#039get-str-field) &lt;br /&gt;	      "\nint-field : " (obj &amp;#039get-int-field))&lt;br /&gt;    (newline)))&lt;br /&gt;&lt;br /&gt;(test-base-obj)&lt;br /&gt;(test-parent-obj)&lt;br /&gt;(test-child-obj)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;Как видно из кода система получилась в стиле "передачи сообщений объекту", где в качестве "объектов" выступают функции-замыкания, сохраняющие свое состояние(поля) а в качестве "классов" -- функции высшего порядка, возвращающие(создающие) "объекты".&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;2. Как известно Лисп превосходно подходит для реализации языков, например всяких DSL/eDSL. Говорят что на Лиспе Вы не описываете как решить задачу, а подгоняете язык под задачу до тех пор, пока не создадите язык, на котором задача формулируется легко и просто. Приведу несколько пример, как можно расширить синтаксис/семантику Scheme.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;2.1. Один мой знакомый очень любит язык Pascal. Специально для него вот немного сахарку в Схему, предоставляющую пару паскалеподобных конструкций:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(define-syntax for&lt;br /&gt;  (syntax-rules (:= to do)&lt;br /&gt;    ((_ i := a to n do e ...)&lt;br /&gt;     (if (&amp;lt; a n)&lt;br /&gt;         (let ((i a) &lt;br /&gt;	       (f (lambda (i f)&lt;br /&gt;		    (if (&amp;lt;= i n)&lt;br /&gt;		        (begin&lt;br /&gt;			  e ...&lt;br /&gt;			  (f (+ i 1) f))))))&lt;br /&gt;	   (f i f))))))&lt;br /&gt;&lt;br /&gt;(define-syntax while&lt;br /&gt;  (syntax-rules (do)&lt;br /&gt;    ((_ s do e ...)&lt;br /&gt;     (let ((f (lambda (f)&lt;br /&gt;		(if s&lt;br /&gt;		    (begin&lt;br /&gt;		      e ...&lt;br /&gt;		      (f f))))))&lt;br /&gt;       (f f)))))&lt;br /&gt;&lt;br /&gt;(define-syntax repeat&lt;br /&gt;  (syntax-rules (until)&lt;br /&gt;    ((_ (e ...) until s)&lt;br /&gt;     (let ((f (lambda (f)&lt;br /&gt;		(begin&lt;br /&gt;		  e ...&lt;br /&gt;		  (if s (f f))))))&lt;br /&gt;       (f f)))))&lt;br /&gt;&lt;br /&gt;(define integer integer?)&lt;br /&gt;(define real    real?)&lt;br /&gt;(define char    char?)&lt;br /&gt;(define TString string?)&lt;br /&gt;(define TVector vector?)&lt;br /&gt;(define TPair   pair?)&lt;br /&gt;(define TList   list?)&lt;br /&gt;&lt;br /&gt;(define-syntax function&lt;br /&gt;  (syntax-rules (:)&lt;br /&gt;    ((_ name ((a1 : t1) (a2 : t2) ...) : type &lt;br /&gt;	(e1 e2 ...))&lt;br /&gt;     (define (name a1 a2 ...)&lt;br /&gt;       (let &lt;br /&gt;	 ((result&lt;br /&gt;	    (if (and (t1 a1) (t2 a2) ...)&lt;br /&gt;	        (begin e1 e2 ...)&lt;br /&gt;		(begin&lt;br /&gt;	          (message "* ERROR: type mismatch in function ``(" &amp;#039name &lt;br /&gt;			   " " &amp;#039((a1 : t1) (a2 : t2) ...) &lt;br /&gt;		           " : " &amp;#039type ")&amp;#039&amp;#039:\n         (" &amp;#039name &lt;br /&gt;			   " " `,(list a1 a2 ...) ")")&lt;br /&gt;		  &amp;#039null))))&lt;br /&gt;	 (if (type result)&lt;br /&gt;	     result&lt;br /&gt;	     (if (eq? result &amp;#039null)&lt;br /&gt;	         (message "         function returns `null&amp;#039")&lt;br /&gt;	         (message "* ERROR: wrong result type in function ``(" &amp;#039name&lt;br /&gt;			  " " &amp;#039((a1 : t1) (a2 : t2) ...)&lt;br /&gt;			  " : " &amp;#039type ")&amp;#039&amp;#039:\n         (" &amp;#039name&lt;br /&gt;			  " " `,(list a1 a2 ...) ") -&amp;gt; " result))))))))&lt;br /&gt;&lt;br /&gt;(define-syntax procedure&lt;br /&gt;  (syntax-rules (:)&lt;br /&gt;    ((_ name ((a1 : t1) (a2 : t2) ...) &lt;br /&gt;	(e1 e2 ...))&lt;br /&gt;     (define (name a1 a2 ...)&lt;br /&gt;       (if (and (t1 a1) (t2 a2) ...)&lt;br /&gt;	   (begin&lt;br /&gt;	     (begin e1 e2 ...)&lt;br /&gt;	     &amp;#039null)&lt;br /&gt;	   (message "* ERROR: type mismatch in procedure (" &amp;#039name &lt;br /&gt;		    " "  &amp;#039((a1 : t1) (a2 : t2) ...) &lt;br /&gt;		    "):\n         (" &amp;#039name " " `,(list a1 a2 ...) ")"))))))&lt;br /&gt;&lt;br /&gt;(define-syntax [&lt;br /&gt;  (syntax-rules (.. ])&lt;br /&gt;    ((_ x0 .. xN ])&lt;br /&gt;     (let* ((dx (if (&amp;lt; x0 xN) 1 -1)) &lt;br /&gt;	    (f (lambda (x f)&lt;br /&gt;		 (if (= x xN)&lt;br /&gt;		     (cons x &amp;#039())&lt;br /&gt;		     (cons x (f (+ x dx) f))))))&lt;br /&gt;       (f x0 f)))&lt;br /&gt;    ((_ x0 x1 .. xN ])&lt;br /&gt;     (let* ((dx (- x1 x0))&lt;br /&gt;	    (f (lambda (x f)&lt;br /&gt;		 (if (&amp;gt; x xN)&lt;br /&gt;		     &amp;#039()&lt;br /&gt;		     (cons x (f (+ x dx) f))))))&lt;br /&gt;       (f x0 f)))))&lt;br /&gt;&lt;br /&gt;(message ([ 1 .. 20 ]))&lt;br /&gt;(message ([ 1 3 .. 20 ]))&lt;br /&gt;(message (apply + ([ 1 3 .. 20 ])))&lt;br /&gt;&lt;br /&gt;;------------------------------&lt;br /&gt;&lt;br /&gt;(function summ-func ((a : integer) (b : integer)) : integer &lt;br /&gt;    (  ;begin&lt;br /&gt;	(+ a b)&lt;br /&gt;    )) ;end&lt;br /&gt;&lt;br /&gt;(message (summ-func 1 2))&lt;br /&gt;(message (summ-func 1 2.0))&lt;br /&gt;(message (summ-func 1 2.1))&lt;br /&gt;&lt;br /&gt;(function summ-func-2 ((a : integer) (b : integer)) : integer&lt;br /&gt;    (  ;begin&lt;br /&gt;	(cons a b)&lt;br /&gt;    )) ;end&lt;br /&gt;&lt;br /&gt;(message (summ-func-2 1 2))&lt;br /&gt;&lt;br /&gt;(procedure summ-proc ((a : integer) (b : integer)) &lt;br /&gt;    (  ;begin&lt;br /&gt;	(display (+ a b))&lt;br /&gt;	(newline)&lt;br /&gt;    )) ;end&lt;br /&gt;&lt;br /&gt;(summ-proc 1 2)&lt;br /&gt;(summ-proc 1 2.0)&lt;br /&gt;(summ-proc 1 2.1)&lt;br /&gt;&lt;br /&gt;;------------------------------&lt;br /&gt;&lt;br /&gt;(display "for i in [1..10] do : ")&lt;br /&gt;&lt;br /&gt;(for i := 1 to 10 do&lt;br /&gt;  (display i)&lt;br /&gt;  (display " "))&lt;br /&gt;&lt;br /&gt;(newline)&lt;br /&gt;&lt;br /&gt;(display "while  i  &amp;lt;  10  do : ")&lt;br /&gt;&lt;br /&gt;(define x 0)&lt;br /&gt;&lt;br /&gt;(while (&amp;lt; x 10) do&lt;br /&gt;  (display x)&lt;br /&gt;  (display " ")&lt;br /&gt;  (set! x (+ x 1)))&lt;br /&gt;&lt;br /&gt;(newline)&lt;br /&gt;&lt;br /&gt;(display "repeat until x &amp;lt; 10 : ")&lt;br /&gt;&lt;br /&gt;(set! x 0)&lt;br /&gt;&lt;br /&gt;(repeat &lt;br /&gt;  ((display x)&lt;br /&gt;   (display " ")&lt;br /&gt;   (set! x (+ x 1)))&lt;br /&gt;  until (&amp;lt; x 10))&lt;br /&gt;&lt;br /&gt;(newline)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;2.2. А вот пример реализации простейшей базы данных и sql-еподобных языковых конструкций для работы с ней(здесь был использован опыт из пункта 1 про ООП)&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(define *current-db* &amp;#039())&lt;br /&gt;&lt;br /&gt;(define number  (cons &amp;#039number number?))&lt;br /&gt;(define char    (cons &amp;#039char char?))&lt;br /&gt;(define varchar (cons &amp;#039varchar string?))&lt;br /&gt;(define bool    (cons &amp;#039bool boolean?))&lt;br /&gt;(define int     (cons &amp;#039int integer?))&lt;br /&gt;(define symbol  (cons &amp;#039symbol symbol?))&lt;br /&gt;&lt;br /&gt;(define (make-field name type default-value)&lt;br /&gt;  (let ((name   name)&lt;br /&gt;	(type   type)&lt;br /&gt;	(defval default-value)&lt;br /&gt;	(vals &amp;#039()))&lt;br /&gt;    (lambda (action . args)&lt;br /&gt;      (cond&lt;br /&gt;	((eq? action &amp;#039get-name) name)&lt;br /&gt;	((eq? action &amp;#039get-values) vals)&lt;br /&gt;	((eq? action &amp;#039get-type) (car type))&lt;br /&gt;	((eq? action &amp;#039get-value)&lt;br /&gt;	 (if (not (null? args))&lt;br /&gt;	   (if (integer? (car args))&lt;br /&gt;	       (let find-val ((ls vals)&lt;br /&gt;			      (n (car args)))&lt;br /&gt;		 (if (null? ls)&lt;br /&gt;		     &amp;#039()&lt;br /&gt;		     (if (= n 0)&lt;br /&gt;			 (car ls)&lt;br /&gt;			 (find-val (cdr ls) (- n 1))))))&lt;br /&gt;	   &amp;#039()))&lt;br /&gt;	((eq? action &amp;#039set-value)&lt;br /&gt;	 (if (not (null? args))&lt;br /&gt;	   (if ((cdr type) (car args))&lt;br /&gt;	     (if (not (null? (cdr args)))&lt;br /&gt;	       (if (integer? (cadr args))&lt;br /&gt;	           (set! vals (set-ref vals (car args) (cadr args))))))))&lt;br /&gt;	((eq? action &amp;#039add-value)&lt;br /&gt;	 (if (not (null? args))&lt;br /&gt;	   (if ((cdr type) (car args))&lt;br /&gt;	       (set! vals (append vals (list (car args)))))&lt;br /&gt;	   (set! vals (append vals (list defval)))))))))&lt;br /&gt;&lt;br /&gt;(define (make-db name)&lt;br /&gt;  (let ((name name)&lt;br /&gt;	(tables &amp;#039()))&lt;br /&gt;    (lambda (action . args)&lt;br /&gt;      (cond ((eq? action &amp;#039add-table)&lt;br /&gt;	     (set! tables (cons args tables)))&lt;br /&gt;	    ((eq? action &amp;#039get-tables)&lt;br /&gt;	     (if (not (null? tables))&lt;br /&gt;		 (map car tables)))&lt;br /&gt;	     ;tables)&lt;br /&gt;	    (else&lt;br /&gt;	      (if (symbol? action)&lt;br /&gt;		  (let &lt;br /&gt;		    ((result (let find-table ((table action)&lt;br /&gt;					      (tables tables))&lt;br /&gt;			       (if (null? tables)&lt;br /&gt;				   &amp;#039null&lt;br /&gt;				   (if (eq? table (caar tables))&lt;br /&gt;				       (cadar tables)&lt;br /&gt;				       (find-table table (cdr tables)))))))&lt;br /&gt;		    (if (eq? result &amp;#039null)&lt;br /&gt;			(lambda args&lt;br /&gt;			  (message "*ERROR* " name ": no tables with name `" action "&amp;#039 found\n"))&lt;br /&gt;			result))&lt;br /&gt;		  (message "*ERROR* " name ": wrong type of action")))))))&lt;br /&gt;&lt;br /&gt;(define (make-table name columns)&lt;br /&gt;  (let ((name name)&lt;br /&gt;	(columns columns))&lt;br /&gt;    (lambda (action . args)&lt;br /&gt;      (cond &lt;br /&gt;	((eq? action &amp;#039get-name) name)&lt;br /&gt;	((eq? action &amp;#039get-columns) &lt;br /&gt;	 (map (lambda (col) &lt;br /&gt;		(cons (col &amp;#039get-name) (col &amp;#039get-values)))&lt;br /&gt;	      columns))&lt;br /&gt;	((eq? action &amp;#039select-column)&lt;br /&gt;	 (if (not (null? args))&lt;br /&gt;	   (if (symbol? (car args))&lt;br /&gt;	       (let find-cols ((cols columns))&lt;br /&gt;		 (cond&lt;br /&gt;		   ((null? cols) &amp;#039null)&lt;br /&gt;		   ((eq? ((car cols) &amp;#039get-name) &lt;br /&gt;			 (car args))&lt;br /&gt;		    (cons ((car cols) &amp;#039get-name) &lt;br /&gt;			  ((car cols) &amp;#039get-values)))&lt;br /&gt;		   (else (find-cols (cdr cols))))))))&lt;br /&gt;	((eq? action &amp;#039append-record)&lt;br /&gt;	 (let add-values ((cols columns)&lt;br /&gt;			  (vals args))&lt;br /&gt;	   (if (not (null? cols))&lt;br /&gt;	       (if (null? vals)&lt;br /&gt;		   (begin&lt;br /&gt;		     ((car cols) &amp;#039add-value ((car cols))&lt;br /&gt;		     (add-values (cdr cols) &amp;#039())))&lt;br /&gt;		   (begin&lt;br /&gt;		     ((car cols) &amp;#039add-value (car vals))&lt;br /&gt;		     (add-values (cdr cols) (cdr vals)))))))))))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define-syntax use&lt;br /&gt;  (syntax-rules ()&lt;br /&gt;    ((_ db)&lt;br /&gt;     (set! *current-db* db))))&lt;br /&gt;&lt;br /&gt;(define-syntax create&lt;br /&gt;  (syntax-rules (field : table database)&lt;br /&gt;    ((_ field name : type (default-value))&lt;br /&gt;     (define name (make-field &amp;#039name type default-value)))&lt;br /&gt;    ((_ table name ((f t v) ...))&lt;br /&gt;     (let ((table (make-table &amp;#039name &lt;br /&gt;		    (list (make-field &amp;#039f t v)&lt;br /&gt;			  ...))))&lt;br /&gt;       (*current-db* &amp;#039add-table (table &amp;#039get-name) table)))&lt;br /&gt;    ((_ database name)&lt;br /&gt;     (define name (make-db &amp;#039name)))))&lt;br /&gt;&lt;br /&gt;(define-syntax insert&lt;br /&gt;  (syntax-rules (into values:)&lt;br /&gt;    ((_ into table values: v ...)&lt;br /&gt;     ((*current-db* &amp;#039table) &amp;#039append-record v ...))))&lt;br /&gt;&lt;br /&gt;(define print &lt;br /&gt;  (lambda (ls)&lt;br /&gt;    ;(message ls)&lt;br /&gt;    (if (pair? ls)&lt;br /&gt;      (if (not (null? (car ls)))&lt;br /&gt;        (begin&lt;br /&gt;	  (for-each (lambda (x) &lt;br /&gt;		      (display x) &lt;br /&gt;		      (display "\t"))&lt;br /&gt;		    (map car ls))&lt;br /&gt;	  (display "\n")&lt;br /&gt;	  (print (map cdr ls)))))))&lt;br /&gt;&lt;br /&gt;(define-syntax select&lt;br /&gt;  (syntax-rules (* from)&lt;br /&gt;    ((_ * from table)&lt;br /&gt;     (print ((*current-db* &amp;#039table) &amp;#039get-columns)))&lt;br /&gt;    ((_ (field ...) from table)&lt;br /&gt;     (print (list ((*current-db* &amp;#039table) &amp;#039select-column &amp;#039field)&lt;br /&gt;		  ...)))&lt;br /&gt;    ((_ ((f1 ...) ...) (from t1 ...))&lt;br /&gt;     (begin&lt;br /&gt;       (let ((table &amp;#039t1))&lt;br /&gt;	 (message ((*current-db* table) &amp;#039get-name) ": ")&lt;br /&gt;         (print (list ((*current-db* table) &amp;#039select-column &amp;#039f1)&lt;br /&gt;		      ...))&lt;br /&gt;	 (newline))&lt;br /&gt;       ...))))&lt;br /&gt;&lt;br /&gt;;------------------------------------------------------&lt;br /&gt;&lt;br /&gt;(define-syntax test&lt;br /&gt;  (syntax-rules ()&lt;br /&gt;    ((_ (f ...))&lt;br /&gt;     (begin&lt;br /&gt;       (message ";;; " &amp;#039(f ...) ": ")&lt;br /&gt;       (f ...)))&lt;br /&gt;    ((_ displayfunc (f ...))&lt;br /&gt;     (begin&lt;br /&gt;       (message ";;; " &amp;#039(f ...) ": ")&lt;br /&gt;       (displayfunc (f ...))))))&lt;br /&gt;&lt;br /&gt;;------------------------------------------------------&lt;br /&gt;&lt;br /&gt;(define main-test&lt;br /&gt;  (lambda ()&lt;br /&gt;    (create database test-db)&lt;br /&gt;    (create database other-db)&lt;br /&gt;&lt;br /&gt;    (use test-db)&lt;br /&gt;&lt;br /&gt;    (create table table-1 ((name varchar "")&lt;br /&gt;			   (age  int      0)&lt;br /&gt;			   (sex  symbol &amp;#039male)))&lt;br /&gt;&lt;br /&gt;    (create table table-2 ((name varchar "")&lt;br /&gt;			   (age  int      0)&lt;br /&gt;			   (sex  symbol &amp;#039male)&lt;br /&gt;			   (prof varchar "")))&lt;br /&gt;&lt;br /&gt;    (test message (*current-db* &amp;#039get-tables))&lt;br /&gt;    (test message ((test-db &amp;#039table-1) &amp;#039get-columns))&lt;br /&gt;    (test message ((test-db &amp;#039table-2) &amp;#039get-columns))&lt;br /&gt;&lt;br /&gt;    (insert into table-1 values: "vasya" 22 &amp;#039male)&lt;br /&gt;    (insert into table-1 values: "kolya" 24 &amp;#039male)&lt;br /&gt;&lt;br /&gt;    (test message ((*current-db* &amp;#039table-1) &amp;#039get-columns))&lt;br /&gt;    (test message ((*current-db* &amp;#039table-1) &amp;#039select-column &amp;#039age))&lt;br /&gt;&lt;br /&gt;    (test (select (name age) from table-1))&lt;br /&gt;    (test (select * from table-1))&lt;br /&gt;&lt;br /&gt;    (insert into table-2 values: "lena" 23 &amp;#039female "manager")&lt;br /&gt;&lt;br /&gt;    (test (select * from table-2))&lt;br /&gt;    (test (select ((name age) (name sex prof)) (from table-1 table-2)))&lt;br /&gt;    (test (select * from table-2))&lt;br /&gt;&lt;br /&gt;    (use other-db)&lt;br /&gt;&lt;br /&gt;    (test (select * from table-2))&lt;br /&gt;&lt;br /&gt;    (create table table-3 ((id     int      0) &lt;br /&gt;			   (name   varchar "") &lt;br /&gt;			   (f_name varchar "")&lt;br /&gt;			   (dep_id int      0)))&lt;br /&gt;&lt;br /&gt;    (test (select * from table-3))&lt;br /&gt;&lt;br /&gt;    (insert into table-3 values: 1 "name" "family name" 2)&lt;br /&gt;&lt;br /&gt;    (test (select * from table-3))&lt;br /&gt;&lt;br /&gt;    (use test-db)))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define field-object-test&lt;br /&gt;  (lambda ()&lt;br /&gt;    (create field age : int (0))&lt;br /&gt;    &lt;br /&gt;    (test message (age &amp;#039get-name))&lt;br /&gt;    (test message (age &amp;#039get-values))&lt;br /&gt;    (test message (age &amp;#039get-value))&lt;br /&gt;    (test message (age &amp;#039get-value 2))&lt;br /&gt;    &lt;br /&gt;    (age &amp;#039add-value 23)&lt;br /&gt;    &lt;br /&gt;    (test message (age &amp;#039get-value 0))&lt;br /&gt;    (test message (age &amp;#039get-values))&lt;br /&gt;    &lt;br /&gt;    (age &amp;#039set-value 25 0)&lt;br /&gt;    &lt;br /&gt;    (test message (age &amp;#039get-values))))&lt;br /&gt;&lt;br /&gt;;(field-object-test)&lt;br /&gt;&lt;br /&gt;(main-test)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;2.3. А теперь попробуем реализовать свой язык, например нечто похожее на Форт, ибо он, пожалуй, еще проще Лиспа:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(define ~ `~)&lt;br /&gt;(define begin-declare `[)&lt;br /&gt;(define delim-declare `|)&lt;br /&gt;(define end-declare   `])&lt;br /&gt;(define if-expr   `if)&lt;br /&gt;(define else-expr `else)&lt;br /&gt;(define then-expr `then)&lt;br /&gt;(define assign `&amp;gt;&amp;gt;)&lt;br /&gt;(define norm-recursion &amp;#039normal)&lt;br /&gt;(define tail-recursion &amp;#039tail)&lt;br /&gt;&lt;br /&gt;(define basic-dictionary&lt;br /&gt;  (list&lt;br /&gt;   `(+  ~ ,(list +))&lt;br /&gt;   `(-  ~ ,(list -))&lt;br /&gt;   `(*  ~ ,(list *))&lt;br /&gt;   `(/  ~ ,(list /))&lt;br /&gt;   `(&amp;gt;  ~ ,(list &amp;gt;))&lt;br /&gt;   `(&amp;lt;  ~ ,(list &amp;lt;))&lt;br /&gt;   `(^  ~ ,(list (lambda args (cdr args))))&lt;br /&gt;   `(&amp;amp;  ~ ,(list (lambda args (car args))))&lt;br /&gt;   `(*&amp;gt; ~ ,(list (lambda args (apply printf args) &amp;#039())))&lt;br /&gt;   `(@&amp;gt; ~ ,(list (lambda args (apply printl args) &amp;#039())))&lt;br /&gt;   `(true  ~ ,(list #t))&lt;br /&gt;   `(false ~ ,(list #f))&lt;br /&gt;   `(null? ~ ,(list (lambda args (null? args))))&lt;br /&gt;  ))&lt;br /&gt;&lt;br /&gt;(define eof-error "unexpected EOF")&lt;br /&gt;(define syntax-error "wrong syntax")&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define (declare name text)&lt;br /&gt;&lt;br /&gt;  (define (make-body params body text braces)&lt;br /&gt;    (cond&lt;br /&gt;&lt;br /&gt;      ((null? text)&lt;br /&gt;       (error declare "`" name "&amp;#039: " eof-error))&lt;br /&gt;&lt;br /&gt;      ((eq? (car text) begin-declare)&lt;br /&gt;       (make-body&lt;br /&gt;	 params&lt;br /&gt;	 (cons (car text) body)&lt;br /&gt;	 (cdr text)&lt;br /&gt;	 (+ braces 1)))&lt;br /&gt;&lt;br /&gt;      ((eq? (car text) end-declare)&lt;br /&gt;       (if (= 0 braces)&lt;br /&gt;	   (list&lt;br /&gt;	     (list&lt;br /&gt;	       name&lt;br /&gt;	       params&lt;br /&gt;	       (reverse body))&lt;br /&gt;	     (cdr text))&lt;br /&gt;	   (make-body&lt;br /&gt;	     params&lt;br /&gt;	     (cons (car text) body)&lt;br /&gt;	     (cdr text)&lt;br /&gt;	     (- braces 1))))&lt;br /&gt;      (else&lt;br /&gt;	(make-body&lt;br /&gt;	  params&lt;br /&gt;	  (cons (car text) body)&lt;br /&gt;	  (cdr text)&lt;br /&gt;	  braces))))&lt;br /&gt;&lt;br /&gt;  (define (make-head params text)&lt;br /&gt;    (cond&lt;br /&gt;&lt;br /&gt;      ((null? text)&lt;br /&gt;       (error declare "`" name "&amp;#039: " eof-error))&lt;br /&gt;&lt;br /&gt;      ((or (eq? (car text) begin-declare)&lt;br /&gt;	   (eq? (car text) end-declare)&lt;br /&gt;	   (not (symbol? (car text))))&lt;br /&gt;       (error declare "`" name "&amp;#039: " syntax-error))&lt;br /&gt;&lt;br /&gt;      ((eq? (car text) delim-declare)&lt;br /&gt;       (make-body&lt;br /&gt;	 (if (null? params) ~ params)&lt;br /&gt;	 &amp;#039()&lt;br /&gt;	 (cdr text)&lt;br /&gt;	 0))&lt;br /&gt;&lt;br /&gt;      (else&lt;br /&gt;	(make-head&lt;br /&gt;	  (cons (car text) params)&lt;br /&gt;	  (cdr text)))))&lt;br /&gt;&lt;br /&gt;  (make-head &amp;#039() text))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define (make-then-else text)&lt;br /&gt;&lt;br /&gt;  (define (make-t-e then-text else-text text)&lt;br /&gt;    (cond&lt;br /&gt;&lt;br /&gt;      ((null? text)&lt;br /&gt;       (error make-then-else eof-error))&lt;br /&gt;&lt;br /&gt;      ((eq? (car text) else-expr)&lt;br /&gt;       (make-t-e &lt;br /&gt;	 &amp;#039() &lt;br /&gt;	 then-text &lt;br /&gt;	 (cdr text)))&lt;br /&gt;&lt;br /&gt;      ((eq? (car text) then-expr)&lt;br /&gt;       (list&lt;br /&gt;	 (reverse then-text)&lt;br /&gt;	 (reverse else-text)&lt;br /&gt;	 (cdr text)))&lt;br /&gt;&lt;br /&gt;      (else&lt;br /&gt;	(make-t-e&lt;br /&gt;	  (cons (car text) then-text)&lt;br /&gt;	  else-text&lt;br /&gt;	  (cdr text)))))&lt;br /&gt;&lt;br /&gt;  (make-t-e &amp;#039() &amp;#039() text))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define (make-env stack word)&lt;br /&gt;&lt;br /&gt;  (define (make-e stack params env)&lt;br /&gt;    (cond&lt;br /&gt;&lt;br /&gt;      ((null? params)&lt;br /&gt;       (list env stack))&lt;br /&gt;&lt;br /&gt;      ((null? stack)&lt;br /&gt;       (error make-env eof-error))&lt;br /&gt;&lt;br /&gt;      (else&lt;br /&gt;	(make-e&lt;br /&gt;	  (cdr stack)&lt;br /&gt;	  (cdr params)&lt;br /&gt;	  (cons&lt;br /&gt;	    (list (car params) ~ (list (car stack)))&lt;br /&gt;	    env)))))&lt;br /&gt;&lt;br /&gt;  (make-e stack word &amp;#039()))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define (redeclare word words)&lt;br /&gt;  (define (make-words word head tail)&lt;br /&gt;    (cond&lt;br /&gt;      ((null? tail)&lt;br /&gt;       (reverse head))&lt;br /&gt;      ((eq? (car word) (caar tail))&lt;br /&gt;       (append&lt;br /&gt;	 (reverse head)&lt;br /&gt;	 (cons word (cdr tail))))&lt;br /&gt;      (else&lt;br /&gt;        (make-words&lt;br /&gt;	  word&lt;br /&gt;	  (cons (car tail) head)&lt;br /&gt;	  (cdr tail)))))&lt;br /&gt;  (make-words word &amp;#039() words))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define (*iter* stack text words env recursion-type)&lt;br /&gt;  ;(printl (length words) (length env))&lt;br /&gt;  ;(printl (length stack) (length text))&lt;br /&gt;  ;(printl words)&lt;br /&gt;  ;(printl env)&lt;br /&gt;  (cond&lt;br /&gt;&lt;br /&gt;    ((null? text) stack)&lt;br /&gt;    &lt;br /&gt;    ((or (number?  (car text))&lt;br /&gt;	 (boolean? (car text))&lt;br /&gt;	 (char?    (car text))&lt;br /&gt;	 (string?  (car text)))&lt;br /&gt;     (*iter*&lt;br /&gt;       (cons (car text) stack)&lt;br /&gt;       (cdr text)&lt;br /&gt;       words&lt;br /&gt;       env&lt;br /&gt;       recursion-type))&lt;br /&gt;    &lt;br /&gt;    ((symbol? (car text))&lt;br /&gt;     (let ((sym (car text)))&lt;br /&gt;       (cond&lt;br /&gt;&lt;br /&gt;	 ((eq? sym begin-declare)&lt;br /&gt;	  (let ((word/text &lt;br /&gt;		  (declare (cadr text) (cddr text))))&lt;br /&gt;	    (*iter*&lt;br /&gt;	      stack&lt;br /&gt;	      (cadr word/text)&lt;br /&gt;	      (if (eq? recursion-type norm-recursion)&lt;br /&gt;		  (cons (car word/text) words)&lt;br /&gt;		  (redeclare (car word/text) words))&lt;br /&gt;	      env&lt;br /&gt;	      recursion-type)))&lt;br /&gt;&lt;br /&gt;	 ((eq? sym if-expr)&lt;br /&gt;	  (let ((condition (car stack)) &lt;br /&gt;		(then/else/text&lt;br /&gt;		  (make-then-else (cdr text))))&lt;br /&gt;	    (if condition&lt;br /&gt;	        (*iter*&lt;br /&gt;		  (cdr stack)&lt;br /&gt;		  (append (car   then/else/text)&lt;br /&gt;			  (caddr then/else/text))&lt;br /&gt;		  words&lt;br /&gt;		  env&lt;br /&gt;		  recursion-type)&lt;br /&gt;	        (*iter*&lt;br /&gt;		  (cdr stack)&lt;br /&gt;		  (append (cadr  then/else/text)&lt;br /&gt;			  (caddr then/else/text))&lt;br /&gt;		  words&lt;br /&gt;		  env&lt;br /&gt;		  recursion-type))))&lt;br /&gt;&lt;br /&gt;	 ((eq? sym assign)&lt;br /&gt;	  (*iter*&lt;br /&gt;	    &amp;#039()&lt;br /&gt;	    (cddr text)&lt;br /&gt;	    (cons (list (cadr text) ~ stack)&lt;br /&gt;		  words)&lt;br /&gt;	    env&lt;br /&gt;	    recursion-type))&lt;br /&gt;&lt;br /&gt;	 (else&lt;br /&gt;	   (let ((word&lt;br /&gt;		   (cond &lt;br /&gt;		     ((assoc sym env) =&amp;gt; (lambda (x) x))&lt;br /&gt;		     ((assoc sym words) =&amp;gt; (lambda (x) x))&lt;br /&gt;		     (else&lt;br /&gt;		       (begin&lt;br /&gt;		         (error *iter* "word `" sym &lt;br /&gt;				"&amp;#039 not found in dictionary")&lt;br /&gt;			 (list printl))))))&lt;br /&gt;	     (cond&lt;br /&gt;&lt;br /&gt;	       ((eq? (cadr word) ~)&lt;br /&gt;		(*iter*&lt;br /&gt;		  stack&lt;br /&gt;		  (append (caddr word) (cdr text))&lt;br /&gt;		  words&lt;br /&gt;		  env&lt;br /&gt;		  recursion-type))&lt;br /&gt;&lt;br /&gt;	       ((null? (cdr text))&lt;br /&gt;		(let ((env/stack&lt;br /&gt;			(make-env stack (cadr word))))&lt;br /&gt;		  (*iter*&lt;br /&gt;		    (cadr env/stack)&lt;br /&gt;		    (append (caddr word) (cdr text))&lt;br /&gt;		    words&lt;br /&gt;		    (car env/stack)&lt;br /&gt;		    tail-recursion)))&lt;br /&gt;&lt;br /&gt;	       (else&lt;br /&gt;		 (let ((env/stack&lt;br /&gt;			 (make-env stack (cadr word))))&lt;br /&gt;		   (*iter*&lt;br /&gt;		     (cadr env/stack)&lt;br /&gt;		     (append&lt;br /&gt;		       (*iter*&lt;br /&gt;			 &amp;#039()&lt;br /&gt;			 (caddr word)&lt;br /&gt;			 (append env words)&lt;br /&gt;			 (car env/stack)&lt;br /&gt;			 norm-recursion)&lt;br /&gt;		       (cdr text))&lt;br /&gt;		     words&lt;br /&gt;		     env&lt;br /&gt;		     recursion-type)))))))))&lt;br /&gt;&lt;br /&gt;    (else&lt;br /&gt;      (let ((result&lt;br /&gt;	      (apply&lt;br /&gt;		(car text)&lt;br /&gt;		(reverse stack))))&lt;br /&gt;	(*iter*&lt;br /&gt;	  &amp;#039()&lt;br /&gt;	  (if (null? result)&lt;br /&gt;	      (cdr text)&lt;br /&gt;	      ((if (pair? result) append cons) result (cdr text)))&lt;br /&gt;	  words&lt;br /&gt;	  env&lt;br /&gt;	  recursion-type)))))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(define (run ls)&lt;br /&gt;  (*iter* &amp;#039() ls basic-dictionary &amp;#039() norm-recursion))&lt;br /&gt;&lt;br /&gt;(define (interpretator)&lt;br /&gt;  (let &lt;br /&gt;    ((result&lt;br /&gt;     (run `(&lt;br /&gt;      1 2 7 + 5 6 -	    ; (1 +2 +7) -5 -6 = 10 -5 -6 = -1 ; stack: &amp;lt; -1 ]&lt;br /&gt;      &lt;br /&gt;      [ a | 5 + ]	    ; let a = f(ls) = (ls 5 +)&lt;br /&gt;      [ x | 5 ]		    ; let x = 5&lt;br /&gt;			    ; stack: &amp;lt; -2 -1 ]&lt;br /&gt;      -2 a		    ; a(-2 -1) = -2 -1 +5 = 2 ; stack: &amp;lt; 2 ]&lt;br /&gt;      &lt;br /&gt;      [ square x | x x * ]  ; let square = f(x) = x * x&lt;br /&gt;                            ; stack: &amp;lt; 2 2 ]&lt;br /&gt;      2 square	            ; square(2) = 2 * 2 = 4 ; stack: &amp;lt; 4 2 ]&lt;br /&gt;      &lt;br /&gt;      [ quad x |            ; let quad = f(x) =&lt;br /&gt;	x square square ]   ;   square( square(x) )&lt;br /&gt;&lt;br /&gt;      quad		    ; quad(4) = square( square(4) ) = square(16) = 256 &lt;br /&gt;			    ; stack &amp;lt; 256 2 ]&lt;br /&gt;      x	a		    ; stack &amp;lt; 5 256 2 ]&lt;br /&gt;                            ; a(5 256 2) = +5 +256 +2 +5 = 268 ; stack: &amp;lt; 268 ]&lt;br /&gt;      1500                  ; stack: &amp;lt; 1500 268 ]&lt;br /&gt;&lt;br /&gt;      [ b x y |             ; let b = f(x, y) =&lt;br /&gt;	x y &amp;gt; if            ;   if (x &amp;gt; y) then&lt;br /&gt;	  3 quad   else     ;     square(x)&lt;br /&gt;	  x square then ]   ;   else quad(3)&lt;br /&gt;&lt;br /&gt;      b                     ; b( 268, 1500 ) ; stack: &amp;lt; 81 ]&lt;br /&gt;      &amp;gt;&amp;gt; xx                 ; let xx = 81&lt;br /&gt;      xx null? if           ; if (xx == null) then&lt;br /&gt;	xx ^ else           ;   0&lt;br /&gt;	0    then           ; else cdr(xx) ; stack: &amp;lt; ]&lt;br /&gt;      xx @&amp;gt;                 ; printl(xx) = printl( 81 )&lt;br /&gt;      &lt;br /&gt;      [ yy | 123 ]          ; let yy = 123 ; -- "global" yy&lt;br /&gt;      [ def x |             ; let def = f(x) =&lt;br /&gt;	x xx &amp;gt; if           ;   if (x &amp;gt; xx) then&lt;br /&gt;	  [ yy | xx ] else  ;     let yy = x     ; "local" yy&lt;br /&gt;	  [ yy | x  ] then  ;   else let yy = xx ; "local" yy&lt;br /&gt;	yy @&amp;gt; ]             ;   printl(yy)&lt;br /&gt;      &lt;br /&gt;      80 def                ; def(80) = (80 &amp;gt; 81)? = false =&amp;gt; let yy = xx = 81 =&amp;gt; printl(81)&lt;br /&gt;      82 def                ; def(82) = (82 &amp;gt; 81)? = true =&amp;gt; let yy = x = 82 =&amp;gt; print(82)&lt;br /&gt;      yy @&amp;gt; @&amp;gt;              ; printl(yy) = print(123) ; "global" yy&lt;br /&gt;      &lt;br /&gt;      [ n? |&lt;br /&gt;	null? if&lt;br /&gt;	  1 else&lt;br /&gt;	  0 then ]&lt;br /&gt;      &lt;br /&gt;      n? 2 n? @&amp;gt;&lt;br /&gt;&lt;br /&gt;      [ abs x |&lt;br /&gt;	x 0 &amp;lt; if&lt;br /&gt;	  x      else&lt;br /&gt;	  x -1 * then ]&lt;br /&gt;      &lt;br /&gt;      2 abs -2 abs @&amp;gt; @&amp;gt;&lt;br /&gt;      &lt;br /&gt;      [ fac n |&lt;br /&gt;	n 2 &amp;lt; if&lt;br /&gt;	  n 1 - fac n * else&lt;br /&gt;	  1 then ]&lt;br /&gt;      &lt;br /&gt;      "recursive factorial: " @&amp;gt;&lt;br /&gt;      "34 ! = " *&amp;gt; 34 fac @&amp;gt;&lt;br /&gt;      @&amp;gt;&lt;br /&gt;&lt;br /&gt;      [ mul x y | x y * ]&lt;br /&gt;&lt;br /&gt;      [ test x |&lt;br /&gt;	x "! = " *&amp;gt; &lt;br /&gt;	x fac-i @&amp;gt; ]&lt;br /&gt;&lt;br /&gt;      [ fac-i n |&lt;br /&gt;	[ f-iter n acc |&lt;br /&gt;	  2 n &amp;gt; if&lt;br /&gt;	    n 1 - acc n mul f-iter &lt;br /&gt;	  else&lt;br /&gt;	    acc &lt;br /&gt;	  then ]&lt;br /&gt;	n 1 f-iter ]&lt;br /&gt;      &lt;br /&gt;      "iterative factorial: " @&amp;gt;&lt;br /&gt;      12 test&lt;br /&gt;&lt;br /&gt;      [ add x y | x y + ]&lt;br /&gt;&lt;br /&gt;      [ cycle x y |&lt;br /&gt;	[ abc | 2 ]&lt;br /&gt;	0 x &amp;lt; if&lt;br /&gt;	    y *&amp;gt; x y 1 add cycle &lt;br /&gt;	  then ]&lt;br /&gt;      &lt;br /&gt;      1 1 cycle&lt;br /&gt;     ))))&lt;br /&gt;    (display "done: stack: ")&lt;br /&gt;    (if (null? result)&lt;br /&gt;	(display "()")&lt;br /&gt;	(apply printf result))&lt;br /&gt;    (newline)))&lt;br /&gt;&lt;br /&gt;(interpretator)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;Как видно из кода на вновьпридуманном "форте" в его интерпретаторе реализована оптимизация хвостовой рекурсии, в конце приведена проверка этого утверждения -- функция [ cycle x y | ... ] . Я на своем EeePC 1000HD оборвал цикл на 1144131-й итерации, ибо надоело ждать (на работу цикла ушло ~ 5 -- 10 минут). Если кто захочет проверить, отпишитесь о результатах, на какой итерации остановились или был Stack overflow. =) Тем не менее факториал 12345 функция fac-i считает запросто =)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;На сегодня все.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;UPD: я совсем забыл про словарь words, он разрастался при любом типе рекурсии, но я это исправил и поправил соответствующим образом код в статье&lt;/p&gt;</description>
      <author>k0rvin@jabber.ru ( korvin ) </author>
    </item>
    <item>
      <link>http://breys.ru/blog/193.html</link>
      <guid>http://breys.ru/blog/193.html</guid>
      <title>О языке программирования Scheme</title>
      <pubDate>Thu, 26 Feb 2009 15:52:24 +0400</pubDate>
      <description>&lt;h3&gt;&amp;nbsp; 0. Небольшое вступление.&lt;/h3&gt;
&lt;p&gt;&amp;nbsp; Данная заметка посвящена языку программирования(ЯП) Scheme.&lt;/p&gt;
&lt;p&gt;&amp;nbsp; В сети достаточно информации по этому ЯП, например весьма неплохое руководство http://www.scheme.com/tspl2d &lt;br /&gt;(часть описанных мною примеров взяты частично или полностью из этого руководства), кроме того при желании можно найти небезызвестную книгу "Structure and Implementation of Computer Programs" (SICP), являющуюся одной из лучших книг по программированию вообще и по Scheme в частности. Поэтому целью данной заметки является не очередное "пересказывание" этих трудов, а скорее попытка объяснить Scheme, его особенности, возможности так сказать "на пальцах". В частности я буду описывать, что сам уже смог понять, узнать о Scheme и программировании.&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Scheme как и Lisp является мультипарадигменным языком программирования "почти без синтаксиса", разработанный в Массачуссетском Институте Технологий. Некоторые называют Scheme языком функционального программирования(ФП), приравнивая таким образом его к чисто функциональным языкам на подобии Haskell, однако, несмотря на то, что Scheme позволяет писать код в стиле ФП, такое приравнивание некорректно. Более точное и подробное описание языка вы можете найти в Википедии, там же найдете и еще некоторые полезные ссылки.&lt;/p&gt;
&lt;h4&gt;&amp;nbsp; Поскольку до написания этой заметки я уже оставил несколько подобных на паре форумов в сети, то эта, первая, заметка в данном блоге будет относительно более длинной, чем последующие и состоять из вышеупомянутых заметках на форумах.&amp;nbsp;&lt;/h4&gt;
&lt;h4&gt;&amp;nbsp; 1. Немного о "почти отсутствующем синтаксисе".&lt;/h4&gt;
&lt;p&gt;&amp;nbsp; В отличие от более распространенных и привычных ЯП, таких как C, C++, Pascal, Java, PHP и т. д., в Scheme и Lisp используется префиксная запись функций и операторов, а также огромное количество скобок, что может отпугнуть новичков от изучения языка, однако чем дальше вы зайдете в изучении Scheme, тем больше вы будете понимать, что это очень удобная форма записи, открывающая большие возможности для манипулирования кодом и данными. Впрочем не исключен эффект еще большего отторжения =). В этом случае взгляните на Forth, где используется польская, постфиксная нотация, она вам покажется еще более непривычной, и отталкивающей =).&lt;/p&gt;
&lt;p&gt;&amp;nbsp; Итак, вот несколько примеров программ на Scheme:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(* 1 2 3 4 5)&amp;nbsp; ; Произведение чисел от 1 до 5&lt;br /&gt;&lt;br /&gt;(define (square x)&amp;nbsp; ; Объявление функции возведения в квадрат как&lt;br /&gt;&amp;nbsp; (* x x))&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp; произведение аргумента на самого себя&lt;br /&gt;&lt;br /&gt;(define (abs x)&amp;nbsp; ; Объявление функции модуля:&lt;br /&gt;&amp;nbsp; (if (&amp;lt; x 0)&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp; особая форма if вычисляет первый аргумент (функцию &amp;lt;, сравнивающую значение аргумента x с нулем) и &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (- x)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; возвращает результат вычисления второго аргумента, если первый вернул #t (истину) или &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; x))&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; третьего в противном случае&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Как видно из примера, синтаксис действительно очень регулярен и почти отсутсвует, любая функция имеет следующую форму вызова:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(funcname arg1 arg2 arg3 ... argN)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;называемой S-выражением. Границами формы служат круглые скобки, а разделителями имен -- пустое пространство(символы пробела, табуляции и новой строки). Первый символ интерпретируется как вызов функции с ним связанной, для остальных вычисляются значения, с ними связанные, при чем нет никакой разницы, что является значением -- функция или, например, числовая константа, поэтому передача функций как параметров другим функциям является простой и не портит синтаксиса, например: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(define (is func)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; Объявление функции is от func как&lt;br /&gt;&amp;nbsp; (lambda (a b) (func a b)))&amp;nbsp; ;&amp;nbsp;&amp;nbsp; возвращающую функцию от a, b, вычисляющую функцию func от a, b&lt;br /&gt;(define greater? (is &amp;gt;))&lt;br /&gt;(let ((x 1) (y 2))&lt;br /&gt;&amp;nbsp; (greater? x y))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Исключениями являются только особые формы (в данном примере это define и if), которые определяются макросами и тем не менее незначительно отличаются от формы вызова функции. Символ ; означает начало комментария, весь текст, находящийся за ним и до конца строка игнорируется интерпретатором.&lt;br /&gt;&amp;nbsp; Вот и почти весь синтаксис. Некоторые другие "знаки препинания", отличающиеся от вышеуказанной формы синтаксиса и являющиеся в большинстве своем "синтаксическим сахаром" мы рассмотрим позже, по мере необходимости.&lt;/p&gt;
&lt;h2&gt;&amp;nbsp; 2. Немного о списках.&lt;/h2&gt;
&lt;p&gt;&amp;nbsp; Основной структурой данных в Scheme, как и в Lisp, является список. Основные функции работы со списками:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(cons 1 2)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; возвращает пару значений: (1 . 2)&lt;br /&gt;(cons 1 &amp;#039())&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; возвращает список из одного элемента: (1)&lt;br /&gt;(list 1 2 3)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; Возвращает список значений: (1 2 3)&lt;br /&gt;(cons 1 (cons 2 (cons 3 &amp;#039())))&amp;nbsp; ; возвращает список значений: (1 2 3)&lt;br /&gt;(car (list 1 2 3))&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; возвращает значение первого элемента(головы) списка (1 2 3): 1&lt;br /&gt;(cdr (list 1 2 3))&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; возвращает список, начинающийся со второго элемента(хвост) списка (1 2 3): (2 3)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Конструкция &amp;#039() обозначает пустой список, символ &amp;#039 же обозначает цитирование и является синтаксическим сахаром для особой формы (quote ...). Например вызов функции&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(list 1 2 3)&amp;nbsp; ; можно заменить на конструкцию:&lt;br /&gt;&amp;#039(1 2 3)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; Однако не стоит их путать, в отношении констант-значений типа цифр, чисел, строк, заключенных в двойные ковычки, оба выражения равноправны, однако по отношению к символам, связанным с каким-либо значением, дают разный результат, например:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(let ((x 1) (y 2) (z 3))&amp;nbsp;&amp;nbsp; ; Пусть x = 1, y = 2, z = 3, тогда:&lt;br /&gt;&amp;nbsp; (list x y z))&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp; вернет список значений переменных x, y и z: (1 2 3)&lt;br /&gt;(let ((x 1) (y 2) (z 3))&lt;br /&gt;&amp;nbsp; &amp;#039(x y z))&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; вернет список символов x y и z: (x y z)&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;&amp;nbsp; 3. О макросах.&lt;/h2&gt;
&lt;p&gt;&amp;nbsp; Макросы позволяют создавать новые особые формы, расширяя тем самым синтаксис языка. Например:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: comic sans ms,sans-serif; font-size: xx-small;"&gt;(define-syntax my-if&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; ; Объявляем имя синтаксической конструкции&lt;br /&gt;&amp;nbsp; (syntax-rules (then else)&amp;nbsp;&amp;nbsp;&amp;nbsp; ; описываем правила: в первом списке -- (then else) -- &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp; перечисляем слова, которые будут невычисляемыми, а ля "зарезервированные слова"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; в последующих списках описываются шаблоны, которые будет обрабатывать макросом &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp; и собственно обработчики:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: comic sans ms,sans-serif; font-size: xx-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((_ condition then on-true else on-false)&amp;nbsp; ; здесь описываем шаблон конструкции: _ -- сюда подставляется имя макроса, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp; можно написать my-if вместо _ , без разницы&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp; then и else как мы описали раньше просто слово, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp; condition, on-true и on-false -- так сказать локальные переменные макроса, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&amp;nbsp;&amp;nbsp; выражения, переданные в них -- вычисляемые&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;(if condition on-true on-false))&amp;nbsp; ; а это обработчик шаблона. шаблонов может быть несколько, например можно добавить еще 2:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((_ condition then on-true)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;(if condition on-true))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((_ condition else on-false)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;(if (not condition) on-false))&lt;br /&gt;))&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; здесь закрываем списки особых форм syntax-rules и define-syntax.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: comic sans ms,sans-serif; font-size: xx-small;"&gt;; теперь мы можем пользоваться придуманным макросом: &lt;br /&gt;(my-if (&amp;gt; 2 4) then (display "Y\n") else (display "N\n"))&lt;br /&gt;(my-if (&amp;gt; 4 2) then (display "Y\n"))&lt;br /&gt;(my-if (&amp;gt; 4 2) else (display "Y\n"))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Воспользоваться просто определением функции здесь не удалось бы, так как значения аргументов функции вычисляются перед передачей в функцию, т. е. у нас бы в любом случае программа выполнила бы операторы обоих веток, независимо от значения аргумента-условия и чтобы избежать этого, нам пришлось бы каждый раз явно передавать аргументы-ветки через функцию (delay ...) , откладывающую вычисление своего аргумента.&lt;/p&gt;
&lt;p&gt;&amp;nbsp; Еще один пример, показывающий реализацию операторов i++, i--, x += y, x -= y, x *= y и x /= y, содержащий в том числе и элементы метапрограммирования: макрос make-op сам создает для нас макросы, определяющие четыре последних оператора:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(define-syntax make&lt;br /&gt;&amp;nbsp; (syntax-rules ()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((_ op func)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;(define-syntax op&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; (syntax-rules ()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;((_ x y)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; (begin (set! x (func x y)) x)))))))&lt;br /&gt;&lt;br /&gt;(make += +)&lt;br /&gt;(make -= -)&lt;br /&gt;(make *= *)&lt;br /&gt;(make /= /)&lt;br /&gt;&lt;br /&gt;(define-syntax ++&lt;br /&gt;&amp;nbsp; (syntax-rules ()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((_ i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;(begin (set! i (+ i 1)) i))))&lt;br /&gt;&lt;br /&gt;(define-syntax --&lt;br /&gt;&amp;nbsp; (syntax-rules ()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((_ i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;(begin (set! i (- i 1)) i))))&lt;br /&gt;&lt;br /&gt;;--------------------------------&lt;br /&gt;; Пробуем работу: &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;&lt;br /&gt;(define x1 2)&lt;br /&gt;(define x2 3)&lt;br /&gt;(message "x1 = " x1 "; x2 = " x2)&lt;br /&gt;(++ x1) &lt;br /&gt;(+= x2 (-- x2))&lt;br /&gt;(message "x1 = " x1 "; x2 = " x2)&lt;br /&gt;(+= x1 x2) (message "x1 = " x1)&lt;br /&gt;(*= x1 x2) (message "x1 = " x1)&lt;br /&gt;(-= x1 x2) (message "x1 = " x1)&lt;br /&gt;(/= x1 x2) (message "x1 = " x1)&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;&amp;nbsp; 4. О карринге, замыканиях и функциях высшего порядка.&lt;/h2&gt;
&lt;p&gt;&amp;nbsp; Теперь примерчик с каррингом (приведение функции n аргументов к функции одного аргумента, возвращающей функцию n-1 аргументов) и функций высшего порядка (функции, оперирующие другими функциями):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(define (make-val-list v0 dv vN)&lt;br /&gt;&amp;nbsp; (define (make-list v)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (if (= v vN)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (cons v &amp;#039())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (cons v (make-list (+ v dv)))))&lt;br /&gt;&amp;nbsp; (make-list v0))&lt;br /&gt;&lt;br /&gt;(define A-list (make-val-list 1 1 3))&lt;br /&gt;(define x-list (make-val-list 0.2 0.1 1.2))&lt;br /&gt;&lt;br /&gt;(define (y A)&lt;br /&gt;&amp;nbsp; (lambda (x) (- (* A x) (tan (* pi (/ x 4))))))&lt;br /&gt;&lt;br /&gt;(define y-list (map (lambda (A) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; (map (y A) x-list)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; A-list))&lt;br /&gt;&lt;br /&gt;(display (map (lambda (ls) (apply max ls)) y-list))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; В данном коде функция-от(x,A) сведена к функции y(A), возвращающей функцию-от(х), т.е. ее можно было бы применять так:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(let ((A1 1) (x1 0.2))&lt;br /&gt;&amp;nbsp; ((y A1) x1))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Карринг очень похож на замыкание как я понял, только замыкание проявляется в следующих действиях:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(define y1 (y 1)) ; создаст функцию (y1 x) = (- (* 1 x) (tan (* pi (/ x 4))))&lt;br /&gt;(define y2 (y 2)) ; создаст функцию (y1 x) = (- (* 2 x) (tan (* pi (/ x 4))))&lt;br /&gt;(y1 x1)&lt;br /&gt;(y2 x1)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; В примере применялись функции высшего порядка map и apply, они работают следующим образом:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; 1) map применяет переданую ей в качестве переданного аргумента функцию к каждому элементу списка, переданного вторым аргументом, и возвращает список значений-результаттов применения, например&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(define test-list &amp;#039(-2 1 7 0 -5 4))&lt;br /&gt;(map abs test-list)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; вернет список абсолютных величин значений списка test-list: (2 1 7 0 5 4)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; 2) apply применяет переданную ей в качестве первого аргумента функцию ко всем элементам списка, переданного вторым аргументом, &lt;br /&gt;как буд-то они (элементы списка) являются параметрами переданной функции, например функции&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(max -2 1 7 0 -5 4)&amp;nbsp; ; \&lt;br /&gt;(+ -2 1 7 0 -5 4)&amp;nbsp;&amp;nbsp;&amp;nbsp; ; _вернут максимальное значение и сумму значений переданных в качестве параметров соответственно.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;однако попытка вызвать их таким образом:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(max test-list)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : \&lt;br /&gt;(+ test-list)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; _выдаст ошибку. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Это не очень удобно, когда, например, в ходе работы программы генерируется некий список значений, из которого потом нужно выбрать максимальное значение, или сумму подсчитать. Тут-то и приходит на помощь функция apply, которая как-бы раскрывает список, т. е. выражения&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(apply max test-list)&amp;nbsp; ; \&lt;br /&gt;(apply + test-list)&amp;nbsp;&amp;nbsp;&amp;nbsp; ; _эквивалентны выражениям&lt;br /&gt;(max -2 1 7 0 -5 4)&amp;nbsp;&amp;nbsp;&amp;nbsp; ; \&lt;br /&gt;(+ -2 1 7 0 -5 4)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ; _соответственно.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; И в завершении вернемся к каррингу. Как видно из описания функции map, она может оперировать только функциями одной переменной. Вот тут-то к нам и приходят на помощь карринг и замыкания =).&lt;/p&gt;
&lt;h2&gt;&amp;nbsp; 5. Немного о функциях и макросах с произвольным количеством аргументов.&lt;/h2&gt;
&lt;p&gt;&amp;nbsp; Как вы уже заметили, некоторые функции и формы могут принимать произвольное количество аргументов, например:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(+ 1 2 3)&lt;br /&gt;(+ 1 2 3 4)&lt;br /&gt;(and exp1 exp2)&lt;br /&gt;(and exp1 exp2 exp3 exp4)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Чтобы создать подобную функцию, необходимо использовать точечную запись аргументов, например:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(define (message head . tail)&lt;br /&gt;&amp;nbsp; (display head)&lt;br /&gt;&amp;nbsp; (for-each display tail)&lt;br /&gt;&amp;nbsp; (newline))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; В таком определении функции первый аргумент будет передаваться в нее непосредственно, параметром head, а все остальные -- списком tail. Здесь используется еще одна функция высшего порядка for-each, которая применяет функцию, переданную в качестве первого аргумента к каждому элементу списка, переданного вторым аргументом, но в отличие от функции map не возвращает никакого значения. теперь можно так применять функцию message:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(message "Hello World!")&lt;br /&gt;(let ((world "World"))&lt;br /&gt;&amp;nbsp; (message "Hello " world "!"))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Определить форму, принимающую произвольное количество аргумента, можно подобным образом:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(define-syntax and&lt;br /&gt;&amp;nbsp; (syntax-rules ()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((_) #t)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((_ e) e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ((_ e1 e2 e3 ...)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;(if e1 (and e2 e3 ...) #f))))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; Тогда можно будет использовать новую форму таким образом:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new,courier; font-size: xx-small;"&gt;(let ((x&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (x-min 1) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (x-max 3))&lt;br /&gt;&amp;nbsp; (and (&amp;gt; x x-min) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&amp;lt; x x-max) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (not (= x 0))))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; На этом я завершаю свой обзор. Надеюсь он оказался/окажется для кого-то полезным, для кого-то интересным. =)&lt;/p&gt;</description>
      <author>k0rvin@jabber.ru ( korvin ) </author>
    </item>
  </channel>
</rss>

