Scheme/Tutorial/2: различия между версиями

Материал из ALT Linux Wiki
(→‎3 Имена: Исправил выражение в стандарном синтаксисе на синтаксис схемы)
м (вычитка)
 
Строка 1: Строка 1:
==== 3 Имена ====
==== 3 Имена ====


Выражение: <tt>(* 10 50)</tt> хорошо, а: <tt>(* width height)</tt> лучше. <tt>(* 3.1415926 10.5 10.5)</tt> - интригующе, а <tt>(* pi radius radius)</tt> - всё же понятнее, <tt>(+ 2/3 5/7)</tt> - какие-то невзрачные действия с дробями, а <tt>(+ my-piece-of-cake your-piece-of-cake)</tt> - уже обретает смысл.
Выражение: <tt>(* 10 50)</tt> хорошо, а: <tt>(* width height)</tt> лучше. <tt>(* 3.1415926 10.5 10.5)</tt> — интригующе, а <tt>(* pi radius radius)</tt> — всё же понятнее, <tt>(+ 2/3 5/7)</tt> — какие-то невзрачные действия с дробями, а <tt>(+ my-piece-of-cake your-piece-of-cake)</tt> — уже обретает смысл.


Хочется сделать выражения более осмысленные и читаемые. Сказано - сделано. Фраза "Определим b как 5", записывается <tt>(define b 5)</tt>. Сразу несколько примеров:
Хочется сделать выражения более осмысленные и читаемые. Сказано — сделано. Фраза «Определим b как записывается <tt>(define b 5)</tt>. Сразу несколько примеров:
<pre>(define a 3)
<pre>(define a 3)
(define b 4.5)     ; b - это действительное число 4,5
(define b 4.5)     ; b -- это действительное число 4,5
(define c 2/3)              ; c - это рациональное число 2/3 (две третих)
(define c 2/3)              ; c -- это рациональное число 2/3 (две третих)
(define str "some string")  ; str - это строка "some string"
(define str "some string")  ; str -- это строка "some string"
(define width (+ 2 5))      ; width - это сумма 2 и 5, то есть width - это 7</pre>
(define width (+ 2 5))      ; width -- это сумма 2 и 5, то есть width -- это 7</pre>


Если при определении встречается какое-либо выражение, например сумма двух целых чисел из последнего примера, то это выражение вычисляется и переменная полагается равной уже его результату. Кстати <tt>a,b,c,str</tt> и <tt>width</tt> - действительно называются переменными. Вас это совершенно не должно смущать ибо с переменными вы сталкивались ещё в курсе школьной алгебры. Итак, записать <tt>(define w (+ 1 3))</tt> совершенно равносильно тому что записать <tt>(define w 4)</tt>. Либо вы подсчитаете в уме, либо за вас это сделает Scheme.
Если при определении встречается какое-либо выражение, например, сумма двух целых чисел из последнего примера, то это выражение вычисляется и переменная полагается равной уже его результату. Кстати, <tt>a,b,c,str</tt> и <tt>width</tt> действительно называются переменными. Вас это совершенно не должно смущать, ибо с переменными вы сталкивались ещё в курсе школьной алгебры. Итак, записать <tt>(define w (+ 1 3))</tt> совершенно равносильно тому, что записать <tt>(define w 4)</tt>. Либо вы подсчитаете в уме, либо за вас это сделает Scheme.


Ну уж коли мы вспомнили про школу, то теперь мы можем записать известные нам выражения.
Ну уж коли мы вспомнили про школу, то теперь мы можем записать известные нам выражения.
<pre>(+ a b)              ; это a + b, где a и b какие-то переменные
<pre>(+ a b)              ; это a + b, где a и b -- какие-то переменные
(* 2 a)              ; это 2a, где a какая-то переменная
(* 2 a)              ; это 2a, где a -- какая-то переменная
(* a a)              ; это квадрат a
(* a a)              ; это квадрат a
(* c c c)            ; это куб c
(* c c c)            ; это куб c
(+ (* a a) (* b b))  ; это сумма квадратов a и b.</pre>
(+ (* a a) (* b b))  ; это сумма квадратов a и b.</pre>


Теперь вооружившись полученными знаниями мы можем записывать уже гораздо более сложные программы на Scheme, например такую:
Теперь, вооружившись полученными знаниями, мы можем записывать уже гораздо более сложные программы на Scheme — например, такую:
<pre>(define width 3)
<pre>(define width 3)
(define height 5)
(define height 5)
Строка 25: Строка 25:
(* width height)  ; умножить ширину на высоту</pre>
(* width height)  ; умножить ширину на высоту</pre>


Наверное вы заметили, что комментарии к коду я пишу начиная их с <tt>;</tt>. Это не случайно, все комментарии в тексте программы начинаются с символа <tt>;</tt>. Когда интерпретатор или компилятор читает наш код, весь текст начинающийся с <tt>;</tt> и до конца строки он игнорирует.
Наверное, вы заметили, что комментарии к коду я пишу, начиная их с <tt>;</tt>. Это не случайно, все комментарии в тексте программы начинаются с символа <tt>;</tt>. Когда интерпретатор или компилятор читает наш код, весь текст, начинающийся с <tt>;</tt> и до конца строки он игнорирует.


Ещё одна программа:
Ещё одна программа:
Строка 35: Строка 35:
==== 4 Про истину ====
==== 4 Про истину ====


Если говорить кратко "всё есть истина кроме лжи", то есть
Если говорить кратко — «всё есть истина, кроме лжи», то есть
<pre>3 - это истина
<pre>3 -- это истина
3.5 - это истина
3.5 -- это истина
"test" - это истина</pre>
"test" -- это истина</pre>
Вообще все другие типы, которые мы ещё не изучили - это истина. Все кроме "лжи", которая имеет обозначение <tt>#f</tt>.
Вообще все другие типы, которые мы ещё не изучили — это истина. Все, кроме «лжи», которая имеет обозначение <tt>#f</tt>.


Сразу познакомимся с простейшими логическими операциями:
Сразу познакомимся с простейшими логическими операциями:
Результат <tt>(not 3)</tt> - это <tt>#f</tt>,
Результат <tt>(not 3)</tt> — это <tt>#f</tt>,
Результат <tt>(not "test")</tt> - это тоже <tt>#f</tt>.
Результат <tt>(not "test")</tt> — это тоже <tt>#f</tt>.
Интересно, а какой должен быть результат <tt>(not #f) </tt>. Истин-то у нас много ;) На этот случай есть истина в первой инстанции, обозначаемая <tt>#t</tt>. Стало быть результат <tt>(not #f)</tt> - это <tt>#t</tt>.
Интересно, а какой должен быть результат <tt>(not #f) </tt>. Истин-то у нас много ;) На этот случай есть истина в первой инстанции, обозначаемая <tt>#t</tt>. Стало быть, результат <tt>(not #f)</tt> — это <tt>#t</tt>.


==== 5 Разделяй и властвуй ====
==== 5 Разделяй и властвуй ====
Строка 50: Строка 50:
Ещё для счастья нам не хватает объединять повторяющиеся фрагменты в функции, которые можно было бы потом вызывать.
Ещё для счастья нам не хватает объединять повторяющиеся фрагменты в функции, которые можно было бы потом вызывать.


Это очень важный и интересный момент в Схеме. Вы наверное часто замечали, что разделение многоэтапной операции на составляющие очень полезно. Например, создание нового процесса, можно разделить на два этапа. Клонирование - <tt>fork</tt> и замена содержимого клона на другой процесс  - <tt>exec</tt>. Такое разделение позволяет не запускать например новый процесс, когда это не нужно (сразу <tt>exec</tt>) или не порождать новый процесс, если клон сам справится с задачей (сразу <tt>fork</tt>).
Это очень важный и интересный момент в Схеме. Вы, наверное, часто замечали, что разделение многоэтапной операции на составляющие очень полезно. Например, создание нового процесса можно разделить на два этапа. Клонирование — <tt>fork</tt> и замена содержимого клона на другой процесс — <tt>exec</tt>. Такое разделение позволяет не запускать, например, новый процесс, когда это не нужно (сразу <tt>exec</tt>) или не порождать новый процесс, если клон сам справится с задачей (только <tt>fork</tt>).


Вот так и с функциями. Создание функции, например <tt>f</tt> от одного аргумента, делится на собственно создание одноаргументной функции и на присваивании ей имени <tt>f</tt>.
Вот так и с функциями. Создание функции, например, <tt>f</tt> от одного аргумента, делится на собственно создание одноаргументной функции и на присваивании ей имени <tt>f</tt>.


Как присваивать имена, мы уже знаем - через <tt>define</tt>, а создание функции описывается следующей конструкцией
Как присваивать имена, мы уже знаем — через <tt>define</tt>, а создание функции описывается следующей конструкцией:
<pre>(lambda (<аргументы>) <инструкции>)</pre>
<pre>(lambda (<аргументы>) <инструкции>)</pre>


Строка 73: Строка 73:
Теперь совместим создание функции с присваиванием ей имени:
Теперь совместим создание функции с присваиванием ей имени:
<pre>(define f (lambda() 7))
<pre>(define f (lambda() 7))
;f - это функция без аргументов, которая возвращает 7
;f -- это функция без аргументов, которая возвращает 7
(define square (lambda (x) (* x x)))
(define square (lambda (x) (* x x)))
;square - это функция с одним аргуметном, которая возвращает квадрат переданного ей числа.
;square -- это функция с одним аргуметном, которая возвращает квадрат переданного ей числа.
(define sum (lambda (x y) (+ x y)))
(define sum (lambda (x y) (+ x y)))
;sum - это функция с двумя аргументами, которая возвращает сумму переданных ей двух чисел.</pre>
;sum -- это функция с двумя аргументами, которая возвращает сумму переданных ей двух чисел.</pre>


Вызываются созданные функции точно также как мы это делали ранее: <tt>(имя аргументы)</tt>
Вызываются созданные функции точно также, как мы это делали ранее: <tt>(имя аргументы)</tt>
Как я говорил уже, синтаксис в Схеме очень регулярный, нет лишних синтаксических конструкций, если они не требуются.
Как я говорил уже, синтаксис в Схеме очень регулярный, нет лишних синтаксических конструкций, если они не требуются.


Строка 91: Строка 91:
;подсчитать квадрат числа 3, ответ будет 9.
;подсчитать квадрат числа 3, ответ будет 9.
(square a)
(square a)
;подсчитать квадрат a, где a - это 3, то есть ответ будет опять 9.
;подсчитать квадрат a, где a -- это 3, то есть ответ будет опять 9.
(sum 5 6)
(sum 5 6)
;подсчитать сумму 5 и 6, ответ будет 11
;подсчитать сумму 5 и 6, ответ будет 11
Строка 99: Строка 99:
;подсчитать сумму a и b, ответ будет 8</pre>
;подсчитать сумму a и b, ответ будет 8</pre>


'''[[Scheme/Tutorial/3|далее>>]]'''


{{Category navigation|title=Scheme|category=Scheme|sortkey=Tutorial}}
{{Category navigation|title=Scheme|category=Scheme|sortkey=Tutorial}}

Текущая версия от 08:21, 11 мая 2012

3 Имена

Выражение: (* 10 50) хорошо, а: (* width height) лучше. (* 3.1415926 10.5 10.5) — интригующе, а (* pi radius radius) — всё же понятнее, (+ 2/3 5/7) — какие-то невзрачные действия с дробями, а (+ my-piece-of-cake your-piece-of-cake) — уже обретает смысл.

Хочется сделать выражения более осмысленные и читаемые. Сказано — сделано. Фраза «Определим b как 5» записывается (define b 5). Сразу несколько примеров:

(define a 3)
(define b 4.5)		    ; b -- это действительное число 4,5
(define c 2/3)              ; c -- это рациональное число 2/3 (две третих)
(define str "some string")  ; str -- это строка "some string"
(define width (+ 2 5))      ; width -- это сумма 2 и 5, то есть width -- это 7

Если при определении встречается какое-либо выражение, например, сумма двух целых чисел из последнего примера, то это выражение вычисляется и переменная полагается равной уже его результату. Кстати, a,b,c,str и width действительно называются переменными. Вас это совершенно не должно смущать, ибо с переменными вы сталкивались ещё в курсе школьной алгебры. Итак, записать (define w (+ 1 3)) совершенно равносильно тому, что записать (define w 4). Либо вы подсчитаете в уме, либо за вас это сделает Scheme.

Ну уж коли мы вспомнили про школу, то теперь мы можем записать известные нам выражения.

(+ a b)               ; это a + b, где a и b -- какие-то переменные
(* 2 a)               ; это 2a, где a -- какая-то переменная
(* a a)               ; это квадрат a
(* c c c)             ; это куб c
(+ (* a a) (* b b))   ; это сумма квадратов a и b.

Теперь, вооружившись полученными знаниями, мы можем записывать уже гораздо более сложные программы на Scheme — например, такую:

(define width 3)
(define height 5)

(* width height)   ; умножить ширину на высоту

Наверное, вы заметили, что комментарии к коду я пишу, начиная их с ;. Это не случайно, все комментарии в тексте программы начинаются с символа ;. Когда интерпретатор или компилятор читает наш код, весь текст, начинающийся с ; и до конца строки он игнорирует.

Ещё одна программа:

(define pi 3.1415926)
(define radius 15)

(* pi radius radius)

4 Про истину

Если говорить кратко — «всё есть истина, кроме лжи», то есть

3 -- это истина
3.5 -- это истина
"test" -- это истина

Вообще все другие типы, которые мы ещё не изучили — это истина. Все, кроме «лжи», которая имеет обозначение #f.

Сразу познакомимся с простейшими логическими операциями: Результат (not 3) — это #f, Результат (not "test") — это тоже #f. Интересно, а какой должен быть результат (not #f) . Истин-то у нас много ;) На этот случай есть истина в первой инстанции, обозначаемая #t. Стало быть, результат (not #f) — это #t.

5 Разделяй и властвуй

Ещё для счастья нам не хватает объединять повторяющиеся фрагменты в функции, которые можно было бы потом вызывать.

Это очень важный и интересный момент в Схеме. Вы, наверное, часто замечали, что разделение многоэтапной операции на составляющие очень полезно. Например, создание нового процесса можно разделить на два этапа. Клонирование — fork и замена содержимого клона на другой процесс — exec. Такое разделение позволяет не запускать, например, новый процесс, когда это не нужно (сразу exec) или не порождать новый процесс, если клон сам справится с задачей (только fork).

Вот так и с функциями. Создание функции, например, f от одного аргумента, делится на собственно создание одноаргументной функции и на присваивании ей имени f.

Как присваивать имена, мы уже знаем — через define, а создание функции описывается следующей конструкцией:

(lambda (<аргументы>) <инструкции>)

Если аргументов нет, то они просто не пишутся. Результат вычисления последней инструкции возвращается в качестве ответа.

Примеры:

(lambda () (+ 2 5)) 
; создать безаргументную функцию, которая вернёт результат суммирования 2 и 5, то есть 7.
(lambda () 7)
;тоже самое, функция которая возвращает 7.
(lambda (x) (* x x))
;создать одноаргументную функцию от параметра x, которая вернёт результат
умножения x на x, то есть вернёт квадрат x.
(lambda (x y) (+ x y))
;создать двухаргументную функцию от параметра x, которая вернёт результат
сложения x и y.

Теперь совместим создание функции с присваиванием ей имени:

(define f (lambda() 7))
;f -- это функция без аргументов, которая возвращает 7
(define square (lambda (x) (* x x)))
;square -- это функция с одним аргуметном, которая возвращает квадрат переданного ей числа.
(define sum (lambda (x y) (+ x y)))
;sum -- это функция с двумя аргументами, которая возвращает сумму переданных ей двух чисел.

Вызываются созданные функции точно также, как мы это делали ранее: (имя аргументы) Как я говорил уже, синтаксис в Схеме очень регулярный, нет лишних синтаксических конструкций, если они не требуются.

Ну вот, теперь мы можем ещё больше усовершенствовать наши программы:

(define a 3)
(define b 5)
(define square (lambda (x) (* x x)))
(define sum (lambda (x y) (+ x y)))

(square 3)
;подсчитать квадрат числа 3, ответ будет 9.
(square a)
;подсчитать квадрат a, где a -- это 3, то есть ответ будет опять 9.
(sum 5 6)
;подсчитать сумму 5 и 6, ответ будет 11
(sum a 7)
;подсчитать сумму a и 7, ответ будет 10
(sum a b)
;подсчитать сумму a и b, ответ будет 8

далее>>