Объявление переменных и констант — различия между версиями

Материал из Deeptown Manual
Перейти к: навигация, поиск
(minor updates)
 
Строка 1: Строка 1:
G6U30h , [url=http://lypqlevvbgle.com/]lypqlevvbgle[/url], [link=http://meovscicmutg.com/]meovscicmutg[/link], http://ghdormjhxgjd.com/
+
Про объявление как переменных так и констант уже достаточно много говорилось в предыдущих главах этой книги. Вероятно, Читатель уже хорошо себе представляет что такое [[переменные]], чем они отличаются от [[Константы|констант]] и как следует их [[Переменные#Типизация при инициализации|инициализировать]]. Читатель уже должен представлять себе, что такое [[Переменные#Понятие переменной, тип переменной|тип]] переменной или константы, и чем статически типированные переменные отличаются от нетипированных, [[Переменные#Нетипированные (динамические) переменные|динамических переменных]]. В этой главе мы не будем уделять много внимания философским вопросам, касающимся переменных и констант, а опишем только сами синтаксические конструкции объявления.
  
== Authors Nominate Top Books of All Time ==
+
Вот несколько примеров объявления как одиночной переменной, так и группы переменных в рамках одного оператора:
  
In 2002, the Norwegian Book Clubs gathered 100 authors from 54 countries and asked each one to list the 10 best works of fiction of all time. The authors responded and this list was created. The titles are arranged alphabetically by author name, so no one book stands above any other. The following list is the groups selection of the worlds 100 best books.How many have you read?
+
<source lang="kpp" line="1">
 +
var x;
 +
var x = "hello";
 +
var x, y;
 +
var x, y = 0;
 +
var int x, y;
 +
var int x, real y;
 +
var int x = "1", y = 1.5;
 +
</source>
  
[[http://goodvillenews.com/Authors-Nominate-Top-Books-of-All-Time-kRj65H.html Authors Nominate Top Books of All Time]]
+
При объявлении переменных важно понимать, что при явном указании типа переменной, он сопостовляется только идентификатору идущему сразу после него. Таким образом, строка 5 объявляет переменную ''x'' типа <tt>[[Стандартные типы данных#Целые числа|int]]</tt>, в то время как переменная ''y'' будет иметь [[Переменные#Нетипированные (динамические) переменные|динамический тип]].
  
[[http://goodvillenews.com/wk.html goodville news]]
+
То же самое относится и к инициализаторам, которые ставятся в соответствие только той переменной, которая стоит слева от оператора "=". К примеру, выражение в строке 4 будет инициализировать только переменную ''y'', в то время как переменная ''x'' не будет иметь инициализатора; то есть для переменной ''x'' объявление эквивалентно тому что записано в строке 1.
  
== Teen Told to Clean His Room Finds Winning Lotto Ticket ==
+
Обратите внимание на строку 7: переменная ''x'' имеет инициализатор типа <tt>string</tt>, но ввиду того что тип переменной указан явным образом, переменная будет иметь тип <tt>int</tt>. При этом, тип инициализатора будет ''приведен'' к типу переменной. Если же типы переменной и инициализатора ''неприводимы'', — будет выдано сообщение об ошибке.
  
A teenager from Midlothian has cleaned up on the National Lottery after finally cleaning up his messy bedroom. Ryan Kitchin scooped more than 50,000 after finding a winning lottery ticket in the room that his mother had been asking him to clean for weeks.
+
Приведем еще раз те же самые примеры, но оформим их в виде таблицы, дополнив сведениями о типах переменых:
  
[[http://goodvillenews.com/Teen-Told-to-Clean-His-Room-Finds-Winning-Lotto-Ticket-AfWho8.html Teen Told to Clean His Room Finds Winning Lotto Ticket]]
+
<source lang="kpp">
 +
//Строка объявления        Тип x    Тип y      Инициализатор x  Инициализатор y
  
[[http://goodvillenews.com/wk.html goodville news]]
+
var x;                    динамика 
 +
var x = "hello";            string                  "hello" 
 +
var x, y;                  динамика  динамика
 +
var x, y = 0;              динамика    int                              0
 +
var int x, y;                int    динамика
 +
var int x, real y;          int      real
 +
var int x = "1", y = 1.5;    int      real        "1" as int        1.5
 +
</source>
  
== Journey to the End of the Earth ==
+
'''Примечание:''' как видно из таблицы, существует различие между инициализацией переменной и присваиванием ей значения, которое заключается в том, что в зависимости от условий, тип переменной может оказаться либо динамическим, либо фиксированным статическим; внешне же, выражения вызывающие такое поведение, могут выглядеть очень похоже. Рассмотрим следующий пример:
  
I realized quickly, after just having traveled to various villages in rural India, that distance is relative. Hailing from a city like San Francisco, going even a few hours outside of town is far but twelve hours outside of a major city? I half expected to run into another country.
+
<source lang="kpp">
 +
var x = 0;
 +
var y;
 +
y = 0;
 +
</source>
  
[[http://goodvillenews.com/Journey-to-the-End-of-the-Earth-tbNql3.html Journey to the End of the Earth]]
+
В результате выполнения этого кода и переменная ''x'', и переменная ''y'' будут иметь значение равное 0. Более того, типы переменных в этот момент будут совпадать и равны <tt>int</tt>. Однако, переменная ''x'' будет иметь статический тип, в то время как переменная ''y'' — [[Переменные#Нетипированные (динамические) переменные|динамический]]. Если же мы попытаемся присвоить этим переменным другие значения, заведомо неприводимого типа, то произойдет следующее:
  
[[http://goodvillenews.com/wk.html goodville news]]
+
<source lang="kpp">
 +
x = { |x| return x + 1; };
 +
y = [1, 2, 3];
 +
</source>
  
== Rats Walking Again After Spinal Cord Injury ==
+
В случае переменной ''x'' будет сгенерирована ошибка еще на этапе компиляции, поскольку тип переменной был назначен статически при инициализации и не может быть изменен в ходе работы программы. В случае переменной ''y'' никакой ошибки не произойдет, поскольку это динамическая переменная. В ходе присваивания, она просто изменит свой тип на <tt>[[Стандартные типы данных#Массивы и списки|array]]</tt> и будет представлять собой уже массив из трех чисел.
  
Scientists in Switzerland have restored full movement to rats paralyzed by spinal cord injuries in a study that spurs hope that the techniques may hold promise for someday treating people with similar injuries.
+
----
  
[[http://goodvillenews.com/Rats-Walking-Again-After-Spinal-Cord-Injury-nBLFSB.html Rats Walking Again After Spinal Cord Injury]]
 
  
[[http://goodvillenews.com/wk.html goodville news]]
+
Объявления констант вместо <tt>'''var'''</tt>, начинаются с ключевого слова <tt>'''const'''</tt> и синтаксически ничем не отличаются от объявления переменных, за исключением того, что константы обязательно должны инициализироваться:
  
== How To Speak More Wisely ==
+
<source lang="kpp">
 +
const x;                    //неверно. требуется инициализатор
 +
const x = "hello";          //верно
 +
const x, y = 0;            //неверно. константа x не инициализируется
 +
const int x = "1", y = 1.5; //верно
 +
</source>
  
It had been three weeks since my throat started to feel sore, and it wasnt getting better. The pain was most acute when I spoke. So I decided to spend a few days speaking as little as possible. Every time I had the urge to say something, I paused for a moment to question whether it was worth irritating my throat.
+
== Конструкция группового объявления ==
  
[[http://goodvillenews.com/How-To-Speak-More-Wisely-86itqo.html How To Speak More Wisely]]
+
Существует также специальная конструкция, позволяющая объявить серию переменных и одновременно присвоить им значения из массива. Выглядит это следующим образом:
  
[[http://goodvillenews.com/wk.html goodville news]]
+
<source lang="kpp">
 +
var (x, y, z) = [1, '2', true];
 +
</source>
 +
 
 +
Будут объявлены три динамических переменных, инициализованные соответствующими элементами из массива. Размер массива должен быть не меньше количества объявляемых переменных. Если это не так, то переменные, которым не хватило элементов массива, не будут инициализированы.
 +
 
 +
Использование группового объявления особенно удобно при работе с функциями, возвращающими массив в качестве значения. Допустим, у нас есть операция, по логике работы возвращающая набор объектов. Такой результат можно описать в виде класса, полями которого будут значиться возвращаемые результаты. Тогда функция создает объект результат, устанавливает ему соответствующие значения свойств и возвращает его. В коде вызывающем функцию производится обратная операция, а именно заводится переменная под объект-результат и далее используется в коде обработки. В таком случае класс объекта-результата работает как структуры в С++.
 +
 
 +
Пример использования:
 +
<source lang="kpp">
 +
class QueryResult {
 +
    var FName, FAddress, FPhone;
 +
public:
 +
    property string name read FName;
 +
    property string address read FAddresss;
 +
    property string phoneNumber read FPhone;
 +
    operator new(_name, _addr, _phone) {
 +
        (FName, FAddress, FPhone) = [_name, _addr, _phone];
 +
    }
 +
}
 +
 
 +
function SearchByName(const string Name) {
 +
    // ... код обращения к БД ...
 +
    // предположим, были возвращены следующие данные:
 +
    var result = new QueryResult( 'Vassily Pupkin',
 +
        'Бобруйская область, село Урюпинское, д. 13', '223-322');
 +
    return result;
 +
}
 +
 
 +
function main() {
 +
    // ...
 +
    var result = SearchByName('%Pupkin%'); // делаем запрос
 +
    // работаем с результатами, используя result.name, result.address и result.phoneNumber
 +
    puts("Телефон Васи Пупкина: #{result.phoneNumber}");
 +
}
 +
</source>
 +
 
 +
В принципе подобный код вполне имеет право на существование, однако далеко не всегда удобно и эффективно городить огород из классов, только ради удобной передачи данных. Особенно если данный класс используется в единственном месте программы.
 +
 
 +
С использованием конструкции группового объявления, задача передачи и разбора параметров становится намного проще:
 +
<source lang="kpp">
 +
function SearchByName(const string Name) {
 +
    // ... код обращения к БД ...
 +
    // ... 'Vassily Pupkin', 'Бобруйская область, село Урюпинское, д. 13', '223-322'
 +
    return [ name, addr, phone ];
 +
}
 +
 
 +
function main() {
 +
    // ...
 +
    var (name, addr, phone) = SearchByName('%Pupkin%'); // делаем запрос   
 +
    puts("Телефон Васи Пупкина: #{phone}");
 +
}
 +
</source>
 +
 
 +
Функция, которой необходимо вернуть несколько значений оборачивает их в массив прямо по месту и возвращает одним объектом. В точке вызова производится обратная операция по вытаскиванию значений из массива и размещению в отдельных переменных.
 +
 
 +
 
 +
А вот простой способ разделить входную строку на подстроки и назначить каждой из них свою переменную:
 +
<source lang="kpp">
 +
var record = System.shellExecute("head -1 /etc/passwd"); // строка вида 'root:x:0:0:root:/root:/bin/bash'
 +
var (account, password, UID, GID, info, homedir, shell) = record.split(':');
 +
puts("Пользователь #{account} с номером #{UID} пользуется оболочкой #{shell} и хранит свои данные в #{homedir}");
 +
</source>
 +
 
 +
Метод [[string#split]] возвращает массив подстрок, поэтому зная результат выполнения метода мы можем произвести нашу операцию объявления переменных. Это намного удобнее, чем обращаться к элементам по индексам, тем самым избегая ошибок и опять же делая код более читаемым.
 +
 
 +
'''Примечание: ''' Существует также похожий синтаксис для оператора присваивания. Смысл точно такой же, как и у оператора объявления, только используются созданные ранее переменные. То есть, объявления переменных не происходит:
 +
 
 +
<source lang="kpp">
 +
var x = 1, y = 2; // объявление переменных
 +
(x, y) = [3, 4];  // групповое присваивание
 +
(x, y) = [y, x];  // простой способ обменять значения местами
 +
</source>
 +
 
 +
== Смотри также ==

Текущая версия на 14:49, 13 июля 2013

Про объявление как переменных так и констант уже достаточно много говорилось в предыдущих главах этой книги. Вероятно, Читатель уже хорошо себе представляет что такое переменные, чем они отличаются от констант и как следует их инициализировать. Читатель уже должен представлять себе, что такое тип переменной или константы, и чем статически типированные переменные отличаются от нетипированных, динамических переменных. В этой главе мы не будем уделять много внимания философским вопросам, касающимся переменных и констант, а опишем только сами синтаксические конструкции объявления.

Вот несколько примеров объявления как одиночной переменной, так и группы переменных в рамках одного оператора:

<source lang="kpp" line="1"> var x; var x = "hello"; var x, y; var x, y = 0; var int x, y; var int x, real y; var int x = "1", y = 1.5; </source>

При объявлении переменных важно понимать, что при явном указании типа переменной, он сопостовляется только идентификатору идущему сразу после него. Таким образом, строка 5 объявляет переменную x типа int, в то время как переменная y будет иметь динамический тип.

То же самое относится и к инициализаторам, которые ставятся в соответствие только той переменной, которая стоит слева от оператора "=". К примеру, выражение в строке 4 будет инициализировать только переменную y, в то время как переменная x не будет иметь инициализатора; то есть для переменной x объявление эквивалентно тому что записано в строке 1.

Обратите внимание на строку 7: переменная x имеет инициализатор типа string, но ввиду того что тип переменной указан явным образом, переменная будет иметь тип int. При этом, тип инициализатора будет приведен к типу переменной. Если же типы переменной и инициализатора неприводимы, — будет выдано сообщение об ошибке.

Приведем еще раз те же самые примеры, но оформим их в виде таблицы, дополнив сведениями о типах переменых:

<source lang="kpp"> //Строка объявления Тип x Тип y Инициализатор x Инициализатор y

var x; динамика var x = "hello"; string "hello" var x, y; динамика динамика var x, y = 0; динамика int 0 var int x, y; int динамика var int x, real y; int real var int x = "1", y = 1.5; int real "1" as int 1.5 </source>

Примечание: как видно из таблицы, существует различие между инициализацией переменной и присваиванием ей значения, которое заключается в том, что в зависимости от условий, тип переменной может оказаться либо динамическим, либо фиксированным статическим; внешне же, выражения вызывающие такое поведение, могут выглядеть очень похоже. Рассмотрим следующий пример:

<source lang="kpp"> var x = 0; var y; y = 0; </source>

В результате выполнения этого кода и переменная x, и переменная y будут иметь значение равное 0. Более того, типы переменных в этот момент будут совпадать и равны int. Однако, переменная x будет иметь статический тип, в то время как переменная yдинамический. Если же мы попытаемся присвоить этим переменным другие значения, заведомо неприводимого типа, то произойдет следующее:

<source lang="kpp"> x = { |x| return x + 1; }; y = [1, 2, 3]; </source>

В случае переменной x будет сгенерирована ошибка еще на этапе компиляции, поскольку тип переменной был назначен статически при инициализации и не может быть изменен в ходе работы программы. В случае переменной y никакой ошибки не произойдет, поскольку это динамическая переменная. В ходе присваивания, она просто изменит свой тип на array и будет представлять собой уже массив из трех чисел.



Объявления констант вместо var, начинаются с ключевого слова const и синтаксически ничем не отличаются от объявления переменных, за исключением того, что константы обязательно должны инициализироваться:

<source lang="kpp"> const x; //неверно. требуется инициализатор const x = "hello"; //верно const x, y = 0; //неверно. константа x не инициализируется const int x = "1", y = 1.5; //верно </source>

[править] Конструкция группового объявления

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

<source lang="kpp"> var (x, y, z) = [1, '2', true]; </source>

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

Использование группового объявления особенно удобно при работе с функциями, возвращающими массив в качестве значения. Допустим, у нас есть операция, по логике работы возвращающая набор объектов. Такой результат можно описать в виде класса, полями которого будут значиться возвращаемые результаты. Тогда функция создает объект результат, устанавливает ему соответствующие значения свойств и возвращает его. В коде вызывающем функцию производится обратная операция, а именно заводится переменная под объект-результат и далее используется в коде обработки. В таком случае класс объекта-результата работает как структуры в С++.

Пример использования: <source lang="kpp"> class QueryResult {

   var FName, FAddress, FPhone;

public:

   property string name read FName;
   property string address read FAddresss;
   property string phoneNumber read FPhone;
   operator new(_name, _addr, _phone) { 
       (FName, FAddress, FPhone) = [_name, _addr, _phone]; 
   }

}

function SearchByName(const string Name) {

   // ... код обращения к БД ...
   // предположим, были возвращены следующие данные:
   var result = new QueryResult( 'Vassily Pupkin', 
       'Бобруйская область, село Урюпинское, д. 13', '223-322');
   return result; 

}

function main() {

   // ...
   var result = SearchByName('%Pupkin%'); // делаем запрос
   // работаем с результатами, используя result.name, result.address и result.phoneNumber
   puts("Телефон Васи Пупкина: #{result.phoneNumber}");

} </source>

В принципе подобный код вполне имеет право на существование, однако далеко не всегда удобно и эффективно городить огород из классов, только ради удобной передачи данных. Особенно если данный класс используется в единственном месте программы.

С использованием конструкции группового объявления, задача передачи и разбора параметров становится намного проще: <source lang="kpp"> function SearchByName(const string Name) {

   // ... код обращения к БД ...
   // ... 'Vassily Pupkin', 'Бобруйская область, село Урюпинское, д. 13', '223-322'
   return [ name, addr, phone ]; 

}

function main() {

   // ...
   var (name, addr, phone) = SearchByName('%Pupkin%'); // делаем запрос    
   puts("Телефон Васи Пупкина: #{phone}");

} </source>

Функция, которой необходимо вернуть несколько значений оборачивает их в массив прямо по месту и возвращает одним объектом. В точке вызова производится обратная операция по вытаскиванию значений из массива и размещению в отдельных переменных.


А вот простой способ разделить входную строку на подстроки и назначить каждой из них свою переменную: <source lang="kpp"> var record = System.shellExecute("head -1 /etc/passwd"); // строка вида 'root:x:0:0:root:/root:/bin/bash' var (account, password, UID, GID, info, homedir, shell) = record.split(':'); puts("Пользователь #{account} с номером #{UID} пользуется оболочкой #{shell} и хранит свои данные в #{homedir}"); </source>

Метод string#split возвращает массив подстрок, поэтому зная результат выполнения метода мы можем произвести нашу операцию объявления переменных. Это намного удобнее, чем обращаться к элементам по индексам, тем самым избегая ошибок и опять же делая код более читаемым.

Примечание: Существует также похожий синтаксис для оператора присваивания. Смысл точно такой же, как и у оператора объявления, только используются созданные ранее переменные. То есть, объявления переменных не происходит:

<source lang="kpp"> var x = 1, y = 2; // объявление переменных (x, y) = [3, 4]; // групповое присваивание (x, y) = [y, x]; // простой способ обменять значения местами </source>

[править] Смотри также

Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
информация
документация
Инструменты