Scheme/Tutorial/2
Материал из ALT Linux Wiki
(→3 Имена: Исправил выражение в стандарном синтаксисе на синтаксис схемы) |
м (вычитка) |
||
Строка 1: | Строка 1: | ||
==== 3 Имена ==== | ==== 3 Имена ==== | ||
- | Выражение: <tt>(* 10 50)</tt> хорошо, а: <tt>(* width height)</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>. Сразу несколько примеров: |
<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>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 — например, такую: |
<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> и до конца строки он игнорирует. |
Ещё одна программа: | Ещё одна программа: | ||
Строка 35: | Строка 35: | ||
==== 4 Про истину ==== | ==== 4 Про истину ==== | ||
- | Если говорить | + | Если говорить кратко — «всё есть истина, кроме лжи», то есть |
- | <pre>3 - это истина | + | <pre>3 -- это истина |
- | 3.5 - это истина | + | 3.5 -- это истина |
- | "test" - это истина</pre> | + | "test" -- это истина</pre> |
- | Вообще все другие типы, которые мы ещё не | + | Вообще все другие типы, которые мы ещё не изучили — это истина. Все, кроме «лжи», которая имеет обозначение <tt>#f</tt>. |
Сразу познакомимся с простейшими логическими операциями: | Сразу познакомимся с простейшими логическими операциями: | ||
- | Результат <tt>(not 3)</tt> | + | Результат <tt>(not 3)</tt> — это <tt>#f</tt>, |
- | Результат <tt>(not "test")</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>. |
==== 5 Разделяй и властвуй ==== | ==== 5 Разделяй и властвуй ==== | ||
Строка 50: | Строка 50: | ||
Ещё для счастья нам не хватает объединять повторяющиеся фрагменты в функции, которые можно было бы потом вызывать. | Ещё для счастья нам не хватает объединять повторяющиеся фрагменты в функции, которые можно было бы потом вызывать. | ||
- | Это очень важный и интересный момент в Схеме. Вы наверное часто замечали, что разделение многоэтапной операции на составляющие очень полезно. | + | Это очень важный и интересный момент в Схеме. Вы, наверное, часто замечали, что разделение многоэтапной операции на составляющие очень полезно. Например, создание нового процесса можно разделить на два этапа. Клонирование — <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>, а создание функции описывается следующей конструкцией: |
<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