Учебник языка Перфо для школьников — различия между версиями
Админ (обсуждение | вклад) м |
Админ (обсуждение | вклад) м (→Введение в синтаксис) |
||
Строка 32: | Строка 32: | ||
(define имя <первоначальное значение>) | (define имя <первоначальное значение>) | ||
+ | |||
+ | Пример: | ||
+ | |||
+ | Пример: | ||
+ | |||
+ | (define width 3) | ||
+ | (define height 7) | ||
+ | (* 2 (+ width height)) | ||
+ | |||
+ | Прочитаем записанное по-русски: «Положим ширина — это 3, высота — это 7, подсчитаем произведение двух и суммы ширины и высоты (например, периметр прямоугольника)». Результат такого вычисления в нашем случае будет 20. | ||
+ | |||
+ | Продолжим совершенствовать конструкции. Положим, нам требуется подсчитать сумму квадратов двух чисел. Это можно сделать, например, так: | ||
+ | |||
+ | (define a 3) | ||
+ | (define b 4) | ||
+ | (+ (* a a) (* b b)) | ||
+ | |||
+ | Что-то не так; мы обычно вместо «помножь переменную на саму себя» говорим «возведи в квадрат эту переменную», на Скиме — <code>square</code>: | ||
+ | |||
+ | (+ (square a) (square b)) | ||
+ | |||
+ | «Сумма квадрата <code>a</code> и квадрата <code>b</code>». Есть задача — есть её решение. Мы можем объявить новое слово-функцию, назвать её <code>square</code>. Функция будет принимать в качестве параметра число и возвращать его квадрат. Делается это следующим образом: | ||
+ | |||
+ | (define (square x) (* x x)) | ||
+ | |||
+ | Общий формат: | ||
+ | |||
+ | (define (название параметр параметр …) тело_функции) | ||
+ | |||
+ | Функция возвращает последнее вычисленное значение. Это означает, что следующая функция <code>square2</code>: | ||
+ | |||
+ | (define (square2 x) (* 2 2) (* x x)) | ||
+ | |||
+ | вернёт тот же результат, что и <code>square</code>, перед этим умножив два на два безо всякого эффекта. Перепишем пример с суммой квадратов чисел заново: | ||
+ | |||
+ | (define a 3) | ||
+ | (define b 4) | ||
+ | (define (square x) (* x x)) | ||
+ | (+ (square a) (square b)) | ||
+ | |||
+ | Нам не хватало слов в языке — мы их добавили. Вообще, когда пишете программу на Лиспе, вы описываете не алгоритм, а сначала создаёте язык, а потом на нём формулируете исходную задачу. Несколько точнее — вы «подгоняете» данный вам язык Scheme до тех пор, пока он не станет совпадать с языком, на котором задача формулируется легко. | ||
+ | |||
+ | Сразу пример. Пусть перед нами стоит задача сделать программу, которая спрашивает имя пользователя, а потом выводит ему приветствие. | ||
+ | |||
+ | Scheme предоставляет нам несколько готовых «глаголов»: | ||
+ | |||
+ | ; <code>read</code>: для чтения имени, | ||
+ | ; <code>display</code>: вывод чего-то на дисплее, | ||
+ | ; <code>newline</code>: вывод перевода строки. | ||
+ | |||
+ | Мы бы хотели иметь такие «глаголы»: | ||
+ | |||
+ | ; <code>привет</code>: для приветствия с одним параметром — именем пользователя; | ||
+ | ; <code>пользователь</code>: для получения имени пользователя, без параметров. | ||
+ | |||
+ | Наша задача выглядела бы так: | ||
+ | |||
+ | (привет (пользователь)) | ||
+ | |||
+ | Дело за малым — определить <code>привет</code> и <code>пользователь</code>. Нет проблем. Вот полный текст программы. | ||
+ | |||
+ | (define (привет имя) | ||
+ | (display "Привет, ") | ||
+ | (display имя) | ||
+ | (display "!") | ||
+ | (newline)) | ||
+ | (define (пользователь) | ||
+ | (write "Представьтесь:") | ||
+ | (read)) | ||
+ | (привет (пользователь)) | ||
+ | |||
+ | [[w:Лисп|Лисп]] — полноценный функциональный язык, а поэтому функции — полноправные члены этого языка, независимо от того, определили вы их сами, или они уже были в языке готовые. В частности, их можно передавать в качестве параметров в другие функции, а там уже делать с ними всё, что потребуется. | ||
+ | Например, функцию «модуль числа» можно определить так: | ||
+ | |||
+ | (define (abs x) | ||
+ | (if (positive? x ) | ||
+ | x | ||
+ | (- x))) | ||
+ | |||
+ | «Определим, что функция <code>abs</code> возвращает свой аргумент, если он положителен, иначе — <code>-x</code>». А можно и так: | ||
+ | |||
+ | (define (abs x) | ||
+ | ((if (positive? x) + -) x)) | ||
+ | |||
+ | «…если аргумент положителен, то плюс, иначе минус <code>x</code>». Здесь в результате исполнения выражения <code>if</code> возвращается функция <code>+</code> или <code>-</code>, которая затем применяется к аргументу <code>x</code>. Полагаю, что смысл конструкции <code>if</code> вам сразу ясен. Сначала проверяется первый аргумент, если он истинен, то исполняется второй аргумент, иначе третий. Общий формат таков: | ||
+ | |||
+ | (if условие <действие, если условие выполняется> <действие в противном случае>) | ||
+ | |||
[[Категория:Перфо]] | [[Категория:Перфо]] |
Версия 11:36, 2 сентября 2020
Перевод под Перфо "Введение в Scheme для школьников"
* https://ru.wikibooks.org/wiki/Введение_в_язык_Scheme_для_школьников - Оригинал Введение в Scheme для школьников
Замечания: Из-за поломки расширения подсветки синтаксиса в настройке этой вики, при попытке вставить тег подсветки синтаксиса syntaxhighlight lang="scheme" - эта вики зависает, поэтому подсветка синтаксиса не работает и теги подсветки синтаксиса syntaxhighlight надо удалять :( при копировании.
- Часть викиучебника «Лисп»
- Исходный вариант статьи (С. И. Иевлев, «Ваш новый язык — Scheme») опубликован в двух частях в журнале «Потенциал».
Вы хорошо знаете русский, возможно, неплохо уже говорите по-английски, в школе вас научили несколько необычному языку математики. Предлагаю выучить ещё один — Лисп. Точнее, один из его самых интересных диалектов — Scheme (Ским).
Введение в синтаксис
Сперва познакомимся с несколько необычным порядком слов этого языка: «действие — предмет». Но необычен он только в сравнении с популярными языками программирования. В русском языке такая последовательность нередка:
- Сумма трёх и пяти.
- Произведение пяти, шести и семи.
- Купи в булочной батон.
Каждая законченная фраза на этом языке должна быть окружена парой круглых скобок. Запишем сказанное выше на Scheme:
(+ 3 5) (* 5 6 7) (купить булочная батон)
Можно записать выражения и посложнее:
(купить булочная батон (+ 2 1))
«Купи в булочной батоны: два плюс ещё один». Просто, не правда ли? Давайте двигаться дальше. Фраза (* 3 5)
хороша, а (* width height)
— лучше. Выражение (* 2 3.1415926 5)
— интригующе, а (* 2 pi radius)
гораздо более осмысленно. Здесь width
, height
— переменные, а 3
и 5
— их текущие значения.
Переменная задаётся следующей конструкцией языка:
(define имя <первоначальное значение>)
Пример:
Пример:
(define width 3)
(define height 7) (* 2 (+ width height))
Прочитаем записанное по-русски: «Положим ширина — это 3, высота — это 7, подсчитаем произведение двух и суммы ширины и высоты (например, периметр прямоугольника)». Результат такого вычисления в нашем случае будет 20.
Продолжим совершенствовать конструкции. Положим, нам требуется подсчитать сумму квадратов двух чисел. Это можно сделать, например, так:
(define a 3)
(define b 4) (+ (* a a) (* b b))
Что-то не так; мы обычно вместо «помножь переменную на саму себя» говорим «возведи в квадрат эту переменную», на Скиме — square
:
(+ (square a) (square b))
«Сумма квадрата a
и квадрата b
». Есть задача — есть её решение. Мы можем объявить новое слово-функцию, назвать её square
. Функция будет принимать в качестве параметра число и возвращать его квадрат. Делается это следующим образом:
(define (square x) (* x x))
Общий формат:
(define (название параметр параметр …) тело_функции)
Функция возвращает последнее вычисленное значение. Это означает, что следующая функция square2
:
(define (square2 x) (* 2 2) (* x x))
вернёт тот же результат, что и square
, перед этим умножив два на два безо всякого эффекта. Перепишем пример с суммой квадратов чисел заново:
(define a 3)
(define b 4) (define (square x) (* x x)) (+ (square a) (square b))
Нам не хватало слов в языке — мы их добавили. Вообще, когда пишете программу на Лиспе, вы описываете не алгоритм, а сначала создаёте язык, а потом на нём формулируете исходную задачу. Несколько точнее — вы «подгоняете» данный вам язык Scheme до тех пор, пока он не станет совпадать с языком, на котором задача формулируется легко.
Сразу пример. Пусть перед нами стоит задача сделать программу, которая спрашивает имя пользователя, а потом выводит ему приветствие.
Scheme предоставляет нам несколько готовых «глаголов»:
-
read
- для чтения имени,
-
display
- вывод чего-то на дисплее,
-
newline
- вывод перевода строки.
Мы бы хотели иметь такие «глаголы»:
-
привет
- для приветствия с одним параметром — именем пользователя;
-
пользователь
- для получения имени пользователя, без параметров.
Наша задача выглядела бы так:
(привет (пользователь))
Дело за малым — определить привет
и пользователь
. Нет проблем. Вот полный текст программы.
(define (привет имя) (display "Привет, ") (display имя) (display "!") (newline))
(define (пользователь)
(write "Представьтесь:") (read))
(привет (пользователь))
Лисп — полноценный функциональный язык, а поэтому функции — полноправные члены этого языка, независимо от того, определили вы их сами, или они уже были в языке готовые. В частности, их можно передавать в качестве параметров в другие функции, а там уже делать с ними всё, что потребуется. Например, функцию «модуль числа» можно определить так:
(define (abs x) (if (positive? x ) x (- x)))
«Определим, что функция abs
возвращает свой аргумент, если он положителен, иначе — -x
». А можно и так:
(define (abs x) ((if (positive? x) + -) x))
«…если аргумент положителен, то плюс, иначе минус x
». Здесь в результате исполнения выражения if
возвращается функция +
или -
, которая затем применяется к аргументу x
. Полагаю, что смысл конструкции if
вам сразу ясен. Сначала проверяется первый аргумент, если он истинен, то исполняется второй аргумент, иначе третий. Общий формат таков:
(if условие <действие, если условие выполняется> <действие в противном случае>)