diff options
| -rw-r--r-- | c++.html.markdown | 2 | ||||
| -rw-r--r-- | cs-cz/sass.html.markdown | 439 | ||||
| -rw-r--r-- | elm.html.markdown | 68 | ||||
| -rw-r--r-- | ru-ru/d-ru.html.markdown | 753 | 
4 files changed, 1232 insertions, 30 deletions
diff --git a/c++.html.markdown b/c++.html.markdown index 6b452b1b..f4aa2f5a 100644 --- a/c++.html.markdown +++ b/c++.html.markdown @@ -149,7 +149,7 @@ namespace First {  namespace Second {      void foo()      { -        printf("This is Second::foo\n") +        printf("This is Second::foo\n");      }  } diff --git a/cs-cz/sass.html.markdown b/cs-cz/sass.html.markdown new file mode 100644 index 00000000..0d2fca64 --- /dev/null +++ b/cs-cz/sass.html.markdown @@ -0,0 +1,439 @@ +--- +language: sass +filename: learnsass-cz.scss +contributors: +  - ["Laura Kyle", "https://github.com/LauraNK"] +  - ["Sean Corrales", "https://github.com/droidenator"] +translators: +  - ["Michal Martinek", "https://github.com/MichalMartinek"] +lang: cs-cz +--- + +Sass je rozšíření jazyka CSS, který přidává nové vlastnosti jako proměnné, zanořování, mixiny a další. +Sass (a další preprocesory, jako  [Less](http://lesscss.org/)) pomáhají vývojářům psát udržovatelný a neopakující (DRY) kód. + +Sass nabízí dvě možnosti syntaxe. SCSS, které je stejná jako CSS, akorát obsahuje nové vlastnosti Sassu. Nebo Sass, který používá odsazení místo složených závorek a středníků. +Tento tutoriál bude používat syntaxi CSS. + + +Pokud jste již obeznámeni s CSS3, budete schopni používat Sass relativně rychle. Nezprostředkovává nějaké úplně nové stylové možnosti, spíše nátroje, jak psát Vás CSS kód více efektivně, udržitelně a jednoduše. + +```scss + + +//Jednořádkové komentáře jsou ze Sassu při kompilaci vymazány + +/*Víceřádkové komentáře jsou naopak zachovány */ + + + +/*Proměnné +==============================*/ + + + +/* Můžete uložit CSS hodnotu (jako třeba barvu) do proměnné. +Použijte symbol '$' k jejímu vytvoření. */ + +$hlavni-barva: #A3A4FF; +$sekundarni-barva: #51527F; +$body-font: 'Roboto', sans-serif; + +/* Můžete používat proměnné napříč vaším souborem. +Teď, když chcete změnit barvu, stačí ji změnit pouze jednou.*/ + +body { +	background-color: $hlavni-barva; +	color: $sekundarni-barva; +	font-family: $body-font; +} + +/* Toto se zkompiluje do: */ +body { +	background-color: #A3A4FF; +	color: #51527F; +	font-family: 'Roboto', sans-serif; +} + + +/* Toto je o hodně více praktické, než měnit každý výskyt barvy.  */ + + + +/*Mixiny +==============================*/ + + + +/* Pokud zjistíte, že píšete kód pro více než jeden element, můžete jej uložit do mixinu. + +Použijte '@mixin' direktivu, plus jméno vašeho mixinu.*/ + +@mixin na-stred { +	display: block; +	margin-left: auto; +	margin-right: auto; +	left: 0; +	right: 0; +} + +/* Mixin vložíte pomocí '@include' a jména mixinu */ + +div { +	@include na-stred; +	background-color: $hlavni-barva; +} + +/*Což se zkompiluje do: */ +div { +	display: block; +	margin-left: auto; +	margin-right: auto; +	left: 0; +	right: 0; +	background-color: #A3A4FF; +} + + +/* Můžete využít mixiny i třeba pro takovéto ušetření práce: */ + +@mixin velikost($sirka, $vyska) { +	width: $sirka; +	height: $vyska; +} + +/*Stačí vložit argumenty: */ + +.obdelnik { +	@include velikost(100px, 60px); +} + +.ctverec { +	@include velikost(40px, 40px); +} + +/* Toto se zkompiluje do: */ +.obdelnik { +  width: 100px; +  height: 60px; +} + +.ctverec { +  width: 40px; +  height: 40px; +} + + + +/*Funkce +==============================*/    + + + +/* Sass obsahuje funkce, které vám pomůžou splnit různé úkoly. */ + +/* Funkce se spouštějí pomocí jejich jména, které následuje seznam argumentů uzavřený v kulatých závorkách. */ +body { +  width: round(10.25px);     +} + +.footer { +  background-color: fade_out(#000000, 0.25) +} + +/* Se zkompiluje do: */ + +body { +  width: 10px; +} + +.footer { +  background-color: rgba(0, 0, 0, 0.75); +}    + +/* Můžete také definovat vlastní funkce. Funkce jsou velmi podobné mixinům. +   Když se snažíte vybrat mezi funkcí a mixinem, mějte na paměti, že mixiny +   jsou lepší pro generování CSS kódu, zatímco funkce jsou lepší pro logiku. +   Příklady ze sekce Matematické operátory jsou skvělí kandidáti na +   znovupoužitelné funkce. */ + +/* Tato funkce vrací poměr k velikosti rodiče v procentech. +@function vypocitat-pomer($velikost, $velikost-rodice) { +  @return $velikost / $velikost-rodice * 100%; +} + +$hlavni obsah: vypocitat-pomer(600px, 960px); + +.hlavni-obsah { +  width: $hlavni-obsah; +} + +.sloupec { +  width: vypocitat-pomer(300px, 960px); +} + +/* Zkompiluje do: */ + +.hlavni-obsah { +  width: 62.5%; +} + +.sloupec { +  width: 31.25%; +} + + + +/*Dědění +==============================*/ + + + +/*Dědění je způsob jak používat vlastnosti pro jeden selektor ve druhém. */ + +.oznameni { +	@include velikost(5em, 5em); +	border: 5px solid $sekundarni-barva; +} + +.oznameni-uspech { +	@extend .oznameni; +	border-color: #22df56; +} + +/* Zkompiluje do: */ +.oznameni, .oznameni-uspech { +  width: 5em; +  height: 5em; +  border: 5px solid #51527F; +} + +.oznameni-uspech { +  border-color: #22df56; +} + + +/* Dědění CSS výrazů je preferováno před vytvořením mixinu kvůli způsobu, +   jakým způsobem Sass dává dohromady třídy, které sdílejí stejný kód. +   Kdyby to bylo udělané pomocí mixinu, tak výška, šířka, rámeček by byl v +   každém výrazu, který by volal mixin. I když tohle neovlivní vaše workflow, +   přidá to kód navíc do souborů. */ + + +/*Zanořování +==============================*/ + + + +/*Sass vám umožňuje zanořovat selektory do selektorů */ + +ul { +	list-style-type: none; +	margin-top: 2em; + +	li { +		background-color: #FF0000; +	} +} + +/* '&' nahradí rodičovský element. */ +/* Můžete také zanořovat pseudo třídy. */ +/* Pamatujte, že moc velké zanoření do hloubky snižuje čitelnost. +   Doporučuje se používat maximálně trojité zanoření. +   Na příklad: */ + +ul { +	list-style-type: none; +	margin-top: 2em; + +	li { +		background-color: red; + +		&:hover { +		  background-color: blue; +		} + +		a { +		  color: white; +		} +	} +} + +/* Zkompiluje do: */ + +ul { +  list-style-type: none; +  margin-top: 2em; +} + +ul li { +  background-color: red; +} + +ul li:hover { +  background-color: blue; +} + +ul li a { +  color: white; +} + + + +/*Částečné soubory a importy +==============================*/    + + + +/* Sass umožňuje vytvářet částečné soubory. Tyto soubory pomahájí udržovat váš +   kód modulární. Tyto soubory by měli začínat vždy '_', např. _reset.css. +   Částečné soubory se nepřevádí do CSS. */ + +/* Toto je kód, který si uložíme do souboru _reset.css */ + +html, +body, +ul, +ol { +  margin: 0; +  padding: 0; +} + +/* Sass obsahuje @import, které může být použit pro import částečných souborů. +   Toto se liší od klasického CSS @import, který dělá HTTP požadavek na stáhnutí +   souboru. Sass vezme importovaný soubor a vloží ho do kompilovaného kódu. */ + +@import 'reset'; + +body { +  font-size: 16px; +  font-family: Helvetica, Arial, Sans-serif; +} + +/* Zkompiluje do: */ + +html, body, ul, ol { +  margin: 0; +  padding: 0; +}    + +body { +  font-size: 16px; +  font-family: Helvetica, Arial, Sans-serif; +} + + + +/*Zástupné selektory +==============================*/   + + + +/* Zástupné selektory jsou užitečné, když vytváříte CSS výraz, ze kterého +   chcete později dědit. Když chcete vytvořit výraz, ze kterého je možné pouze +   dědit pomocí @extend, vytvořte zástupný selektor s CSS výrazem. Ten začíná +   symbolem '%' místo '.' nebo '#'. Tyto výrazy se neobjeví ve výsledném CSS */ + +%okno-obsahu { +  font-size: 14px; +  padding: 10px; +  color: #000; +  border-radius: 4px; +} + +.okno-zpravy { +  @extend %okno-obsahu; +  background-color: #0000ff; +} + +/* Zkompiluje do: */ + +.okno-zpravy { +  font-size: 14px; +  padding: 10px; +  color: #000; +  border-radius: 4px; +} + +.okno-zpravy { +  background-color: #0000ff; +} + + + +/*Matematické operace +==============================*/    + + + +/* Sass obsahuje následující operátory: +, -, *, /, and %. Tyto operátory +   můžou být velmi užitečné pro počítání hodnot přímo ve vašem souboru Sass. +   Níže je příklad, jak udělat jednoduchý dvousloupcový layout. */ + +$oblast-obsahu: 960px; +$hlavni-obsah: 600px; +$vedlejsi-sloupec: 300px; + +$obsah-velikost: $hlavni-obsah / $oblast-obsahu * 100%; +$vedlejsi-sloupec-velikost: $vedlejsi-sloupec / $oblast-obsahu * 100%; +$zbytek-velikost: 100% - ($main-size + $vedlejsi-sloupec-size); + +body { +  width: 100%; +} + +.hlavni-obsah { +  width: $obsah-velikost; +} + +.vedlejsi-sloupec { +  width: $vedlejsi-sloupec-velikost; +} + +.zbytek { +  width: $zbytek-velikost; +} + +/* Zkompiluje do: */ + +body { +  width: 100%; +} + +.hlavni-obsah { +  width: 62.5%; +} + +.vedlejsi-sloupec { +  width: 31.25%; +} + +.gutter { +  width: 6.25%; +} + + +``` + + + +## SASS nebo Sass? +Divili jste se někdy, jestli je Sass zkratka nebo ne? Pravděpodobně ne, ale řeknu vám to stejně. Jméno tohoto jazyka je slovo, "Sass", a ne zkratka. +Protože to lidé konstatně píší jako "SASS", nazval ho autor jazyka jako "Syntactically Awesome StyleSheets" (Syntaktický úžasně styly). + + +## Procvičování Sassu +Pokud si chcete hrát se Sassem ve vašem prohlížeči, navštivte [SassMeister](http://sassmeister.com/). +Můžete používát oba dva způsoby zápisu, stačí si vybrat v nastavení SCSS nebo SASS. + + +## Kompatibilita + +Sass může být použit v jakémkoliv projektu, jakmile máte program, pomocí kterého ho zkompilujete do CSS. Pokud si chcete ověřit, že CSS, které Sass produkuje je kompatibilní s prohlížeči: + +[QuirksMode CSS](http://www.quirksmode.org/css/) a [CanIUse](http://caniuse.com) jsou skvělé stránky pro kontrolu kompatibility. + + +## Kam dál? +* [Oficiální dokumentace](http://sass-lang.com/documentation/file.SASS_REFERENCE.html) +* [The Sass Way](http://thesassway.com/) obsahuje tutoriál a řadu skvělých článků diff --git a/elm.html.markdown b/elm.html.markdown index f8564c4b..f395e85b 100644 --- a/elm.html.markdown +++ b/elm.html.markdown @@ -38,11 +38,10 @@ not False -- True  1 < 10 -- True  -- Strings and characters -"This is a string." -'a' -- character -'You cant use single quotes for strings.' -- error! +"This is a string because it uses double quotes." +'a' -- characters in single quotes --- Strings can be appended +-- Strings can be appended.  "Hello " ++ "world!" -- "Hello world!"  {-- Lists, Tuples, and Records --} @@ -53,10 +52,10 @@ not False -- True  -- The second example can also be written with two dots.  [1..5] --- Append lists just like strings +-- Append lists just like strings.  [1..5] ++ [6..10] == [1..10] -- True --- To add one item, use "cons" +-- To add one item, use "cons".  0 :: [1..5] -- [0, 1, 2, 3, 4, 5]  -- The head and tail of a list are returned as a Maybe. Instead of checking @@ -64,6 +63,7 @@ not False -- True  List.head [1..5] -- Just 1  List.tail [1..5] -- Just [2, 3, 4, 5]  List.head [] -- Nothing +-- List.functionName means the function lives in the List module.  -- Every element in a tuple can be a different type, but a tuple has a  -- fixed length. @@ -74,23 +74,24 @@ List.head [] -- Nothing  fst ("elm", 42) -- "elm"  snd ("elm", 42) -- 42 --- Records are like tuples but the fields have names. --- Notice that equals signs, not colons, are used. +-- Records are like tuples but the fields have names. The order of fields +-- doesn't matter. Notice that record values use equals signs, not colons.  { x = 3, y = 7 }  -- Access a field with a dot and the field name.  { x = 3, y = 7 }.x -- 3 --- Or with an accessor fuction, a dot and then the field name. +-- Or with an accessor fuction, which is a dot and the field name on its own.  .y { x = 3, y = 7 } -- 7  -- Update the fields of a record. (It must have the fields already.)  { person |    name = "George" } -{ physics | -  position = physics.position + physics.velocity, -  velocity = physics.velocity + physics.acceleration } +-- Update multiple fields at once, using the current values. +{ particle | +  position = particle.position + particle.velocity, +  velocity = particle.velocity + particle.acceleration }  {-- Control Flow --} @@ -111,11 +112,15 @@ else  -- Use case statements to pattern match on different possibilities.  case aList of    [] -> "matches the empty list" +  [x]-> "matches a list of exactly one item, " ++ toString x    x::xs -> "matches a list of at least one item whose head is " ++ toString x +-- Pattern matches go in order. If we put [x] last, it would never match because +-- x::xs also matches (xs would be the empty list). Matches do not "fall through". +-- Pattern match on a Maybe.  case List.head aList of    Just x -> "The head is " ++ toString x -  Nothing -> "The list was empty" +  Nothing -> "The list was empty."  {-- Functions --} @@ -151,8 +156,8 @@ area (width, height) =  area (6, 7) -- 42 --- Use curly brackets to pattern match record field names --- Use let to define intermediate values +-- Use curly brackets to pattern match record field names. +-- Use let to define intermediate values.  volume {width, height, depth} =    let      area = width * height @@ -161,7 +166,7 @@ volume {width, height, depth} =  volume { width = 3, height = 2, depth = 7 } -- 42 --- Functions can be recursive +-- Functions can be recursive.  fib n =    if n < 2 then      1 @@ -170,12 +175,13 @@ fib n =  List.map fib [0..8] -- [1, 1, 2, 3, 5, 8, 13, 21, 34] +-- Another recursive function (use List.length in real code).  listLength aList =    case aList of      [] -> 0      x::xs -> 1 + listLength xs --- Function application happens before any infix operation +-- Function calls happen before any infix operator. Parens indicate precedence.  cos (degrees 30) ^ 2 + sin (degrees 30) ^ 2 -- 1  -- First degrees is applied to 30, then the result is passed to the trig  -- functions, which is then squared, and the addition happens last. @@ -191,7 +197,7 @@ cos (degrees 30) ^ 2 + sin (degrees 30) ^ 2 -- 1  True : Bool  -- Functions have types too. Read -> as "goes to". Think of the rightmost type --- as the type of the return value. +-- as the type of the return value, and the others as arguments.  not : Bool -> Bool  round : Float -> Int @@ -226,7 +232,7 @@ type alias Point3D = { x : Float, y : Float, z : Float }  otherOrigin : Point3D  otherOrigin = Point3D 0 0 0 --- But it's still the same type, you can equate them +-- But it's still the same type, so you can equate them.  origin == otherOrigin -- True  -- By contrast, defining a union type creates a type that didn't exist before. @@ -236,14 +242,15 @@ type Direction = North | South | East | West  -- Tags can carry other values of known type. This can work recursively.  type IntTree = Leaf | Node Int IntTree IntTree -  -- "Leaf" and "Node" are the tags. Everything following a tag is a type. +  -- Tags can be used as values or functions.  root : IntTree  root = Node 7 Leaf Leaf  -- Union types (and type aliases) can use type variables.  type Tree a = Leaf | Node a (Tree a) (Tree a) +-- "The type tree of a is a leaf, or a node of a, tree of a, and tree of a."  -- You can pattern match union tags. The uppercase tags must be matched exactly.  -- The lowercase variables will match anything. Underscore also matches @@ -260,21 +267,20 @@ leftmostElement tree =  {-- Modules and Imports --} --- The core libraries are organized into modulues, as are any third-party --- libraries you may use. For large projects, you can define your own modulues. +-- The core libraries are organized into modules, as are any third-party +-- libraries you may use. For large projects, you can define your own modules.  -- Put this at the top of the file. If omitted, you're in Main.  module Name where --- By default, everything is exported. --- Limit what values and types are exported -module Name (Type, value) where +-- By default, everything is exported. You can specify exports explicity. +module Name (MyType, myValue) where  -- One common pattern is to export a union type but not its tags. This is known  -- as an "opaque type", and is frequently used in libraries. --- Import code from other modules to use it in this one --- Places Dict in scope, so you can call Dict.insert +-- Import code from other modules to use it in this one. +-- Places Dict in scope, so you can call Dict.insert.  import Dict  -- Imports the Dict module and the Dict type, so your annotations don't have to @@ -318,6 +324,8 @@ $ elm repl  -- Install a new package, and record it in elm-package.json.  $ elm package install evancz/elm-html +-- See what changed between versions of a package. +$ elm package diff evancz/elm-html 3.0.0 4.0.2  -- Elm's package manager enforces semantic versioning, so minor version bumps  -- will never break your build!  ``` @@ -335,12 +343,14 @@ Here are some useful resources.  * Documentation for [Elm's core libraries](http://package.elm-lang.org/packages/elm-lang/core/latest/). Take note of:    * [Basics](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics), which is imported by default -  * Data structures like [Array](http://package.elm-lang.org/packages/elm-lang/core/latest/Array), [Dict](http://package.elm-lang.org/packages/elm-lang/core/latest/Dict), and [Set](http://package.elm-lang.org/packages/elm-lang/core/latest/Set) +  * [Maybe](http://package.elm-lang.org/packages/elm-lang/core/latest/Maybe) and its cousin [Result](http://package.elm-lang.org/packages/elm-lang/core/latest/Result), commonly used for missing values or error handling +  * Data structures like [List](http://package.elm-lang.org/packages/elm-lang/core/latest/List), [Array](http://package.elm-lang.org/packages/elm-lang/core/latest/Array), [Dict](http://package.elm-lang.org/packages/elm-lang/core/latest/Dict), and [Set](http://package.elm-lang.org/packages/elm-lang/core/latest/Set)    * JSON [encoding](http://package.elm-lang.org/packages/elm-lang/core/latest/Json-Encode) and [decoding](http://package.elm-lang.org/packages/elm-lang/core/latest/Json-Decode) -* [The Elm Architecture](https://github.com/evancz/elm-architecture-tutorial#the-elm-architecture). An essay with examples on how to organize code into components. +* [The Elm Architecture](https://github.com/evancz/elm-architecture-tutorial#the-elm-architecture). An essay by Elm's creator with examples on how to organize code into components.  * The [Elm mailing list](https://groups.google.com/forum/#!forum/elm-discuss). Everyone is friendly and helpful. +* [Scope in Elm](https://github.com/elm-guides/elm-for-js/blob/master/Scope.md#scope-in-elm) and [How to Read a Type Annotation](https://github.com/elm-guides/elm-for-js/blob/master/How%20to%20Read%20a%20Type%20Annotation.md#how-to-read-a-type-annotation). More community guides on the basics of Elm, written for JavaScript developers.  Go out and write some Elm! diff --git a/ru-ru/d-ru.html.markdown b/ru-ru/d-ru.html.markdown new file mode 100644 index 00000000..8f4233fd --- /dev/null +++ b/ru-ru/d-ru.html.markdown @@ -0,0 +1,753 @@ +--- +language: d +filename: learnd-ru.d +contributors: +    - ["Anton Pastukhov", "http://dprogramming.ru/"] +    - ["Robert Brights-Gray", "http://lhs-blog.info/"] +    - ["Andre Polykanine", "http://oire.me/"] +lang: ru-ru +--- +D - современный компилируемый язык общего назначения с Си-подобным синтаксисом, +который сочетает удобство, продуманный дизайн и высокую производительность. +D - это С++, сделанный правильно. + +```d +// Welcome to D! Это однострочный комментарий + +/* многострочный +   комментарий  */ + +/+ +    // вложенные комментарии + +    /* еще вложенные +       комментарии */ + +    /+ +        // мало уровней вложенности? Их может быть сколько угодно. +    +/ ++/ + +/* +    Имя модуля. Каждый файл с исходным кодом на D — модуль. +    Если имя не указано явно, то предполагается, что оно совпадает с именем +    файла. Например, для файла "test.d" имя модуля будет "test", если явно +    не указать другое + */ +module app; + +// импорт модуля. Std — пространство имен стандартной библиотеки (Phobos) +import std.stdio; + +// можно импортировать только нужные части, не обязательно модуль целиком +import std.exception : enforce; + +// точка входа в программу — функция main, аналогично C/C++ +void main() +{ +    writeln("Hello, world!"); +} + + + +/*** типы и переменные ***/ + +int a; // объявление переменной типа int (32 бита) +float b = 12.34; // тип с плавающей точкой +double c = 56.78; // тип с плавающей точкой (64 бита) + +/* +    Численные типы в D, за исключением типов с плавающей точкой и типов +    комплексных чисел, могут быть беззнаковыми. +    В этом случае название типа начинается с префикса "u" +*/ +uint d = 10; ulong e = 11; +bool b = true; // логический тип +char d = 'd';  // UTF-символ, 8 бит. D поддерживает UTF "из коробки" +wchar e = 'é';   // символ UTF-16 +dchar f;       // и даже UTF-32, если он вам зачем-то понадобится + +string s = "для строк есть отдельный тип, это не просто массив char-ов из Си"; +wstring ws = "поскольку у нас есть wchar, должен быть и  wstring"; +dstring ds = "...и dstring, конечно"; + +string кириллица = "Имена переменных должны быть в Unicode, но не обязательно на латинице."; + +typeof(a) b = 6; // typeof возвращает тип своего выражения. +                 // В результате, b имеет такой же тип, как и a + +// Тип переменной, помеченной ключевым словом auto, +// присваивается компилятором исходя из значения этой переменной +auto x = 1;              // Например, тип этой переменной будет int. +auto y = 1.1;            // этой — double +auto z = "Zed is dead!"; // а этой — string + +int[3] arr = [1, 2, 3]; // простой одномерный массив с фиксированным размером +int[] arr2 = [1, 2, 3, 4]; // динамический массив +int[string] aa = ["key1": 5, "key2": 6]; // ассоциативный массив + +/* +   Строки и массивы в D — встроенные типы. Для их использования не нужно +   подключать ни внешние, ни даже стандартную библиотеку, хотя в последней +   есть множество дополнительных инструментов для работы с ними. + */ +immutable int ia = 10;  // неизменяемый тип, +                        // обозначается ключевым словом immutable +ia += 1;                // — вызовет ошибку на этапе компиляции + +// перечислимый (enumerable) тип, +// более правильный способ работы с константами в D +enum myConsts = { Const1, Const2, Const3 }; + +// свойства типов +writeln("Имя типа               : ", int.stringof); // int +writeln("Размер в байтах        : ", int.sizeof);   // 4 +writeln("Минимальное значение   : ", int.min);      // -2147483648 +writeln("Максимальное значение : ", int.max);      // 2147483647 +writeln("Начальное значение     : ", int.init);     // 0. Это значение, +                                                    // присвоенное по умолчанию + +// На самом деле типов в D больше, но все мы здесь описывать не будем, +// иначе не уложимся в Y минут. + + + +/*** Приведение типов ***/ + +// to!(имя типа)(выражение) - для большинства конверсий +import std.conv : to; // функция "to" - часть стандартной библиотеки, а не языка +double d = -1.75; +short s = to!short(d); // s = -1 + +/* +   cast - если вы знаете, что делаете. Кроме того, это единственный способ +   преобразования типов-указателей в "обычные" и наоборот +*/ +void* v; +int* p = cast(int*)v; + +// Для собственного удобства можно создавать псевдонимы +// для различных встроенных объектов +alias int newInt; // теперь можно обращаться к newInt так, как будто бы это int +newInt a = 5; + +alias newInt = int; // так тоже допустимо +alias uint[2] pair; // дать псевдоним можно даже сложным структурам данных + + + +/*** Операторы ***/ + +int x = 10; // присваивание +x = x + 1;  // 11 +x -= 2;     // 9 +x++;        // 10 +++x;        // 11 +x *= 2;     // 22 +x /= 2;     // 11 +x = x ^^ 2; // 121 (возведение в степень) +x ^^= 2;    // 1331 (то же самое) + +string str1 = "Hello"; +string str2 = ", world!"; +string hw = str1 ~ str2; // Конкатенация строк + +int[] arr = [1, 2, 3]; +arr ~= 4; // [1, 2, 3, 4] - добавление элемента в конец массива + + + +/*** Логика и сравнения ***/ + +int x = 0; int y = 1; + +x == y;         // false +x > y;          // false +x < y;          // true +x >= y;         // false +x != y;         // true. ! — логическое "не" +x > 0 || x < 1; // true. || — логическое "или" +x > 0 && x < 1; // false && — логическое "и" +x ^ y           // true; ^ - xor (исключающее "или") + +// Тернарный оператор +auto y = (x > 10) ? 1 : 0; // если x больше 10, то y равен 1, +                           // в противном случае y равен нулю + + +/***  Управляющие конструкции  ***/ + +// if - абсолютно привычен +if (a == 1) { +    // .. +} else if (a == 2) { +    // .. +} else { +    // .. +} + +// switch +switch (a) { +    case 1: +        // делаем что-нибудь +        break; +    case 2: +        // делаем что-нибудь другое +        break; +    case 3: +        // делаем что-нибудь еще +        break; +    default: +        // default обязателен, без него будет ошибка компиляции +        break; +} + +// в D есть констукция "final switch". Она не может содержать секцию "defaul" +// и применяется, когда все перечисляемые в switch варианты должны быть +// обработаны явным образом + +int dieValue = 1; +final switch (dieValue) { +    case 1: +        writeln("You won"); +        break; + +    case 2, 3, 4, 5: +        writeln("It's a draw"); +        break; + +    case 6: +        writeln("I won"); +        break; +} + +// while +while (a > 10) { +    // .. +    if (number == 42) { +        break; +    } +} + +while (true) { +    // бесконечный цикл +} + +// do-while +do { +    // .. +} while (a == 10); + +// for +for (int number = 1; number < 11; ++number) { +    writeln(number); // все абсолютно стандартно +} + +for ( ; ; ) { +    // секции могут быть пустыми. Это бесконечный цикл в стиле Си +} + +// foreach - универсальный и самый "правильный" цикл в D +foreach (element; array) { +    writeln(element); // для простых массивов +} + +foreach (key, val; aa) { +    writeln(key, ": ", val); // для ассоциативных массивов +} + +foreach (c; "hello") { +    writeln(c); // hello. Поскольку строки - это вариант массива, +                // foreach применим и к ним +} + +foreach (number; 10..15) { +    writeln(number); // численные интервалы можно указывать явным образом +                     // этот цикл выведет значения с 10 по 14, но не 15, +                     // поскольку диапазон не включает в себя верхнюю границу +} + +// foreach_reverse - в обратную сторону +auto container = [1, 2, 3]; +foreach_reverse (element; container) { +    writefln("%s ", element); // 3, 2, 1 +} + +// foreach в массивах и им подобных структурах не меняет сами структуры +int[] a = [1, 2 ,3 ,4 ,5]; +foreach (elem; array) { +    elem *= 2; // сам массив останется неизменным +} + +writeln(a); // вывод: [1, 2, 3, 4, 5] Т.е изменений нет + +// добавление ref приведет к тому, что массив будет изменяться +foreach (ref elem; array) { +    elem *= 2; +} + +writeln(a); // [2, 4, 6, 8, 10] + +// foreach умеет рассчитывать индексы элементов +int[] a = [1, 2, 3, 4, 5]; +foreach (ind, elem; array) { +    writeln(ind, " ", elem); // через ind - доступен индекс элемента, +                             // а через elem - сам элемент +} + + + +/*** Функции ***/ + +test(42); // Что, вот так сразу? Разве мы где-то уже объявили эту функцию? + +// Нет, вот она. Это не Си, здесь объявление функции не обязательно должно быть +// до первого вызова +int test(int argument) { +    return argument * 2; +} + + +// В D используется единый синтаксис вызова функций +// (UFCS, Uniform Function Call Syntax), поэтому так тоже можно: +int var = 42.test(); + +// и даже так, если у функции нет аргументов: +int var2 = 42.test; + +// можно выстраивать цепочки: +int var3 = 42.test.test; + +/* +    Аргументы в функцию передаются по значению (т.е. функция работает не с +    оригинальными значениями, переданными ей, а с их локальными копиями. +    Исключение составляют объекты классов, которые передаются по ссылке. +    Кроме того, любой параметр можно передать в функцию по ссылке с помощью +    ключевого слова "ref" +*/ +int var = 10; + +void fn1(int arg) { +    arg += 1; +} + +void fn2(ref int arg) { +    arg += 1; +} + +fn1(var); // var все еще = 10 +fn2(var); // теперь var = 11 + +// Возвращаемое значение тоже может быть auto, +// если его можно "угадать" из контекста +auto add(int x, int y) { +    return x + y; +} + +auto z = add(x, y); // тип int - компилятор вывел его автоматически + +// Значения аргументов по умолчанию +float linearFunction(float k, float x, float b = 1) +{ +    return k * x + b; +} + +auto linear1 = linearFunction(0.5, 2, 3); // все аргументы используются +auto linear2 = linearFunction(0.5, 2);    // один аргумент пропущен, но в функции +                                          // он все равно использован и равен 1 + +// допускается описание вложенных функций +float quarter(float x) { +    float doubled(float y) { +        return y * y; +    } + +    return doubled(doubled(x)); +} + +// функции с переменным числом аргументов +int sum(int[] a...) +{ +    int s = 0; +    foreach (elem; a) { +        s += elem; +    } +    return s; +} + +auto sum1 = sum(1); +auto sum2 = sum(1,2,3,4); + +/* +   модификатор "in" перед аргументами функций говорит о том, что функция имеет +    право их только просматривать. При попытке модификации такого аргумента +    внутри функции - получите ошибку +*/ +float printFloat(in float a) +{ +    writeln(a); +} +printFloat(a); // использование таких функций - самое обычное + +// модификатор "out" позволяет вернуть из функции несколько результатов +// без посредства глобальных переменных или массивов +uint remMod(uint a, uint b, out uint modulus) +{ +    uint remainder = a / b; +    modulus = a % b; +    return remainder; +} + +uint modulus;                   // пока в этой переменной ноль +uint rem = remMod(5, 2, modulus); // наша "хитрая" функция, и теперь +                                // в modulus - остаток от деления +writeln(rem, " ", modulus);     // вывод: 2 1 + + + +/*** Структуры, классы, базовое ООП ***/ + +// Объявление структуры. Структуры почти как в Си +struct MyStruct { +    int a; +    float b; + +    void multiply() { +        return a * b; +    } +} + +MyStruct str1; // Объявление переменной с типом MyStruct +str1.a = 10;   // Обращение к полю +str1.b = 20; +auto result = str1.multiply(); +MyStruct str2 = {4, 8}          // Объявление + инициализация  в стиле Си +auto str3 = MyStruct(5, 10);    // Объявление + инициализация  в стиле D + + +// области видимости полей и методов - 3 способа задания +struct MyStruct2 { +    public int a; + +    private: +        float b; +        bool c; + +    protected { +        float multiply() { +            return a * b; +        } +    } +    /* +        в дополнение к знакомым public, private и protected, в D есть еще +        область видимости "package". Поля и методы с этим атрибутом будут +        доступны изо всех модулей, включенных в "пакет" (package), но не +        за его пределами. package - это "папка", в которой может храниться +        несколько модулей. Например, в "import.std.stdio", "std" - это +        package, в котором есть модуль stdio (и еще множество других) +    */ +    package: +        string d; + +    /* помимо этого, имеется еще один модификатор - export, который позволяет +    использовать объявленный с ним идентификатор даже вне самой программы ! +    */ +    export: +         string description; +} + +// Конструкторы и деструкторы +struct MyStruct3 { +    this() { // конструктор. Для структур его не обязательно указывать явно, +             // в этом случае пустой конструктор добавляется компилятором +        writeln("Hello, world!"); +    } + + +    // а вот это конструкция - одна из интересных идиом и представляет собой +    // конструктор копирования, т.е конструктор, возвращающий копию структуры. +    // Работает только в структурах. +    this(this) +    { +        return this; +    } + +    ~this() { // деструктор, также необязателен +        writeln("Awww!"); +    } +} + +// Объявление простейшего класса +class MyClass { +    int a;  // в D по умолчанию данные-члены являются public +    float b; +} + +auto mc = new MyClass(); // ...и создание его экземпляра +auto mc2 = new MyClass; // ... тоже сработает + +// Конструктор +class MyClass2 { +    int a; +    float b; + +    this(int a, float b) { +        this.a = a; // ключевое слово "this" - ссылка на объект класса +        this.b = b; +    } +} + +auto mc2 = new MyClass2(1, 2.3); + +// Классы могут быть вложенными +class Outer +{ +    int m; + +    class Inner +    { +        int foo() +        { +            return m; // можно обращаться к полям "внешнего" класса +        } +    } +} + +// наследование +class Base { +    int a = 1; +    float b = 2.34; + + +    // это статический метод, т.е метод который можно вызывать, обращаясь +    // к классу напрямую, а не через создание экземпляра объекта +    static void multiply(int x, int y) +    { +        writeln(x * y); +    } +} + +Base.multiply(2, 5); // используем статический метод. Результат: 10 + +class Derived : Base { +    string c = "Поле класса - наследника"; + + +    // override означает то, что наследник предоставит свою реализацию метода, +    // переопределив метод базового класса +    override static void multiply(int x, int y) +    { +        super.multiply(x, y);  // super - это ссылка на класс-предок, или базовый класс +        writeln(x * y * 2); +    } +} + +auto mc3 = new Derived(); +writeln(mc3.a); // 1 +writeln(mc3.b); // 2.34 +writeln(mc3.c); // Поле класса - наследника + +// Финальный класс, наследовать от него нельзя +// кроме того, модификатор final работает не только для классов, но и для методов +// и даже для модулей ! +final class FC { +    int a; +} + +class Derived : FC { // это вызовет ошибку +    float b; +} + +// Абстрактный класс не может быть истанциирован, но может иметь наследников +abstract class AC { +    int a; +} + +auto ac = new AC(); // это вызовет ошибку + +class Implementation : AC { +    float b; + +     // final перед методом нефинального класса означает запрет возможности +     // переопределения метода +    final void test() +    { +       writeln("test passed !"); +    } +} + +auto impl = new Implementation(); // ОК + + + +/*** Примеси (mixins) ***/ + +// В D можно вставлять код как строку, если эта строка известна на этапе +// компиляции. Например: +void main() { +   mixin(`writeln("Hello World!");`); +} + +// еще пример +string print(string s) { +   return `writeln("` ~ s ~ `");`; +} + +void main() { +   mixin (print("str1")); +   mixin (print("str2")); +} + + + +/*** Шаблоны ***/ + +/* +    Шаблон функции. Эта функция принимает аргументы разных типов, которые +    подставляются вместо T на этапе компиляции. "T" - это не специальный +    символ, а просто буква. Вместо "T" может быть любое слово, кроме ключевого. + */ +void print(T)(T value) { +   writefln("%s", value); +} + +void main() { +   print(42);     // В одну и ту же функцию передается: целое +   print(1.2);    // ...число с плавающей точкой, +   print("test"); // ...строка +} + +// "Шаблонных" параметров может быть сколько угодно +void print(T1, T2)(T1 value1, T2 value2) { +   writefln(" %s %s", value1, value2); +} + +void main() { +   print(42, "Test"); +   print(1.2, 33); +} + +// Шаблон класса +class Stack(T) +{ +    private: +        T[] elements; + +    public: +        void push(T element) { +            elements ~= element; +        } + +        void pop() { +            --elements.length; +        } + +        T top() const @property { +            return elements[$ - 1]; +        } + +        size_t length() const @property { +            return elements.length; +        } +} + +void main() { +    /* +        восклицательный знак - признак шаблона. В данном случае мы создаем +        класс и указываем, что "шаблонное" поле будет иметь тип string +    */ +   auto stack = new Stack!string; + +   stack.push("Test1"); +   stack.push("Test2"); + +   writeln(stack.top); +   writeln(stack.length); + +   stack.pop; +   writeln(stack.top); +   writeln(stack.length); +} + + + +/*** Диапазоны (ranges) ***/ + +/* +   Диапазоны - это абстракция, которая позволяет легко использовать разные +   алгоритмы с разными структурами данных. Вместо того, чтобы определять свои +   уникальные алгоритмы для каждой структуры, мы можем просто указать для нее +   несколько единообразных функций, определяющих, _как_ мы получаем доступ +   к элементам контейнера, вместо того, чтобы описывать внутреннее устройство +   этого контейнера. Сложно? На самом деле не очень. + +    Простейший вид диапазона - Input Range. Для того, чтобы превратить любой +    контейнер в Input Range, достаточно реализовать для него 3 метода: +    - empty - проверяет, пуст ли контейнер +    - front - дает доступ к первому элементу контейнера +    - popFront - удаляет из контейнера первый элемент +*/ +struct Student +{ +    string name; +    int number; +    string toString() { +        return format("%s(%s)", name, number); +    } +} + +struct School +{ +    Student[] students; +} + +struct StudentRange +{ +    Student[] students; + +    this(School school) { +        this.students = school.students; +    } + +    bool empty() { +        return students.length == 0; +    } + +    Student front() { +        return students[0]; +    } + +    void popFront() { +        students = students[1 .. $]; +    } +} + +void main(){ +    auto school = School([ +            Student("Mike", 1), +            Student("John", 2) , +            Student("Dan", 3) +    ]); +    auto range = StudentRange(school); +    writeln(range);                     // [Mike(1), John(2), Dan(3)] +    writeln(school.students.length);    // 3 +    writeln(range.front());             // Mike(1) +    range.popFront(); +    writeln(range.empty());             // false +    writeln(range);                     // [John(2), Dan(3)] +} +/* +   Смысл в том, что нам не так уж важно внутреннее устройство контейнера, если +   у нас есть унифицированные методы доступа к его элементам. +   Кроме Input Range в D есть и другие типы диапазонов, которые требуют +   реализации большего числа методов, зато дают больше контроля. Это большая +   тема и мы не будем в подробностях освещать ее здесь. + +   Диапазоны - это важная часть D, они используются в нем повсеместно. +*/ +``` +## Что дальше? + +- [Официальный сайт](http://dlang.org/) +- [Онлайн-книга](http://ddili.org/ders/d.en/) +- [Официальная вики](http://wiki.dlang.org/)  | 
