diff options
author | woclass <inkydragon@users.noreply.github.com> | 2018-12-03 20:30:45 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-03 20:30:45 +0800 |
commit | cd7816a2be62b0dcd2aca181d1aadd68b8e4d5d7 (patch) | |
tree | f75c300c92d40e29bf59f83775aec019b45e56e7 /ru-ru | |
parent | 440247a59706603bd980016821ecd6a72a6182d1 (diff) | |
parent | 1fd955ae6479650b987a54a93b09507bfdf06954 (diff) |
Merge pull request #1 from adambard/master
Update from Upstream
Diffstat (limited to 'ru-ru')
-rw-r--r-- | ru-ru/c++-ru.html.markdown | 7 | ||||
-rw-r--r-- | ru-ru/clojure-ru.html.markdown | 52 | ||||
-rw-r--r-- | ru-ru/common-lisp-ru.html.markdown | 704 | ||||
-rw-r--r-- | ru-ru/crystal-ru.html.markdown | 584 | ||||
-rw-r--r-- | ru-ru/jquery-ru.html.markdown | 127 | ||||
-rw-r--r-- | ru-ru/markdown-ru.html.markdown | 1 | ||||
-rw-r--r-- | ru-ru/php-composer-ru.html.markdown | 196 | ||||
-rw-r--r-- | ru-ru/rust-ru.html.markdown | 316 |
8 files changed, 1957 insertions, 30 deletions
diff --git a/ru-ru/c++-ru.html.markdown b/ru-ru/c++-ru.html.markdown index b9704fc3..35994749 100644 --- a/ru-ru/c++-ru.html.markdown +++ b/ru-ru/c++-ru.html.markdown @@ -886,7 +886,6 @@ v.swap(vector<Foo>()); ``` ## Дальнейшее чтение: -Наиболее полное и обновленное руководство по С++ можно найти на -<http://cppreference.com/w/cpp> - -Дополнительные ресурсы могут быть найдены на <http://cplusplus.com> +* Наиболее полное и обновленное руководство по С++ можно найти на [CPP Reference](http://cppreference.com/w/cpp). +* Дополнительные ресурсы могут быть найдены на [CPlusPlus](http://cplusplus.com). +* Учебник, посвященный основам языка и настройке среды кодирования, доступен в [TheChernoProject - C ++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb). diff --git a/ru-ru/clojure-ru.html.markdown b/ru-ru/clojure-ru.html.markdown index 356d1cc0..19233d23 100644 --- a/ru-ru/clojure-ru.html.markdown +++ b/ru-ru/clojure-ru.html.markdown @@ -8,9 +8,9 @@ translators: lang: ru-ru --- -Clojure, это представитель семейства Lisp-подобных языков, разработанный +Clojure — это представитель семейства Lisp-подобных языков, разработанный для Java Virtual Machine. Язык идейно гораздо ближе к чистому -[функциональному программированию](https://ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5) чем его прародитель Common Lisp, но в то же время обладает набором инструментов для работы с состоянием, +[функциональному программированию](https://ru.wikipedia.org/wiki/%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5), чем его прародитель Common Lisp, но в то же время обладает набором инструментов для работы с состоянием, таких как [STM](https://ru.wikipedia.org/wiki/Software_transactional_memory). Благодаря такому сочетанию технологий в одном языке, разработка программ, @@ -23,9 +23,9 @@ Clojure, это представитель семейства Lisp-подобн ```clojure ; Комментарии начинаются символом ";". -; Код на языке Clojure записывается в виде "форм", +; Код на языке Clojure записывается в виде «форм», ; которые представляют собой обычные списки элементов, разделенных пробелами, -; заключённые в круглые скобки +; заключённые в круглые скобки. ; ; Clojure Reader (инструмент языка, отвечающий за чтение исходного кода), ; анализируя форму, предполагает, что первым элементом формы (т.е. списка) @@ -76,32 +76,32 @@ Clojure, это представитель семейства Lisp-подобн '(+ 1 2) ; => (+ 1 2) ; ("'", это краткая запись формы (quote (+ 1 2)) -; "Квотированный" список можно вычислить, передав его функции eval +; «Квотированный» список можно вычислить, передав его функции eval (eval '(+ 1 2)) ; => 3 ; Коллекции и Последовательности ;;;;;;;;;;;;;;;;;;; -; Списки (Lists) в clojure структурно представляют собой "связанные списки", +; Списки (Lists) в clojure структурно представляют собой «связанные списки», ; тогда как Векторы (Vectors), устроены как массивы. ; Векторы и Списки тоже являются классами Java! (class [1 2 3]); => clojure.lang.PersistentVector (class '(1 2 3)); => clojure.lang.PersistentList -; Список может быть записан, как (1 2 3), но в этом случае +; Список может быть записан как (1 2 3), но в этом случае ; он будет воспринят reader`ом, как вызов функции. ; Есть два способа этого избежать: ; '(1 2 3) - квотирование, ; (list 1 2 3) - явное конструирование списка с помощью функции list. -; "Коллекции", это некие наборы данных +; «Коллекции» — это некие наборы данных. ; И списки, и векторы являются коллекциями: (coll? '(1 2 3)) ; => true (coll? [1 2 3]) ; => true -; "Последовательности" (seqs), это абстракция над наборами данных, +; «Последовательности» (seqs) — это абстракция над наборами данных, ; элементы которых "упакованы" последовательно. -; Списки - последовательности, а вектора - нет. +; Списки — последовательности, а векторы — нет. (seq? '(1 2 3)) ; => true (seq? [1 2 3]) ; => false @@ -119,7 +119,7 @@ Clojure, это представитель семейства Lisp-подобн ; Функция conj добавляет элемент в коллекцию ; максимально эффективным для неё способом. -; Для списков эффективно добавление в начло, а для векторов - в конец. +; Для списков эффективно добавление в начло, а для векторов — в конец. (conj [1 2 3] 4) ; => [1 2 3 4] (conj '(1 2 3) 4) ; => (4 1 2 3) @@ -130,7 +130,7 @@ Clojure, это представитель семейства Lisp-подобн (map inc [1 2 3]) ; => (2 3 4) (filter even? [1 2 3]) ; => (2) -; reduce поможет "свернуть" коллекцию +; reduce поможет «свернуть» коллекцию (reduce + [1 2 3 4]) ; = (+ (+ (+ 1 2) 3) 4) ; => 10 @@ -144,12 +144,12 @@ Clojure, это представитель семейства Lisp-подобн ;;;;;;;;;;;;;;;;;;;;; ; Функция создается специальной формой fn. -; "Тело" функции может состоять из нескольких форм, +; «Тело» функции может состоять из нескольких форм, ; но результатом вызова функции всегда будет результат вычисления ; последней из них. (fn [] "Hello World") ; => fn -; (Вызов функции требует "оборачивания" fn-формы в форму вызова) +; (Вызов функции требует «оборачивания» fn-формы в форму вызова) ((fn [] "Hello World")) ; => "Hello World" ; Назначить значению имя можно специальной формой def @@ -160,7 +160,7 @@ x ; => 1 (def hello-world (fn [] "Hello World")) (hello-world) ; => "Hello World" -; Поскольку именование функций - очень частая операция, +; Поскольку именование функций — очень частая операция, ; clojure позволяет, сделать это проще: (defn hello-world [] "Hello World") @@ -211,7 +211,7 @@ x ; => 1 ; Отображения могут использовать в качестве ключей любые хэшируемые значения, ; однако предпочтительными являются ключи, -; являющиеся "ключевыми словами" (keywords) +; являющиеся «ключевыми словами» (keywords) (class :a) ; => clojure.lang.Keyword (def stringmap {"a" 1, "b" 2, "c" 3}) @@ -263,7 +263,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут ; Исключаются - посредством disj (disj #{1 2 3} 1) ; => #{2 3} -; Вызов множества, как функции, позволяет проверить +; Вызов множества как функции позволяет проверить ; принадлежность элемента этому множеству: (#{1 2 3} 1) ; => 1 (#{1 2 3} 4) ; => nil @@ -274,8 +274,8 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут ; Полезные формы ;;;;;;;;;;;;;;;;; -; Конструкции ветвления в clojure, это обычные макросы -; и подобны их собратьям в других языках: +; Конструкции ветвления в clojure — это обычные макросы, +; они подобны своим собратьям в других языках: (if false "a" "b") ; => "b" (if false "a") ; => nil @@ -285,7 +285,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут (let [a 1 b 2] (> a b)) ; => false -; Несколько форм можно объединить в одну форму посредством do +; Несколько форм можно объединить в одну форму посредством do. ; Значением do-формы будет значение последней формы из списка вложенных в неё: (do (print "Hello") @@ -298,7 +298,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут (str "Hello " name)) (print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff") -; Ещё один пример - let: +; Ещё один пример — let: (let [name "Urkel"] (print "Saying hello to " name) (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel") @@ -306,7 +306,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут ; Модули ;;;;;;;;; -; Форма "use" позволяет добавить в текущее пространство имен +; Форма use позволяет добавить в текущее пространство имен ; все имена (вместе со значениями) из указанного модуля: (use 'clojure.set) @@ -392,7 +392,7 @@ keymap ; => {:a 1, :b 2, :c 3} - оригинал не был затронут my-atom ;=> Atom<#...> (Возвращает объект типа Atom) @my-atom ; => {:a 1 :b 2} -; Пример реализации счётчика на атоме +; Пример реализации счётчика на атоме: (def counter (atom 0)) (defn inc-counter [] (swap! counter inc)) @@ -414,13 +414,13 @@ my-atom ;=> Atom<#...> (Возвращает объект типа Atom) Это руководство не претендует на полноту, но мы смеем надеяться, способно вызвать интерес к дальнейшему изучению языка. -Clojure.org - сайт содержит большое количество статей по языку: +Сайт Clojure.org содержит большое количество статей по языку: [http://clojure.org/](http://clojure.org/) -Clojuredocs.org - сайт документации языка с примерами использования функций: +Clojuredocs.org — сайт документации языка с примерами использования функций: [http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core) -4Clojure - отличный способ закрепить навыки программирования на clojure, решая задачи вместе с коллегами со всего мира: +4Clojure — отличный способ закрепить навыки программирования на clojure, решая задачи вместе с коллегами со всего мира: [http://www.4clojure.com/](http://www.4clojure.com/) Clojure-doc.org (да, именно) неплохой перечень статей для начинающих: diff --git a/ru-ru/common-lisp-ru.html.markdown b/ru-ru/common-lisp-ru.html.markdown new file mode 100644 index 00000000..d5f9bf0e --- /dev/null +++ b/ru-ru/common-lisp-ru.html.markdown @@ -0,0 +1,704 @@ +--- + +language: "Common Lisp" +filename: commonlisp.lisp +contributors: + - ["Paul Nathan", "https://github.com/pnathan"] + - ["Rommel Martinez", "https://ebzzry.io"] +translators: + - ["Michael Filonenko", "https://github.com/filonenko-mikhail"] +lang: ru-ru +--- + +Common Lisp - мультипарадигменный язык программирования общего назначения, подходящий для широкого +спектра задач. +Его частенько называют программируемым языком программирования. + +Идеальная отправная точка - книга [Common Lisp на практике (перевод)](http://lisper.ru/pcl/). +Ещё одна популярная книга [Land of Lisp](http://landoflisp.com/). +И одна из последних книг [Common Lisp Recipes](http://weitz.de/cl-recipes/) вобрала в себя лучшие +архитектурные решения на основе опыта коммерческой работки автора. + + + +```common-lisp + +;;;----------------------------------------------------------------------------- +;;; 0. Синтаксис +;;;----------------------------------------------------------------------------- + +;;; Основные формы + +;;; Существует два фундамента CL: АТОМ и S-выражение. +;;; Как правило, сгруппированные S-выражения называют `формами`. + +10 ; атом; вычисляется в самого себя +:thing ; другой атом; вычисляется в символ :thing +t ; ещё один атом, обозначает `истину` (true) +(+ 1 2 3 4) ; s-выражение +'(4 :foo t) ; ещё одно s-выражение + +;;; Комментарии + +;;; Однострочные комментарии начинаются точкой с запятой. Четыре знака подряд +;;; используют для комментария всего файла, три для раздела, два для текущего +;;; определения; один для текущей строки. Например: + +;;;; life.lisp + +;;; То-сё - пятое-десятое. Оптимизировано для максимального бадабума и ччччч. +;;; Требуется для функции PoschitatBenzinIsRossiiVBelarus + +(defun meaning (life) + "Возвращает смысл Жизни" + (let ((meh "abc")) + ;; Вызывает бадабум + (loop :for x :across meh + :collect x))) ; сохранить значения в x, и потом вернуть + +;;; А вот целый блок комментария можно использовать как угодно. +;;; Для него используются #| и |# + +#| Целый блок комментария, который размазан + на несколько строк + #| + которые могут быть вложенными! + |# +|# + +;;; Чем пользоваться + +;;; Существует несколько реализаций: и коммерческих, и открытых. +;;; Все они максимально соответствуют стандарту языка. +;;; SBCL, например, добротен. А за дополнительными библиотеками +;;; нужно ходить в Quicklisp + +;;; Обычно разработка ведется в текстовом редакторе с запущенным в цикле +;;; интерпретатором (в CL это Read Eval Print Loop). Этот цикл (REPL) +;;; позволяет интерактивно выполнять части программы вживую сразу наблюдая +;;; результат. + +;;;----------------------------------------------------------------------------- +;;; 1. Базовые типы и операторы +;;;----------------------------------------------------------------------------- + +;;; Символы + +'foo ; => FOO Символы автоматически приводятся к верхнему регистру. + +;;; INTERN создаёт символ из строки. + +(intern "AAAA") ; => AAAA +(intern "aaa") ; => |aaa| + +;;; Числа + +9999999999999999999999 ; целые +#b111 ; двоичные => 7 +#o111 ; восьмеричные => 73 +#x111 ; шестнадцатиричные => 273 +3.14159s0 ; с плавающей точкой +3.14159d0 ; с плавающей точкой с двойной точностью +1/2 ; рациональные) +#C(1 2) ; комплексные + +;;; Вызов функции пишется как s-выражение (f x y z ....), где f это функция, +;;; x, y, z, ... аругменты. + +(+ 1 2) ; => 3 + +;;; Если вы хотите просто представить код как данные, воспользуйтесь формой QUOTE +;;; Она не вычисляет аргументы, а возвращает их как есть. +;;; Она даёт начало метапрограммированию + +(quote (+ 1 2)) ; => (+ 1 2) +(quote a) ; => A + +;;; QUOTE можно сокращенно записать знаком ' + +'(+ 1 2) ; => (+ 1 2) +'a ; => A + +;;; Арифметические операции + +(+ 1 1) ; => 2 +(- 8 1) ; => 7 +(* 10 2) ; => 20 +(expt 2 3) ; => 8 +(mod 5 2) ; => 1 +(/ 35 5) ; => 7 +(/ 1 3) ; => 1/3 +(+ #C(1 2) #C(6 -4)) ; => #C(7 -2) + +;;; Булевые + +t ; истина; любое не-NIL значение `истинно` +nil ; ложь; а ещё пустой список () тоже `ложь` +(not nil) ; => T +(and 0 t) ; => T +(or 0 nil) ; => 0 + +;;; Строковые символы + +#\A ; => #\A +#\λ ; => #\GREEK_SMALL_LETTER_LAMDA +#\u03BB ; => #\GREEK_SMALL_LETTER_LAMDA + +;;; Строки это фиксированные массивы символов + +"Hello, world!" +"Тимур \"Каштан\" Бадтрудинов" ; экранировать двойную кавычку обратным слешом + +;;; Строки можно соединять + +(concatenate 'string "ПРивет, " "мир!") ; => "ПРивет, мир!" + +;;; Можно пройтись по строке как по массиву символов + +(elt "Apple" 0) ; => #\A + +;;; Для форматированного вывода используется FORMAT. Он умеет выводить, как просто значения, +;;; так и производить циклы и учитывать условия. Первый агрумент указывает куда отправить +;;; результат. Если NIL, FORMAT вернет результат как строку, если T результат отправиться +;;; консоль вывода а форма вернет NIL. + +(format nil "~A, ~A!" "Привет" "мир") ; => "Привет, мир!" +(format t "~A, ~A!" "Привет" "мир") ; => NIL + + +;;;----------------------------------------------------------------------------- +;;; 2. Переменные +;;;----------------------------------------------------------------------------- + +;;; С помощью DEFVAR и DEFPARAMETER вы можете создать глобальную (динамческой видимости) +;;; переменную. +;;; Имя переменной может состоять из любых символов кроме: ()",'`;#|\ + +;;; Разница между DEFVAR и DEFPARAMETER в том, что повторное выполнение DEFVAR +;;; переменную не поменяет. А вот DEFPARAMETER меняет переменную при каждом вызове. + +;;; Обычно глобальные (динамически видимые) переменные содержат звездочки в имени. + +(defparameter *some-var* 5) +*some-var* ; => 5 + +;;; Можете использовать unicode. +(defparameter *КУКУ* nil) + +;;; Доступ к необъявленной переменной - это непредсказуемое поведение. Не делайте так. + +;;; С помощью LET можете сделать локальное связывание. +;;; В следующем куске кода, `я` связывается с "танцую с тобой" только +;;; внутри формы (let ...). LET всегда возвращает значение последней формы. + +(let ((я "танцую с тобой")) я) ; => "танцую с тобой" + + +;;;-----------------------------------------------------------------------------; +;;; 3. Структуры и коллекции +;;;-----------------------------------------------------------------------------; + + +;;; Структуры + +(defstruct dog name breed age) +(defparameter *rover* + (make-dog :name "rover" + :breed "collie" + :age 5)) +*rover* ; => #S(DOG :NAME "rover" :BREED "collie" :AGE 5) +(dog-p *rover*) ; => T +(dog-name *rover*) ; => "rover" + +;;; DEFSTRUCT автоматически создала DOG-P, MAKE-DOG, и DOG-NAME + + +;;; Пары (cons-ячейки) + +;;; CONS создаёт пары. CAR и CDR возвращают начало и конец CONS-пары. + +(cons 'SUBJECT 'VERB) ; => '(SUBJECT . VERB) +(car (cons 'SUBJECT 'VERB)) ; => SUBJECT +(cdr (cons 'SUBJECT 'VERB)) ; => VERB + + +;;; Списки + +;;; Списки это связанные CONS-пары, в конце самой последней из которых стоит NIL +;;; (или '() ). + +(cons 1 (cons 2 (cons 3 nil))) ; => '(1 2 3) + +;;; Списки с произвольным количеством элементов удобно создавать с помощью LIST + +(list 1 2 3) ; => '(1 2 3) + +;;; Если первый аргумент для CONS это атом и второй аргумент список, CONS +;;; возвращает новую CONS-пару, которая представляет собой список + +(cons 4 '(1 2 3)) ; => '(4 1 2 3) + +;;; Чтобы объединить списки, используйте APPEND + +(append '(1 2) '(3 4)) ; => '(1 2 3 4) + +;;; Или CONCATENATE + +(concatenate 'list '(1 2) '(3 4)) ; => '(1 2 3 4) + +;;; Списки это самый используемый элемент языка. Поэтому с ними можно делать +;;; многие вещи. Вот несколько примеров: + +(mapcar #'1+ '(1 2 3)) ; => '(2 3 4) +(mapcar #'+ '(1 2 3) '(10 20 30)) ; => '(11 22 33) +(remove-if-not #'evenp '(1 2 3 4)) ; => '(2 4) +(every #'evenp '(1 2 3 4)) ; => NIL +(some #'oddp '(1 2 3 4)) ; => T +(butlast '(subject verb object)) ; => (SUBJECT VERB) + + +;;; Вектора + +;;; Вектора заданные прямо в коде - это массивы с фиксированной длинной. + +#(1 2 3) ; => #(1 2 3) + +;;; Для соединения векторов используйте CONCATENATE + +(concatenate 'vector #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6) + + +;;; Массивы + +;;; И вектора и строки это подмножества массивов. + +;;; Двухмерные массивы + +(make-array (list 2 2)) ; => #2A((0 0) (0 0)) +(make-array '(2 2)) ; => #2A((0 0) (0 0)) +(make-array (list 2 2 2)) ; => #3A(((0 0) (0 0)) ((0 0) (0 0))) + +;;; Внимание: значение по-умолчанию элемента массива зависит от реализации. +;;; Лучше явно указывайте: + +(make-array '(2) :initial-element 'unset) ; => #(UNSET UNSET) + +;;; Для доступа к элементу в позиции 1, 1, 1: + +(aref (make-array (list 2 2 2)) 1 1 1) ; => 0 + + +;;; Вектора с изменяемой длиной + +;;; Вектора с изменяемой длиной при выводе на консоль выглядят также, +;;; как и вектора, с константной длиной + +(defparameter *adjvec* (make-array '(3) :initial-contents '(1 2 3) + :adjustable t :fill-pointer t)) +*adjvec* ; => #(1 2 3) + +;;; Добавление новых элементов + +(vector-push-extend 4 *adjvec*) ; => 3 +*adjvec* ; => #(1 2 3 4) + + +;;; Множества, это просто списки: + +(set-difference '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1) +(intersection '(1 2 3 4) '(4 5 6 7)) ; => 4 +(union '(1 2 3 4) '(4 5 6 7)) ; => (3 2 1 4 5 6 7) +(adjoin 4 '(1 2 3 4)) ; => (1 2 3 4) + +;;; Несмотря на все, для действительно больших объемов данных, вам нужно что-то +;;; лучше, чем просто связанные списки + +;;; Словари представлены хеш таблицами. + +;;; Создание хеш таблицы: + +(defparameter *m* (make-hash-table)) + +;;; Установка пары ключ-значение + +(setf (gethash 'a *m*) 1) + +;;; Возврат значения по ключу + +(gethash 'a *m*) ; => 1, T + +;;; CL выражения умеют возвращать сразу несколько значений. + +(values 1 2) ; => 1, 2 + +;;; которые могут быть распределены по переменным с помощью MULTIPLE-VALUE-BIND + +(multiple-value-bind (x y) + (values 1 2) + (list y x)) + +; => '(2 1) + +;;; GETHASH как раз та функция, которая возвращает несколько значений. Первое +;;; значение - это значение по ключу в хеш таблицу. Если ключ не был найден, +;;; возвращает NIL. + +;;; Второе возвращаемое значение, указывает был ли ключ в хеш таблице. Если ключа +;;; не было, то возвращает NIL. Таким образом можно проверить, это значение +;;; NIL, или ключа просто не было. + +;;; Вот возврат значений, в случае когда ключа в хеш таблице не было: + +(gethash 'd *m*) ;=> NIL, NIL + +;;; Можете задать значение по умолчанию. + +(gethash 'd *m* :not-found) ; => :NOT-FOUND + +;;; Давайте обработаем возврат несколько значений. + +(multiple-value-bind (a b) + (gethash 'd *m*) + (list a b)) +; => (NIL NIL) + +(multiple-value-bind (a b) + (gethash 'a *m*) + (list a b)) +; => (1 T) + + +;;;----------------------------------------------------------------------------- +;;; 3. Функции +;;;----------------------------------------------------------------------------- + +;;; Для создания анонимных функций используйте LAMBDA. Функций всегда возвращают +;;; значение последнего своего выражения. Как выглядит функция при выводе в консоль +;;; зависит от реализации. + +(lambda () "Привет Мир") ; => #<FUNCTION (LAMBDA ()) {1004E7818B}> + +;;; Для вызова анонимной функции пользуйтесь FUNCALL + +(funcall (lambda () "Привет Мир")) ; => "Привет мир" +(funcall #'+ 1 2 3) ; => 6 + +;;; FUNCALL сработает и тогда, когда анонимная функция стоит в начале +;;; неэкранированного списка + +((lambda () "Привет Мир")) ; => "Привет Мир" +((lambda (val) val) "Привет Мир") ; => "Привет Мир" + +;;; FUNCALL используется, когда аргументы заранее известны. +;;; В противном случае используйте APPLY + +(apply #'+ '(1 2 3)) ; => 6 +(apply (lambda () "Привет Мир") nil) ; => "Привет Мир" + +;;; Для обычной функции с именем используйте DEFUN + +(defun hello-world () "Привет Мир") +(hello-world) ; => "Привет Мир" + +;;; Выше видно пустой список (), это место для определения аргументов + +(defun hello (name) (format nil "Hello, ~A" name)) +(hello "Григорий") ; => "Привет, Григорий" + +;;; Можно указать необязательные аргументы. По умолчанию они будут NIL + +(defun hello (name &optional from) + (if from + (format t "Приветствие для ~A от ~A" name from) + (format t "Привет, ~A" name))) + +(hello "Георгия" "Василия") ; => Приветствие для Георгия от Василия + +;;; Можно явно задать значения по умолчанию + +(defun hello (name &optional (from "Мира")) + (format nil "Приветствие для ~A от ~A" name from)) + +(hello "Жоры") ; => Приветствие для Жоры от Мира +(hello "Жоры" "альпаки") ; => Приветствие для Жоры от альпаки + +;;; Можно также задать именованные параметры + +(defun generalized-greeter (name &key (from "Мира") (honorific "Господин")) + (format t "Здравствуйте, ~A ~A, от ~A" honorific name from)) + +(generalized-greeter "Григорий") +; => Здравствуйте, Господин Григорий, от Мира + +(generalized-greeter "Григорий" :from "альпаки" :honorific "гражданин") +; => Здравствуйте, Гражданин Григорий, от альпаки + + +;;;----------------------------------------------------------------------------- +;;; 4. Равенство или эквивалентность +;;;----------------------------------------------------------------------------- + +;;; У CL сложная система эквивалентности. Взглянем одним глазом. + +;;; Для чисел используйте `=' +(= 3 3.0) ; => T +(= 2 1) ; => NIL + +;;; Для идентичености объектов используйте EQL +(eql 3 3) ; => T +(eql 3 3.0) ; => NIL +(eql (list 3) (list 3)) ; => NIL + +;;; Для списков, строк, и битовых векторов - EQUAL +(equal (list 'a 'b) (list 'a 'b)) ; => T +(equal (list 'a 'b) (list 'b 'a)) ; => NIL + + +;;;----------------------------------------------------------------------------- +;;; 5. Циклы и ветвления +;;;----------------------------------------------------------------------------- + +;;; Ветвления + +(if t ; проверямое значение + "случилась истина" ; если, оно было истинно + "случилась ложь") ; иначе, когда оно было ложно +; => "случилась истина" + +;;; В форме ветвления if, все не-NIL значения это `истина` + +(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(GROUCHO ZEPPO) +(if (member 'Groucho '(Harpo Groucho Zeppo)) + 'yep + 'nope) +; => 'YEP + +;;; COND это цепочка проверок для нахождения искомого +(cond ((> 2 2) (error "мимо!")) + ((< 2 2) (error "опять мимо!")) + (t 'ok)) ; => 'OK + +;;; TYPECASE выбирает ветку исходя из типа выражения +(typecase 1 + (string :string) + (integer :int)) +; => :int + + +;;; Циклы + +;;; С рекурсией + +(defun fact (n) + (if (< n 2) + 1 + (* n (fact(- n 1))))) + +(fact 5) ; => 120 + +;;; И без + +(defun fact (n) + (loop :for result = 1 :then (* result i) + :for i :from 2 :to n + :finally (return result))) + +(fact 5) ; => 120 + +(loop :for x :across "abc" :collect x) +; => (#\a #\b #\c #\d) + +(dolist (i '(1 2 3 4)) + (format t "~A" i)) +; => 1234 + + +;;;----------------------------------------------------------------------------- +;;; 6. Установка значений в переменные (и не только) +;;;----------------------------------------------------------------------------- + +;;; Для присвоения переменной нового значения используйте SETF. Это уже было +;;; при работе с хеш таблицами. + +(let ((variable 10)) + (setf variable 2)) +; => 2 + +;;; Для функционального подхода в программировании, старайтесь избегать измений +;;; в переменных. + +;;;----------------------------------------------------------------------------- +;;; 7. Классы и объекты +;;;----------------------------------------------------------------------------- + +;;; Никаких больше животных в примерах. Берем устройства приводимые в движение +;;; мускульной силой человека. + +(defclass human-powered-conveyance () + ((velocity + :accessor velocity + :initarg :velocity) + (average-efficiency + :accessor average-efficiency + :initarg :average-efficiency)) + (:documentation "Устройство движимое человеческой силой")) + +;;; Аргументы DEFCLASS: +;;; 1. Имя класса +;;; 2. Список родительских классов +;;; 3. Список полей +;;; 4. Необязательная метаинформация + +;;; Если родительские классы не заданы, используется "стандартный" класс +;;; Это можно *изменить*, но хорошенько подумайте прежде. Если все-таки +;;; решились вам поможет "Art of the Metaobject Protocol" + +(defclass bicycle (human-powered-conveyance) + ((wheel-size + :accessor wheel-size + :initarg :wheel-size + :documentation "Diameter of the wheel.") + (height + :accessor height + :initarg :height))) + +(defclass recumbent (bicycle) + ((chain-type + :accessor chain-type + :initarg :chain-type))) + +(defclass unicycle (human-powered-conveyance) nil) + +(defclass canoe (human-powered-conveyance) + ((number-of-rowers + :accessor number-of-rowers + :initarg :number-of-rowers))) + +;;; Если вызвать DESCRIBE для HUMAN-POWERED-CONVEYANCE то получите следующее: + +(describe 'human-powered-conveyance) + +; COMMON-LISP-USER::HUMAN-POWERED-CONVEYANCE +; [symbol] +; +; HUMAN-POWERED-CONVEYANCE names the standard-class #<STANDARD-CLASS +; HUMAN-POWERED-CONVEYANCE>: +; Documentation: +; A human powered conveyance +; Direct superclasses: STANDARD-OBJECT +; Direct subclasses: UNICYCLE, BICYCLE, CANOE +; Not yet finalized. +; Direct slots: +; VELOCITY +; Readers: VELOCITY +; Writers: (SETF VELOCITY) +; AVERAGE-EFFICIENCY +; Readers: AVERAGE-EFFICIENCY +; Writers: (SETF AVERAGE-EFFICIENCY) + +;;; CL задизайнен как интерактивная система. В рантайме доступна информация о +;;; типе объектов. + +;;; Давайте посчитаем расстояние, которое пройдет велосипед за один оборот колеса +;;; по формуле C = d * pi + +(defmethod circumference ((object bicycle)) + (* pi (wheel-size object))) + +;;; PI - это константа в CL + +;;; Предположим мы нашли, что критерий эффективности логарифмически связан +;;; с гребцами каноэ. Тогда вычисление можем сделать сразу при инициализации. + +;;; Инициализируем объект после его создания: + +(defmethod initialize-instance :after ((object canoe) &rest args) + (setf (average-efficiency object) (log (1+ (number-of-rowers object))))) + + +;;; Давайте проверим что получилось с этой самой эффективностью... + +(average-efficiency (make-instance 'canoe :number-of-rowers 15)) +; => 2.7725887 + + +;;;----------------------------------------------------------------------------- +;;; 8. Макросы +;;;----------------------------------------------------------------------------- + +;;; Макросы позволяют расширить синаксис языка. В CL нет например цикла WHILE, +;;; но его проще простого реализовать на макросах. Если мы отбросим наши +;;; ассемблерные (или алгольные) инстинкты, мы взлетим на крыльях: + +(defmacro while (condition &body body) + "Пока `условие` истинно, выполняется `тело`. +`Условие` проверяется перед каждым выполнением `тела`" + (let ((block-name (gensym)) (done (gensym))) + `(tagbody + ,block-name + (unless ,condition + (go ,done)) + (progn + ,@body) + (go ,block-name) + ,done))) + +;;; Взглянем на более высокоуровневую версию этого макроса: + +(defmacro while (condition &body body) + "Пока `условие` истинно, выполняется `тело`. +`Условие` проверяется перед каждым выполнением `тела`" + `(loop while ,condition + do + (progn + ,@body))) + +;;; В современных комиляторах LOOP так же эффективен как и приведенный +;;; выше код. Поэтому используйте его, его проще читать. + +;;; В макросах используются символы ```, `,` и `@`. ``` - это оператор +;;; квазиквотирования - это значит что форма исполнятся не будет, а вернется +;;; как данные. Оператаор `,` позволяет исполнить форму внутри +;;; квазиквотирования. Оператор `@` исполняет форму внутри квазиквотирования +;;; но полученный список вклеивает по месту. + +;;; GENSYM создаёт уникальный символ, который гарантировано больше нигде в +;;; системе не используется. Так надо потому, что макросы разворачиваются +;;; во время компиляции и переменные объявленные в макросе могут совпасть +;;; по имени с переменными в обычном коде. + +;;; Дальнйешую информацию о макросах ищите в книгах Practical Common Lisp +;;; и On Lisp +``` + +## Для чтения + +На русском +- [Practical Common Lisp](http://www.gigamonkeys.com/book/) + +На английском +- [Practical Common Lisp](http://www.gigamonkeys.com/book/) +- [Common Lisp: A Gentle Introduction to Symbolic Computation](https://www.cs.cmu.edu/~dst/LispBook/book.pdf) + + +## Дополнительная информация + +На русском + +- [Lisper.ru](http://lisper.ru/) + +На английском + +- [CLiki](http://www.cliki.net/) +- [common-lisp.net](https://common-lisp.net/) +- [Awesome Common Lisp](https://github.com/CodyReichert/awesome-cl) +- [Lisp Lang](http://lisp-lang.org/) + + +## Благодарности в английской версии + +Спасибо людям из Scheme за отличную статью, взятую за основу для +Common Lisp. + + +- [Paul Khuong](https://github.com/pkhuong) за хорошую вычитку. diff --git a/ru-ru/crystal-ru.html.markdown b/ru-ru/crystal-ru.html.markdown new file mode 100644 index 00000000..87d12f23 --- /dev/null +++ b/ru-ru/crystal-ru.html.markdown @@ -0,0 +1,584 @@ +--- +language: crystal +filename: learncrystal-ru.cr +contributors: + - ["Vitalii Elenhaupt", "http://veelenga.com"] + - ["Arnaud Fernandés", "https://github.com/TechMagister/"] +translators: + - ["Den Patin", "https://github.com/denpatin"] +lang: ru-ru +--- + +```crystal +# — так начинается комментарий + + +# Всё является объектом +nil.class #=> Nil +100.class #=> Int32 +true.class #=> Bool + +# Возвращают false только nil, false и пустые указатели +!nil #=> true : Bool +!false #=> true : Bool +!0 #=> false : Bool + + +# Целые числа + +1.class #=> Int32 + +# Четыре типа целых чисел со знаком +1_i8.class #=> Int8 +1_i16.class #=> Int16 +1_i32.class #=> Int32 +1_i64.class #=> Int64 + +# Четыре типа целых чисел без знака +1_u8.class #=> UInt8 +1_u16.class #=> UInt16 +1_u32.class #=> UInt32 +1_u64.class #=> UInt64 + +2147483648.class #=> Int64 +9223372036854775808.class #=> UInt64 + +# Двоичные числа +0b1101 #=> 13 : Int32 + +# Восьмеричные числа +0o123 #=> 83 : Int32 + +# Шестнадцатеричные числа +0xFE012D #=> 16646445 : Int32 +0xfe012d #=> 16646445 : Int32 + +# Числа с плавающей точкой + +1.0.class #=> Float64 + +# Два типа чисел с плавающей запятой +1.0_f32.class #=> Float32 +1_f32.class #=> Float32 + +1e10.class #=> Float64 +1.5e10.class #=> Float64 +1.5e-7.class #=> Float64 + + +# Символьные литералы + +'a'.class #=> Char + +# Восьмеричный код символа +'\101' #=> 'A' : Char + +# Код символа Unicode +'\u0041' #=> 'A' : Char + + +# Строки + +"s".class #=> String + +# Строки неизменяемы +s = "hello, " #=> "hello, " : String +s.object_id #=> 134667712 : UInt64 +s += "Crystal" #=> "hello, Crystal" : String +s.object_id #=> 142528472 : UInt64 + +# Поддерживается интерполяция строк +"sum = #{1 + 2}" #=> "sum = 3" : String + +# Поддерживается многострочность +"This is + multiline string" + +# Строка с двойными кавычками +%(hello "world") #=> "hello \"world\"" + + +# Символы — константы без значения, определяемые только именем. Часто +# используются вместо часто используемых строк для лучшей производительности. +# На внутреннем уровне они представлены как Int32. + +:symbol.class #=> Symbol + +sentence = :question? # :"question?" : Symbol + +sentence == :question? #=> true : Bool +sentence == :exclamation! #=> false : Bool +sentence == "question?" #=> false : Bool + + +# Массивы + +[1, 2, 3].class #=> Array(Int32) +[1, "hello", 'x'].class #=> Array(Int32 | String | Char) + +# При объявлении пустого массива необходимо указать тип его элементов +[] # Syntax error: for empty arrays use '[] of ElementType' +[] of Int32 #=> [] : Array(Int32) +Array(Int32).new #=> [] : Array(Int32) + +# Элементы внутри массива имеют свои индексы +array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5] : Array(Int32) +array[0] #=> 1 : Int32 +array[10] # raises IndexError +array[-6] # raises IndexError +array[10]? #=> nil : (Int32 | Nil) +array[-6]? #=> nil : (Int32 | Nil) + +# Можно получать элементы по индексу с конца +array[-1] #=> 5 + +# С начала и с указанием размера итогового массива +array[2, 3] #=> [3, 4, 5] + +# Или посредством указания диапазона +array[1..3] #=> [2, 3, 4] + +# Добавление в массив +array << 6 #=> [1, 2, 3, 4, 5, 6] + +# Удаление элемента из конца массива +array.pop #=> 6 +array #=> [1, 2, 3, 4, 5] + +# Удаление элемента из начала массива +array.shift #=> 1 +array #=> [2, 3, 4, 5] + +# Проверка на наличие элемента в массиве +array.includes? 3 #=> true + +# Синтаксический сахар для массива строк и символов +%w(one two three) #=> ["one", "two", "three"] : Array(String) +%i(one two three) #=> [:one, :two, :three] : Array(Symbol) + +# Массивоподобный синтаксис используется и для других типов, только если для +# них определены методы .new и #<< +set = Set{1, 2, 3} #=> [1, 2, 3] +set.class #=> Set(Int32) + +# Вышеприведенное эквивалентно следующему +set = Set(typeof(1, 2, 3)).new +set << 1 +set << 2 +set << 3 + + +# Хэши + +{1 => 2, 3 => 4}.class #=> Hash(Int32, Int32) +{1 => 2, 'a' => 3}.class #=> Hash(Int32 | Char, Int32) + +# При объявлении пустого хэша необходимо указать типы ключа и значения +{} # Syntax error +{} of Int32 => Int32 # {} +Hash(Int32, Int32).new # {} + +# Значения в хэше легко найти по ключу +hash = {"color" => "green", "number" => 5} +hash["color"] #=> "green" +hash["no_such_key"] #=> Missing hash key: "no_such_key" (KeyError) +hash["no_such_key"]? #=> nil + +# Проверка наличия ключа в хэше +hash.has_key? "color" #=> true + +# Синтаксический сахар для символьных и строковых ключей +{key1: 'a', key2: 'b'} # {:key1 => 'a', :key2 => 'b'} +{"key1": 'a', "key2": 'b'} # {"key1" => 'a', "key2" => 'b'} + +# Хэшеподобный синтаксис используется и для других типов, только если для них +# определены методы .new и #[]= +class MyType + def []=(key, value) + puts "do stuff" + end +end + +MyType{"foo" => "bar"} + +# Вышеприведенное эквивалентно следующему +tmp = MyType.new +tmp["foo"] = "bar" +tmp + + +# Диапазоны + +1..10 #=> Range(Int32, Int32) +Range.new(1, 10).class #=> Range(Int32, Int32) + +# Включающий и исключающий диапазоны +(3..5).to_a #=> [3, 4, 5] +(3...5).to_a #=> [3, 4] + +# Проверка на вхождение в диапазон +(1..8).includes? 2 #=> true + + +# Кортежи +# Неизменяемые последовательности фиксированного размера, содержащие, +# как правило, элементы разных типов + +{1, "hello", 'x'}.class #=> Tuple(Int32, String, Char) + +# Доступ к элементам осуществляется по индексу +tuple = {:key1, :key2} +tuple[1] #=> :key2 +tuple[2] #=> syntax error : Index out of bound + +# Элементы кортежей можно попарно присвоить переменным +a, b, c = {:a, 'b', "c"} +a #=> :a +b #=> 'b' +c #=> "c" + + +# Процедуры +# Указатели на функцию с необязательным содержимым (замыкание). +# Обычно создаётся с помощью специального литерала -> + +proc = ->(x : Int32) { x.to_s } +proc.class # Proc(Int32, String) +# Или посредством метода .new +Proc(Int32, String).new { |x| x.to_s } + +# Вызываются посредством метода .call +proc.call 10 #=> "10" + + +# Управляющие операторы + +if true + "if statement" +elsif false + "else-if, optional" +else + "else, also optional" +end + +puts "if as a suffix" if true + +# if как часть выражения +a = if 2 > 1 + 3 + else + 4 + end + +a #=> 3 + +# Тернарный if +a = 1 > 2 ? 3 : 4 #=> 4 + +# Оператор выбора +cmd = "move" + +action = case cmd + when "create" + "Creating..." + when "copy" + "Copying..." + when "move" + "Moving..." + when "delete" + "Deleting..." +end + +action #=> "Moving..." + + +# Циклы + +index = 0 +while index <= 3 + puts "Index: #{index}" + index += 1 +end +# Index: 0 +# Index: 1 +# Index: 2 +# Index: 3 + +index = 0 +until index > 3 + puts "Index: #{index}" + index += 1 +end +# Index: 0 +# Index: 1 +# Index: 2 +# Index: 3 + +# Но лучше использовать each +(1..3).each do |index| + puts "Index: #{index}" +end +# Index: 1 +# Index: 2 +# Index: 3 + +# Тип переменной зависит от типа выражения +if a < 3 + a = "hello" +else + a = true +end +typeof a #=> (Bool | String) + +if a && b + # здесь гарантируется, что и a, и b — не nil +end + +if a.is_a? String + a.class #=> String +end + + +# Методы + +def double(x) + x * 2 +end + +# Методы (а также любые блоки) всегда возвращают значение последнего выражения +double(2) #=> 4 + +# Скобки можно опускать, если вызов метода не вносит двусмысленности +double 3 #=> 6 + +double double 3 #=> 12 + +def sum(x, y) + x + y +end + +# Параметры методов перечисляются через запятую +sum 3, 4 #=> 7 + +sum sum(3, 4), 5 #=> 12 + + +# yield + +# У всех методов есть неявный необязательный параметр блока, который можно +# вызвать ключевым словом yield + +def surround + puts '{' + yield + puts '}' +end + +surround { puts "hello world" } + +# { +# hello world +# } + +# Методу можно передать блок +# & — ссылка на переданный блок +def guests(&block) + block.call "some_argument" +end + +# Методу можно передать список параметров, доступ к ним будет как к массиву +# Для этого используется оператор * +def guests(*array) + array.each { |guest| puts guest } +end + +# Если метод возвращает массив, можно попарно присвоить значение каждого из его +# элементов переменным +def foods + ["pancake", "sandwich", "quesadilla"] +end +breakfast, lunch, dinner = foods +breakfast #=> "pancake" +dinner #=> "quesadilla" + +# По соглашению название методов, возвращающих булево значение, должно +# оканчиваться вопросительным знаком +5.even? # false +5.odd? # true + +# Если название метода оканчивается восклицательным знаком, по соглашению это +# означает, что метод делает что-то необратимое, например изменяет получателя. +# Некоторые методы имеют две версии: "опасную" версию с !, которая что-то +# меняет, и "безопасную", которая просто возвращает новое значение +company_name = "Dunder Mifflin" +company_name.gsub "Dunder", "Donald" #=> "Donald Mifflin" +company_name #=> "Dunder Mifflin" +company_name.gsub! "Dunder", "Donald" +company_name #=> "Donald Mifflin" + + +# Классы +# Определяются с помощью ключевого слова class + +class Human + + # Переменная класса является общей для всех экземпляров этого класса + @@species = "H. sapiens" + + # Объявление типа переменной name экземпляра класса + @name : String + + # Базовый конструктор + # Значением первого параметра инициализируем переменную @name. + # То же делаем и со вторым параметром — переменная @age. В случае, если мы + # не передаём второй параметр, для инициализации @age будет взято значение + # по умолчанию (в данном случае — 0) + def initialize(@name, @age = 0) + end + + # Базовый метод установки значения переменной + def name=(name) + @name = name + end + + # Базовый метод получения значения переменной + def name + @name + end + + # Синтаксический сахар одновременно для двух методов выше + property :name + + # А также по отдельности + getter :name + setter :name + + # Метод класса определяется ключевым словом self, чтобы его можно было + # различить с методом экземпляра класса. Такой метод можно вызвать только + # на уровне класса, а не экземпляра. + def self.say(msg) + puts msg + end + + def species + @@species + end +end + + +# Создание экземпляра класса +jim = Human.new("Jim Halpert") + +dwight = Human.new("Dwight K. Schrute") + +# Вызов методов экземпляра класса +jim.species #=> "H. sapiens" +jim.name #=> "Jim Halpert" +jim.name = "Jim Halpert II" #=> "Jim Halpert II" +jim.name #=> "Jim Halpert II" +dwight.species #=> "H. sapiens" +dwight.name #=> "Dwight K. Schrute" + +# Вызов метода класса +Human.say("Hi") #=> выведет "Hi" и вернёт nil + +# Переменные экземпляра класса (@) видно только в пределах экземпляра +class TestClass + @var = "I'm an instance var" +end + +# Переменные класса (@) видны как в экземплярах класса, так и в самом классе +class TestClass + @@var = "I'm a class var" +end + +# Переменные с большой буквы — это константы +Var = "I'm a constant" +Var = "can't be updated" # Error: already initialized constant Var + +# Примеры + +# Базовый класс +class Human + @@foo = 0 + + def self.foo + @@foo + end + + def self.foo=(value) + @@foo = value + end +end + +# Класс-потомок +class Worker < Human +end + +Human.foo #=> 0 +Worker.foo #=> 0 + +Human.foo = 2 #=> 2 +Worker.foo #=> 0 + +Worker.foo = 3 #=> 3 +Human.foo #=> 2 +Worker.foo #=> 3 + +module ModuleExample + def foo + "foo" + end +end + +# Подключение модуля в класс добавляет его методы в экземпляр класса +# Расширение модуля добавляет его методы в сам класс + +class Person + include ModuleExample +end + +class Book + extend ModuleExample +end + +Person.foo # => undefined method 'foo' for Person:Class +Person.new.foo # => 'foo' +Book.foo # => 'foo' +Book.new.foo # => undefined method 'foo' for Book + + +# Обработка исключений + +# Создание пользовательского типа исключения +class MyException < Exception +end + +# Ещё одного +class MyAnotherException < Exception; end + +ex = begin + raise MyException.new +rescue ex1 : IndexError + "ex1" +rescue ex2 : MyException | MyAnotherException + "ex2" +rescue ex3 : Exception + "ex3" +rescue ex4 # без указания конкретного типа исключения будут "отлавливаться" все + "ex4" +end + +ex #=> "ex2" + +``` + +## Дополнительная информация + +### На русском + +- [Официальная документация](http://ru.crystal-lang.org/docs/) + +### На английском + +- [Official Documentation](http://crystal-lang.org/) diff --git a/ru-ru/jquery-ru.html.markdown b/ru-ru/jquery-ru.html.markdown new file mode 100644 index 00000000..471b4e24 --- /dev/null +++ b/ru-ru/jquery-ru.html.markdown @@ -0,0 +1,127 @@ +--- +category: tool +tool: jquery +contributors: + - ["Sawyer Charles", "https://github.com/xssc"] +translators: + - ["Ev Bogdanov", "https://github.com/evbogdanov"] +lang: ru-ru +filename: jquery-ru.js +--- + +jQuery — это библиотека JavaScript, которая помогает "делать больше, писать меньше". Она выполняет множество типичных JavaScript-задач, упрощая написание кода. jQuery используется крупными компаниями и разработчиками со всего мира. Она упрощает и ускоряет работу с AJAX, с событиями, с DOM и со многим другим. + +Поскольку jQuery является библиотекой JavaScript, вам следует начать с [изучения JavaScript](https://learnxinyminutes.com/docs/ru-ru/javascript-ru/). + +```js + + +/////////////////////////////////// +// 1. Селекторы + +// Для получения элемента в jQuery используются селекторы +var page = $(window); // Получить страницу целиком + +// В качестве селектора может выступать CSS-селектор +var paragraph = $('p'); // Получить все <p> элементы +var table1 = $('#table1'); // Получить элемент с идентификатором 'table1' +var squares = $('.square'); // Получить все элементы с классом 'square' +var square_p = $('p.square') // Получить <p> элементы с классом 'square' + + +/////////////////////////////////// +// 2. События и эффекты +// jQuery прекрасно справляется с обработкой событий +// Часто используемое событие — это событие документа 'ready' +// Вы можете использовать метод 'ready', который сработает, как только документ полностью загрузится +$(document).ready(function(){ + // Код не выполнится до тех пор, пока документ не будет загружен +}); +// Обработку события можно вынести в отдельную функцию +function onAction() { + // Код выполнится, когда произойдёт событие +} +$('#btn').click(onAction); // Обработчик события сработает при клике + +// Другие распространённые события: +$('#btn').dblclick(onAction); // Двойной клик +$('#btn').hover(onAction); // Наведение курсора +$('#btn').focus(onAction); // Фокус +$('#btn').blur(onAction); // Потеря фокуса +$('#btn').submit(onAction); // Отправка формы +$('#btn').select(onAction); // Когда выбрали элемент +$('#btn').keydown(onAction); // Когда нажали клавишу +$('#btn').keyup(onAction); // Когда отпустили клавишу +$('#btn').keypress(onAction); // Когда нажали символьную клавишу (нажатие привело к появлению символа) +$('#btn').mousemove(onAction); // Когда переместили курсор мыши +$('#btn').mouseenter(onAction); // Когда навели курсор на элемент +$('#btn').mouseleave(onAction); // Когда сдвинули курсор с элемента + + +// Вы можете не только обрабатывать события, но и вызывать их +$('#btn').dblclick(); // Вызвать двойной клик на элементе + +// Для одного селектора возможно назначить несколько обработчиков событий +$('#btn').on( + {dblclick: myFunction1} // Обработать двойной клик + {blur: myFunction1} // Обработать исчезновение фокуса +); + +// Вы можете перемещать и прятать элементы с помощью методов-эффектов +$('.table').hide(); // Спрятать элемент(ы) + +// Обратите внимание: вызов функции в этих методах всё равно спрячет сам элемент +$('.table').hide(function(){ + // Сначала спрятать элемент, затем вызвать функцию +}); + +// Вы можете хранить селекторы в переменных +var tables = $('.table'); + +// Некоторые основные методы для манипуляций с документом: +tables.hide(); // Спрятать элемент(ы) +tables.show(); // Показать элемент(ы) +tables.toggle(); // Спрятать/показать +tables.fadeOut(); // Плавное исчезновение +tables.fadeIn(); // Плавное появление +tables.fadeToggle(); // Плавное исчезновение или появление +tables.fadeTo(0.5); // Изменение прозрачности +tables.slideUp(); // Свернуть элемент +tables.slideDown(); // Развернуть элемент +tables.slideToggle(); // Свернуть или развернуть + +// Все эти методы принимают скорость (в миллисекундах) и функцию обратного вызова +tables.hide(1000, myFunction); // Анимация длится 1 секунду, затем вызов функции + +// В методе 'fadeTo' вторым параметром обязательно идёт прозрачность +tables.fadeTo(2000, 0.1, myFunction); // Прозрачность меняется в течение 2 секунд до 0.1, затем вызывается функция + +// Метод 'animate' позволяет делать более продвинутую анимацию +tables.animate({"margin-top": "+=50", height: "100px"}, 500, myFunction); + + +/////////////////////////////////// +// 3. Манипуляции + +// Манипуляции похожи на эффекты, но позволяют добиться большего +$('div').addClass('taming-slim-20'); // Добавить класс 'taming-slim-20' ко всем <div> элементам + +// Часто встречающиеся методы манипуляций +$('p').append('Hello world'); // Добавить в конец элемента +$('p').attr('class'); // Получить атрибут +$('p').attr('class', 'content'); // Установить атрибут +$('p').hasClass('taming-slim-20'); // Проверить наличие класса +$('p').height(); // Получить или установить высоту элемента + + +// Во многих методах вам доступна информация ТОЛЬКО о первом элементе из выбранных +$('p').height(); // Вы получите высоту только для первого <p> элемента + +// Метод 'each' позволяет это исправить и пройтись по всем выбранным вами элементам +var heights = []; +$('p').each(function() { + heights.push($(this).height()); // Добавить высоту всех <p> элементов в массив +}); + + +``` diff --git a/ru-ru/markdown-ru.html.markdown b/ru-ru/markdown-ru.html.markdown index 91f53f54..579a9a20 100644 --- a/ru-ru/markdown-ru.html.markdown +++ b/ru-ru/markdown-ru.html.markdown @@ -43,6 +43,7 @@ Markdown является надмножеством HTML, поэтому люб и попадают в итоговый HTML без изменений. Однако следует понимать, что эта же особенность не позволяет использовать разметку Markdown внутри HTML-элементов --> +``` ## Заголовки diff --git a/ru-ru/php-composer-ru.html.markdown b/ru-ru/php-composer-ru.html.markdown new file mode 100644 index 00000000..ef6e4912 --- /dev/null +++ b/ru-ru/php-composer-ru.html.markdown @@ -0,0 +1,196 @@ +--- +category: tool +tool: composer +contributors: + - ["Alesey Lysenko", "https://github.com/nasgul"] +filename: LearnComposer-ru.sh +lang: ru-ru +--- + +[Composer](https://getcomposer.org/) это инструмент управления зависимостями в PHP. +Он позволяет вам декларировать библиотеки, от которых зависит ваш проект, +и он будет управлять (устанавливать / обновлять) их для вас. + +# Установка + +```sh +# Устанавливаем composer.phar в текущую папку +curl -sS https://getcomposer.org/installer | php +# Если вы используете этот подход, вам нужно будет вызвать композер следующим образом: +php composer.phar about + +# Устанавливаем с бинарников ~/bin/composer +# Примечание: убедитесь, что ~/bin находится в переменной PATH вашего окружения +curl -sS https://getcomposer.org/installer | php -- --install-dir=~/bin --filename=composer +``` + +Пользователи Windows должны следовать +[Инструкциям по установке в Windows ](https://getcomposer.org/doc/00-intro.md#installation-windows) + +## Подтверждение установки + +```sh +# # Проверить версию и параметры списка +composer + +# Получить дополнительную помощь для параметров +composer help require + +# Проверьте, способен ли Composer делать то, что ему нужно, и если он обновлен +композитор диагностирует +composer diagnose +composer diag # shorthand + +# Обновление Composer к последней версии +composer self-update +composer self # shorthand +``` + +# Использование + +Композитор сохраняет ваши зависимости проекта в `composer.json`. +Вы можете отредактировать этот файл, но лучше всего позволить Composer управлять им для вас. + +```sh +# Создать новый проект в текущей папке +composer init +# запускается интерактивная анкета с просьбой предоставить подробную информацию о вашем проекте. +# Оставляя их пустым, все прекрасно, если вы не делаете другие проекты зависимыми от этого. + +# Если файл composer.json уже существует, загрузите зависимости +composer install + +# Чтобы загрузить только производственные зависимости, т. Е. Исключая зависимости разработки +composer install --no-dev + +# Добавить зависимость от этого проекта +composer require guzzlehttp/guzzle +# выяснит, какая последняя версия guzzlehttp / guzzle есть, +# загрузите ее и добавьте новую зависимость в поле require.console. + +composer require guzzlehttp/guzzle:6.0.* +# будет загружать последнюю версию, соответствующую шаблону (например, 6.0.2), +# и добавить зависимость к полю require.json + +composer require --dev phpunit/phpunit:~4.5.0 +# потребуется как зависимость от разработки. +# Будет использовать последнюю версию> = 4.5.0 и <4.6.0 + +composer require-dev phpunit/phpunit:^4.5.0 +# потребуется как зависимость от разработки. Будет использовать последнюю версию> = 4.5.0 и <5.0 + +# Для получения дополнительной информации о совместимости версий Composer см. +# [Документация композитора по версиям] (https://getcomposer.org/doc/articles/versions.md) +# для получения более подробной информации + +# Чтобы узнать, какие пакеты доступны для установки и в настоящее время установлены +composer show + +# Чтобы узнать, какие пакеты в настоящее время установлены +composer show --installed + +# Чтобы найти пакет с «mailgun» в его названии или описании +composer search mailgun +``` + +[Packagist.org](https://packagist.org/) является основным хранилищем для пакетов Composer. +Поиск там для существующих сторонних пакетов. + +## `composer.json` vs `composer.lock` + +Файл `composer.json` хранит ваши параметры плавающей версии вашего проекта для каждой зависимости, +а также другую информацию. + + +Файл `composer.lock` хранит точно, какую версию он загрузил для каждой зависимости. +Никогда не редактируйте этот файл. + +Если вы включите файл `composer.lock` в свой репозиторий git, +каждый разработчик установит текущую версию зависимостей. +Даже когда выпущена новая версия зависимости, Composer продолжит загрузку версии, +записанной в файле блокировки. + +```sh +# Если вы хотите обновить все зависимости до их новейшей версии, +# которые по-прежнему соответствуют вашим предпочтениям в версии обновление композитора +composer update + +# Если вам нужна новая версия определенной зависимости: +composer update phpunit/phpunit + +# Если вы хотите перенести пакет на более новую версию, +# вам может потребоваться сначала удалить старый пакет и его зависимости. +composer remove --dev phpunit/phpunit +composer require --dev phpunit/phpunit:^5.0 +``` + +## Автозагрузчик + +Composer создает класс автозагрузки, который вы можете потребовать от своего приложения. +Вы можете создавать экземпляры классов через их пространство имен. + +```php +require __DIR__ . '/vendor/autoload.php'; + +$mailgun = new Mailgun\Mailgun("key"); +``` + +### PSR-4 Autoloader + +### Автозагрузчик PSR-4 + +Вы можете добавить свои собственные пространства имен в автозагрузчик. + +Вы можете добавить свои собственные пространства имен в автозагрузчик. + +В `composer.json` добавьте поле 'autoload': + +```json +{ + "autoload": { + "psr-4": {"Acme\\": "src/"} + } +} +``` +Это скажет автозагрузчику искать что-либо в пространстве имен `\ Acme \` в папке `src`. + +Вы также можете использовать +[PSR-0, Classmap или просто список файлов для включения](https://getcomposer.org/doc/04-schema.md#autoload). +Также существует поле `autoload-dev` для пространств имен, предназначенных только для разработки. + +При добавлении или изменении ключа автозагрузки вам необходимо перестроить автозагрузчик: + +```sh +composer dump-autoload +composer dump # shorthand + +# Оптимизирует пакеты PSR0 и PSR4 для загрузки классов. +# Медленно запускается, но улучшает производительность при производстве. +composer dump-autoload --optimize --no-dev +``` + +# Composer Кэш + +```sh +# Composer сохранит загруженные пакеты для использования в будущем. Очистите его с помощью: +composer clear-cache +``` + +# Поиск проблемы + +```sh +composer diagnose +composer self-update +composer clear-cache +``` + +## Темы, которые пока (пока) не включены в этот учебник + +* Создание и распространение ваших собственных пакетов на Packagist.org или в другом месте +* Предварительные и пост-скриптовые перехватчики: запуск задач, +когда происходят определенные события композитора + +### Рекомендации + +* [Composer - Dependency Manager for PHP](https://getcomposer.org/) +* [Packagist.org](https://packagist.org/) diff --git a/ru-ru/rust-ru.html.markdown b/ru-ru/rust-ru.html.markdown new file mode 100644 index 00000000..7bd2809a --- /dev/null +++ b/ru-ru/rust-ru.html.markdown @@ -0,0 +1,316 @@ +--- +language: rust + +filename: learnrust-ru.rs +contributors: + - ["P1start", "http://p1start.github.io/"] +translators: + - ["Anatolii Kosorukov", "https://github.com/java1cprog"] +lang: ru-ru + +--- + +Rust сочетает в себе низкоуровневый контроль над производительностью с удобством высокого уровня и предоставляет гарантии +безопасности. +Он достигает этих целей, не требуя сборщика мусора или времени выполнения, что позволяет использовать библиотеки Rust как замену +для C-библиотек. + +Первый выпуск Rust, 0.1, произошел в январе 2012 года, и в течение 3 лет развитие продвигалось настолько быстро, что до +недавнего времени использование стабильных выпусков было затруднено, и вместо этого общий совет заключался в том, чтобы +использовать последние сборки. + +15 мая 2015 года был выпущен Rust 1.0 с полной гарантией обратной совместимости. Усовершенствования времени компиляции и +других аспектов компилятора в настоящее время доступны в ночных сборках. Rust приняла модель выпуска на поезде с регулярными выпусками каждые шесть недель. Rust 1.1 beta был доступен одновременно с выпуском Rust 1.0. + +Хотя Rust является языком относительно низкого уровня, Rust имеет некоторые функциональные концепции, которые обычно +встречаются на языках более высокого уровня. Это делает Rust не только быстрым, но и простым и эффективным для ввода кода. + + +```rust +// Это однострочный комментарии +// + +/// Так выглядит комментарий для документации +/// # Examples +/// +/// +/// let seven = 7 +/// + +/////////////// +// 1. Основы // +/////////////// + +// Функции +// `i32` это целочисленный знаковый тип 32-bit +#[allow(dead_code)] +fn add2(x: i32, y: i32) -> i32 { + // метод возвращает сумму x и y + x + y +} + +// Главная функция программы +#[allow(unused_variables)] +#[allow(unused_assignments)] +#[allow(dead_code)] +fn main() { + // Числа // + + // неизменяемая переменная + let x: i32 = 1; + + // Суффиксы целое/дробное + let y: i32 = 13i32; + let f: f64 = 1.3f64; + + // Автоматическое выявление типа данных + // В большинстве случаев компилятор Rust может вычислить + // тип переменной, поэтому + // вам не нужно писать явные аннотации типа. + + let implicit_x = 1; + let implicit_f = 1.3; + + // Арифметика + let sum = x + y + 13; + + // Изменяемая переменная + let mut mutable = 1; + mutable = 4; + mutable += 2; + + // Строки // + + // Строковые литералы + let x: &str = "hello world!"; + + // Печать на консоль + println!("{} {}", f, x); // 1.3 hello world + + // `String` – изменяемя строка + let s: String = "hello world".to_string(); + + // Строковый срез - неизменяемый вид в строки + // Это в основном неизменяемая пара указателей на строку - + // Это указатель на начало и конец строкового буфера + + let s_slice: &str = &s; + + println!("{} {}", s, s_slice); // hello world hello world + + // Vectors/arrays // + + // фиксированный массив + let four_ints: [i32; 4] = [1, 2, 3, 4]; + + // динамический массив + let mut vector: Vec<i32> = vec![1, 2, 3, 4]; + vector.push(5); + + // Срез - неизменяемое представление значений вектора + let slice: &[i32] = &vector; + + // Используйте шаблон `{:?}`для печати отладочной информации структур с данными + println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] + + // Кортежи // + + // Кортеж - это фиксированный набор. + // В нём могут находиться значения разных типов данных. + let x: (i32, &str, f64) = (1, "hello", 3.4); + + // Инициализация группы переменных `let` + let (a, b, c) = x; + println!("{} {} {}", a, b, c); // 1 hello 3.4 + + // Доступ по индексу + println!("{}", x.1); // hello + + ////////////// + // 2. Типы // + ////////////// + + // Struct + struct Point { + x: i32, + y: i32, + } + + let origin: Point = Point { x: 0, y: 0 }; + + // Структуры могут быть с безымянными полями ‘tuple struct’ + struct Point2(i32, i32); + + let origin2 = Point2(0, 0); + + // Перечисление + enum Direction { + Left, + Right, + Up, + Down, + } + + let up = Direction::Up; + + // Перечисление с полями + enum OptionalI32 { + AnI32(i32), + Nothing, + } + + let two: OptionalI32 = OptionalI32::AnI32(2); + let nothing = OptionalI32::Nothing; + + // Обобщенные типы данных // + + struct Foo<T> { bar: T } + + // Частоиспользуемое перечисление стандартной библиотеки `Option` + enum Optional<T> { + SomeVal(T), + NoVal, + } + + // Методы // + + impl<T> Foo<T> { + fn get_bar(self) -> T { + self.bar + } + } + + let a_foo = Foo { bar: 1 }; + println!("{}", a_foo.get_bar()); // 1 + + // Типаж + + trait Frobnicate<T> { + fn frobnicate(self) -> Option<T>; + } + + impl<T> Frobnicate<T> for Foo<T> { + fn frobnicate(self) -> Option<T> { + Some(self.bar) + } + } + + let another_foo = Foo { bar: 1 }; + println!("{:?}", another_foo.frobnicate()); // Some(1) + + ///////////////////////// + // 3. Поиск по шаблону // + ///////////////////////// + + let foo = OptionalI32::AnI32(1); + match foo { + OptionalI32::AnI32(n) => println!("it’s an i32: {}", n), + OptionalI32::Nothing => println!("it’s nothing!"), + } + + // Более сложный пример + struct FooBar { x: i32, y: OptionalI32 } + let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) }; + + match bar { + FooBar { x: 0, y: OptionalI32::AnI32(0) } => + println!("The numbers are zero!"), + FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m => + println!("The numbers are the same"), + FooBar { x: n, y: OptionalI32::AnI32(m) } => + println!("Different numbers: {} {}", n, m), + FooBar { x: _, y: OptionalI32::Nothing } => + println!("The second number is Nothing!"), + } + + ///////////////////// + // 4. Управление ходом выполнения программы // + ///////////////////// + + // `for` loops/iteration + let array = [1, 2, 3]; + for i in array.iter() { + println!("{}", i); + } + + // Отрезки + for i in 0u32..10 { + print!("{} ", i); + } + println!(""); + // prints `0 1 2 3 4 5 6 7 8 9 ` + + // `if` + if 1 == 1 { + println!("Maths is working!"); + } else { + println!("Oh no..."); + } + + // `if` as expression + let value = if true { + "good" + } else { + "bad" + }; + + // `while` loop + while 1 == 1 { + println!("The universe is operating normally."); + break; + } + + // Infinite loop + loop { + println!("Hello!"); + break; + } + + ///////////////////////////////// + // 5. Защита памяти и указатели // + ///////////////////////////////// + + // Владеющий указатель – такой указатель может быть только один + // Это значит, что при вызоде из блока переменная автоматически становится недействительной. + let mut mine: Box<i32> = Box::new(3); + *mine = 5; // dereference + // Здесь, `now_its_mine` получает во владение `mine`. Т.е. `mine` была перемещена. + let mut now_its_mine = mine; + *now_its_mine += 2; + + println!("{}", now_its_mine); // 7 + // println!("{}", mine); + + // Ссылки - это неизменяемые указатели + // Если ссылка получает значения, то говорят, что она заимствует это значение. + // Такое значение не может быть изменено или перемещено. + let mut var = 4; + var = 3; + let ref_var: &i32 = &var; + + println!("{}", var); + println!("{}", *ref_var); + // var = 5; // не скомпилируется + // *ref_var = 6; // и это + + // Изменяемые ссылки + // + let mut var2 = 4; + let ref_var2: &mut i32 = &mut var2; + *ref_var2 += 2; // '*' используется для изменения значения + + println!("{}", *ref_var2); // 6 , // var2 would not compile. + // ref_var2 имеет тип &mut i32, т.е. он содержит ссылку на i32, а не значение. + // var2 = 2; // не скомпилируется, т.к. эта переменная уже была заимствована ранее +} + +``` + +## Более подробная информация о языке + +Уже есть хорошие книги для изучающих Rust. Основным источником остаётся +[The Rust Programming Language](http://doc.rust-lang.org/book/index.html) + +Для компиляции программ при изучении языка весьма удобно использовать +[Rust playpen](http://play.rust-lang.org). +Множество ресурсов на разных языках можно найти в [этом проекте](https://github.com/ctjhoa/rust-learning). |