Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

снова про языковые конструкции

64K
20 сентября 2011 года
az20110303
29 / / 13.09.2011
решил создать новую тему, так как в предыдущей всё еще идет бурное обсуждение.

В общем, пришел в голову такой изврат:
Возвращаемое значение функции/метода в современных императивных языках программирования всегда одно. Мне же часто в коде требуется оформить определенным образом результат работы функции, а также некую дополнительную информацию, например код ошибки.
Конечно, существует множество "выходов из положения", но на мой взгляд лучший вариант - позволить функциям возвращать несколько значений.

Например:

 
Код:
int i, enum error = remainder(100500, 600); //остаток от деления целого на целое
if (error==DivisionErrors::NoError) {
  printf("result is %d", i);
}else {
  printf("error happened: %d", error);
}
Страницы:
64K
20 сентября 2011 года
az20110303
29 / / 13.09.2011
Тут речь идет об удобстве использования. Еще один более удачный пример:
 
Код:
int red, int green, int blue = getColor();

В частности, если нужна только зеленая составляющая цвета:
 
Код:
, int green, = getColor();

Конечно, можно создать структуру (или класс) Color, но что если эта структура больше никогда не понадобится, кроме использования в качестве результата этой функции?
278
20 сентября 2011 года
Alexander92
1.1K / / 04.08.2008
А чем не устраивают, например, out-параметры C#? (Собственно, в C++ можно реализовать то же самое, просто в C# это заложено на уровне концепций языка.)
87
20 сентября 2011 года
Kogrom
2.7K / / 02.02.2008
Цитата: az20110303
Тут речь идет об удобстве использования. Еще один более удачный пример:
 
Код:
int red, int green, int blue = getColor();

В частности, если нужна только зеленая составляющая цвета:
 
Код:
, int green, = getColor();



Языки с таким синтаксисом есть.

Код:
def get_params():
    return 1, 2, 3

a, b, c = get_params()
print a, b, c

d = get_params()[2]
print d

_, f, _ = get_params()
print f
18K
20 сентября 2011 года
rrrFer
50 / / 08.09.2008
az20110303
Цитата:
но на мой взгляд лучший вариант - позволить функциям возвращать несколько значений.


позволь, мы причем?
по приведенному примеру - используй механизм исключений

Цитата:
но что если эта структура больше никогда не понадобится, кроме использования в качестве результата этой функции?


ничего страшного

Цитата:
В частности, если нужна только зеленая составляющая цвета:
 
Код:
, int green, = getColor();


а если только красная - то:

 
Код:
, int red, = getColor();

?

 
Код:
remainder(100500, 600, &error)

не?
18K
20 сентября 2011 года
rrrFer
50 / / 08.09.2008
а все, понял зачем в примере с цветами запятые )
64K
20 сентября 2011 года
az20110303
29 / / 13.09.2011
C шарпом не сталкивался, и не хочу.
С питоном тоже, но поковыряю его как нибудь
87
20 сентября 2011 года
Kogrom
2.7K / / 02.02.2008
Цитата: az20110303
C шарпом не сталкивался, и не хочу.
С питоном тоже, но поковыряю его как нибудь



На C++ можно воспользоваться ссылками или указателями. Например:

[CODE=с++]void get_color(int *red = 0, int *green = 0, int * blue = 0)
{
if (red) *red = 1;
if (green) *green = 2;
if (blue) *blue = 3;
}


int main () {

int red = 0;
get_color(&red);
cout << red << endl;

int green = 0;
get_color(0, &green);
cout << green << endl;

int blue = 0;
get_color(0, 0, &blue);
cout << blue << endl;
return 0;
}[/CODE]

Но тут есть свои недостатки. Код опаснее и не такой компактный.
Кроме того, можно попробовать использовать перегрузку функции. Но это может запутать пользователя.

4
20 сентября 2011 года
mike
3.7K / / 01.10.2002
 
Код:
($red,$green,$blue)=getColor();
278
20 сентября 2011 года
Alexander92
1.1K / / 04.08.2008
Ну тогда уже и
 
Код:
function getColor() {
  return array($r, $g, $b);
}

list(,$green,) = getColor();
87
20 сентября 2011 года
Kogrom
2.7K / / 02.02.2008
Ну раз такая пьянка, то быдлокод на C++ тоже рулит :)

[CODE=c++]enum {RED, GREEN, BLUE};

vector<int> get_color()
{
vector<int> v(3);
v[RED] = 1;
v[GREEN] = 2;
v[BLUE] = 3;
return v;
}


int main () {

cout << get_color()[RED] << endl;
cout << get_color()[GREEN] << endl;
cout << get_color()[BLUE] << endl;
return 0;
}
[/CODE]
297
20 сентября 2011 года
koodeer
1.2K / / 02.05.2009
Как завещал дедушка Ленин: "Учиться, учиться и учиться!" Топикстартер, похоже, едва знаком с одним языком, вот и считает, что изобрёл нечто новое. Но, как уже показали многие, способы возврата нескольких значений из функции существуют во многих языках.
 
Код:
let getColor = (1,2,3);;

let (r,g,b) = getColor;;
let (_,g,_) = getColor;;

Остаётся лишь пожелать топикстартеру ознакомиться с другими языками и парадигмами.


2Kogrom: да уж, C++ как всегда рулит, и как всегда не туда...
278
20 сентября 2011 года
Alexander92
1.1K / / 04.08.2008
Цитата: Kogrom
Ну раз такая пьянка, то быдлокод на C++ тоже рулит :)

[CODE=c++]enum {RED, GREEN, BLUE};

vector<int> get_color()
{
vector<int> v(3);
v[RED] = 1;
v[GREEN] = 2;
v[BLUE] = 3;
return v;
}


int main () {

cout << get_color()[RED] << endl;
cout << get_color()[GREEN] << endl;
cout << get_color()[BLUE] << endl;
return 0;
}
[/CODE]



Тогда уже лучше через map делать, мне сдается. =)
[CODE=C++]
map<string, int> get_color() {
map<string, int> ret;
ret["red"] = 1;
ret["green"] = 2;
ret["blue"] = 3;
return ret;
}

int main() {
cout << get_color()["green"] << endl;
return 0;
}
[/CODE]

87
20 сентября 2011 года
Kogrom
2.7K / / 02.02.2008
Цитата: Alexander92
Тогда уже лучше через map делать, мне сдается. =)



Да, map возвращать по значению - ещё круче :)
Но я действительно зарулил не туда, так как это почти то, о чём автор сказал сразу, то есть возврат чего-то типа структуры. Что, кстати, тоже не является хорошим тоном.

7
20 сентября 2011 года
@pixo $oft
3.4K / / 20.09.2006
Что плохого в возврате структуры?(НЯП,речь идёт всё же о возвращении указателя на неё)
260
20 сентября 2011 года
Ramon
1.1K / / 16.08.2003
Цитата: @pixo $oft
Что плохого в возврате структуры?(НЯП,речь идёт всё же о возвращении указателя на неё)



Это же примитивно и не инновационно, да и сопли поразвешивать, рассуждая о "великом", не дает.

87
20 сентября 2011 года
Kogrom
2.7K / / 02.02.2008
Цитата: @pixo $oft
Что плохого в возврате структуры?(НЯП,речь идёт всё же о возвращении указателя на неё)



Я говорю про передачу по значению. Тут у нас будет создание дополнительных объектов и копирование (которое может быть вообще запрещено для некоторых классов).

Передача по значению - это нормально при работе с примитивными данными, но структуры или контейнеры обычно передают по ссылке, указателю (или используют интеллектуальные указатели).

Возвращение обычного указателя (который указывает на объект, созданный в куче) для C++ тоже не самая лучшая идея. Тут придется не забыть удалить объект из кучи.

18K
20 сентября 2011 года
rrrFer
50 / / 08.09.2008
 
Код:
get_color( [ rED | [ gREEN | bLUE ] ] ).

ну или
 
Код:
get_color( [ 1 | [ 2 | 3 ] ] ).


В первом случае возвращаем список строк, во втором - чисел
341
20 сентября 2011 года
Der Meister
874 / / 21.12.2007
Цитата: az20110303
Конечно, существует множество "выходов из положения", но на мой взгляд лучший вариант - позволить функциям возвращать несколько значений.

Попробуйте Forth.
В примерах на Python и F# также возвращается одно значение - кортеж.

Цитата: Alexander92
Тогда уже лучше через map делать, мне сдается. =)

На мой взгляд, гораздо лучше возвращать подписанный XML-документ (вместе со схемой и сертификатом, чтоб наверняка).

297
20 сентября 2011 года
koodeer
1.2K / / 02.05.2009
Цитата: @pixo $oft
Что плохого в возврате структуры?


Плохо то, что эту структуру предварительно приходится объявить. Даже если она нужна всего лишь для одного-единственного раза.

87
20 сентября 2011 года
Kogrom
2.7K / / 02.02.2008
Цитата: Kogrom
Я говорю про передачу по значению. Тут у нас будет создание дополнительных объектов и копирование (которое может быть вообще запрещено для некоторых классов).



Хотя, возможно при возврате значения не всегда будет копирование и создание нового объекта. Вот этот код меня удивил (наверное сказалось то, что пол года на C++ не программировал):

[CODE=C++]struct MyClass
{
MyClass(){cout << "MyClass" << endl;}
~MyClass(){cout << "~MyClass" << endl;}

MyClass(const MyClass&)
{
cout << "copy constructor" << endl;
}
MyClass& operator=(const MyClass&)
{
cout << "operator =" << endl;
return *this;
}
};

MyClass func()
{
MyClass t;
return t;
}


int main () {
MyClass t = func();
return 0;
}
[/CODE]

выводится только один конструктор и деструктор...

Цитата: Der Meister
В примерах на Python и F# также возвращается одно значение - кортеж.



Какие в этом есть недостатки?

Цитата: Der Meister
На мой взгляд, гораздо лучше возвращать подписанный XML-документ (вместе со схемой и сертификатом, чтоб наверняка).



Думаю, по хорошему, без базы данных не обойтись.

87
20 сентября 2011 года
Kogrom
2.7K / / 02.02.2008
Цитата: Kogrom
выводится только один конструктор и деструктор...



это g++ (4.4.1) так выдает. Кодепадовский же компилятор выдаёт другое:
http://codepad.org/IDQMT906
Чудеса.

Добавлено позже. У них тоже g++, но флаги другие. Видать, у них без оптимизации...

341
20 сентября 2011 года
Der Meister
874 / / 21.12.2007
Цитата: Kogrom
Хотя, возможно при возврате значения не всегда будет копирование и создание нового объекта. Вот этот код меня удивил (наверное сказалось то, что пол года на C++ не программировал): ... выводится только один конструктор и деструктор...

Это оптимизация возврата по значению. Она не входит в стандарт и может произойти, а может и нет - на усмотрение производителя компилятора. В оригинале она происходит при возврате анонимных объектов, а суть её более-менее раскрыта у Мейерса. Полагаться на неё всё равно нельзя в том смысле, что про конструктор копирования надо помнить вне зависимости от компилятора.

Цитата: Kogrom
Какие в этом есть недостатки?

Никаких, но ведь автору нужно именно несколько? А в форте в натуре можно. Только там функций нет - в этом и состоит подвох. Ну вообще да, бугагашенька, нарна, не очевидна... просто даже в математике у функции одно значение. :)

278
20 сентября 2011 года
Alexander92
1.1K / / 04.08.2008
Цитата: Der Meister
просто даже в математике у функции одно значение. :)


А давайте перейдем в комплексную плоскость, там хоть 35 значений у функции не проблема. :)

18K
20 сентября 2011 года
rrrFer
50 / / 08.09.2008
Der Meister
Цитата:
в математике у функции одно значение


функция - окружность, например.

Цитата:
Никаких, но ведь автору нужно именно несколько?


если прочитать все - то несколько полей структуры его устраивает, но структуру он описывать не хочет лишний раз.

341
20 сентября 2011 года
Der Meister
874 / / 21.12.2007
Цитата: Alexander92
А давайте перейдем в комплексную плоскость, там хоть 35 значений у функции не проблема. :)


Цитата: rrrFer
функция - окружность, например.

Наверное, это всё-таки будет одно комплексное значение?

278
20 сентября 2011 года
Alexander92
1.1K / / 04.08.2008
Если бы. :) Плоскость режется на бесконечное количество римановых поверхностей, на каждой поверхности - свое значение. :) Например - логарифм:
Ln(z) = ln(|z|) + i*arg(z) + 2*Pi*k*i

k - произвольное целое число.
18K
20 сентября 2011 года
rrrFer
50 / / 08.09.2008
Цитата:
Наверное, это всё-таки будет одно комплексное значение?


я не предлагал переходить на комплексную плоскость :)
x^2 + y^2 = 4
x = +(-) * (4-y^2)^(1/2)
математика пятый класс. При y = 0, имеется 2 решения уравнения +2 и -2
Ну и если мы опишем соответствующую функцию, принимающую один аргумент - то должны будем получить в результате массив из результатов, не?

240
20 сентября 2011 года
aks
2.5K / / 14.07.2006
Цитата: Der Meister
Это оптимизация возврата по значению. Она не входит в стандарт и может произойти, а может и нет - на усмотрение производителя компилятора.


В стандарт как раз входит (12.8/15), иначе компиляторы бы не имели права реализовывать такое. Только входит не в качестве обязательного требования, а в качестве рекомендации.

Цитата: Der Meister

В оригинале она происходит при возврате анонимных объектов


Не ананимных тоже можно. Это уже Named RVO. И то и другое умеют почти все современные компиляторы, но фича и правда не обязательная к исполнению. )

240
20 сентября 2011 года
aks
2.5K / / 14.07.2006
rrrFer, определитесь уж - про решение уравнения или функции говорите. =)
2.1K
20 сентября 2011 года
Norgat
452 / / 12.08.2009
Цитата: koodeer
Плохо то, что эту структуру предварительно приходится объявить. Даже если она нужна всего лишь для одного-единственного раза.



В .Net 4.0 для этого есть Tuple<> (аля кортеж). Хотя избыточностью объявлений страдают все статически типизированные ЯП, в динамических попроще это.

п.с. имхо, для F# более корректным будет вариант через размеченное объединение:

Код:
open System

type MyResult<'r, 'e> =
    | MSome of 'r
    | MErr of 'e


let my_fun x =
    if x = 0 then
        MSome x
    else
        MErr "err"

let my_call x =
    match my_fun x with
        | MSome z -> printfn "%A" z
        | MErr z -> printfn "Error: %A" z


[<EntryPoint>]
let main _ =
    my_call 1
    my_call 0
    Console.ReadLine()
    0
341
20 сентября 2011 года
Der Meister
874 / / 21.12.2007
Цитата: rrrFer
Ну и если мы опишем соответствующую функцию...

Опишите, посмотрим.

Цитата: Alexander92
Если бы. :) Плоскость режется на бесконечное количество римановых поверхностей, на каждой поверхности - свое значение...

И? Здесь мы просто получили значение из другого множества - значение на множестве, хрен с ним, римановых, плоскостей - не?
http://ru.wikipedia.org/wiki/Функция_(математика)

297
20 сентября 2011 года
koodeer
1.2K / / 02.05.2009
Цитата: Norgat
В .Net 4.0 для этого есть Tuple<> (аля кортеж).


Да, но в таких языках, как C# и VB.NET нет паттерн-матчинга, отчего применение кортежей становится неудобно. А частичное применение - ваще вещь!


Цитата: Norgat
Хотя избыточностью объявлений страдают все статически типизированные ЯП


В правильных языках (да-да, я о нём ;)) есть мощный вывод типов. Благодаря ему типы в большинстве случаев можно не указывать, и код становится практически таким же коротким, как в динамических языках.


Цитата: Norgat
имхо, для F# более корректным будет вариант через размеченное объединение


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

297
20 сентября 2011 года
koodeer
1.2K / / 02.05.2009
В который раз убеждаюсь, что именно нубские вопросы собирают обширную аудиторию, желающих блеснуть знаниями и помериться длиной, хмм, компилятора.

Хочу отметить, что тема навела меня на полезные размышления. Посему предлагаю наградить чем-нибудь ОПа, и забанить - во избежание раздувания дальнейшего холивара :).
341
20 сентября 2011 года
Der Meister
874 / / 21.12.2007
Цитата: koodeer
... предлагаю наградить чем-нибудь ОПа, и забанить - во избежание раздувания дальнейшего холивара :).

Заодно простить Оксотника (никто не помнит Дафифу, не? :)).

2.1K
20 сентября 2011 года
Norgat
452 / / 12.08.2009
Цитата:
В правильных языках (да-да, я о нём ) есть мощный вывод типов. Благодаря ему типы в большинстве случаев можно не указывать, и код становится практически таким же коротким, как в динамических языках.



Я всё больше склоняюсь к мнению, что вывод типов это не более чем игрушки, кроме случаев типа LINQ, где юзаются автоматически сгенерированные анонимные типы.


Цитата:
Да, но в таких языках, как C# и VB.NET нет паттерн-матчинга, отчего применение кортежей становится неудобно. А частичное применение - ваще вещь!



Реальность показывает, что паттерн-матчинг в реальности нужен редко(а вернее он удобен для небольшого класса задач). Т.к. расширять код основанный на операторе match-with тот ещё геморрой (поменял код объединения - скажи привет ручному переписыванию всех блоков match-with).

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



Есть http://msdn.microsoft.com/ru-ru/library/ee353439.aspx и пара вариантов(аля Tuple в C#). Но я не люблю их юзать просто (предпочитаю потратить 2 мин на ручное описание структуры объединения, мне так наглядней).

278
20 сентября 2011 года
Alexander92
1.1K / / 04.08.2008
Цитата: Der Meister
И? Здесь мы просто получили значение из другого множества - значение на множестве, хрен с ним, римановых, плоскостей - не?
http://ru.wikipedia.org/wiki/Функция_(математика)


Что вы имеете в виду? Функция сама по себе по определению становится многозначной, я об этом.

297
20 сентября 2011 года
koodeer
1.2K / / 02.05.2009
Цитата: Norgat
Я всё больше склоняюсь к мнению, что вывод типов это не более чем игрушки, кроме случаев типа LINQ


LINQ - это кусочек функциональщины в императивном мире привычного дотнета. В полностью функциональном окружении вывод типов логичен и более чем удобен.


Цитата: Norgat
Реальность показывает, что паттерн-матчинг в реальности нужен редко(а вернее он удобен для небольшого класса задач). Т.к. расширять код основанный на операторе match-with тот ещё геморрой (поменял код объединения - скажи привет ручному переписыванию всех блоков match-with).


Ну, не знаю. Просто ты не умеешь его готовить. if'ы и switch'и точно так же придётся переписывать.

 
Код:
let getColor = (1,2,3);;

let (r,g,b) = getColor;;

Что тут неудобного? А ведь это именно паттерн-матчинг, когда возвращаемый кортеж разбирается и присваивается трём именам.


Цитата: Norgat
предпочитаю потратить 2 мин на ручное описание структуры объединения, мне так наглядней


Да я не спорю, сам за наглядность.

2.1K
20 сентября 2011 года
Norgat
452 / / 12.08.2009
Цитата:
Ну, не знаю. Просто ты не умеешь его готовить. if'ы и switch'и точно так же придётся переписывать.



Я говорю про большие куски кода, когда удобнее применить ООП, чем извращаться с паттерн матчингом. Локальный паттерн матчинг удобен да, но когда протягиваешь сложное объединение(5+ вариантов или даже несколько таких объединений) через несколько функций эта проблема вылезает.

Просто представь что будет если у тебя 3-4 объединения по 5+ вариантов и больше чем 2-3 match-with'а, которые эти объединения разбивают. Естественно, как вариант, можно собрать разборку в 1 функцию и сделать там частичное применение... но решение особо проще не станет(если вообще упростится). Такое уже надо расписывать через ООП. А небольшие match-with легко пишутся и через if-else\switch-case\if-ifelse-else.

Про локальный паттерн матчинг я ничего не говорю - вещь отличная. Но это лишь небольшой сахар, который существенного влияния на код не имеет (сделать то же через структуру элементарно).


Цитата:
LINQ - это кусочек функциональщины в императивном мире привычного дотнета. В полностью функциональном окружении вывод типов логичен и более чем удобен.



Я думаю, что в чисто функциональном окружении он (вывод типов) банально необходим. Иначе мы бы сошли с ума прописывая типы (причём львиную долю времени этим и занимались бы, т.к. даже сейчас, когда есть вывод типов, иногда приходится в ручную прописывать типы).

Опять же по LINQ (не о сахарном синтаксисе from-in) - вывод типов там банально необходим, т.к. без него мы бы просто захлебнулись в объявлениях типов и весь профит от простоты был бы затёрт объявлениями типов.

341
20 сентября 2011 года
Der Meister
874 / / 21.12.2007
Цитата: Norgat
Я всё больше склоняюсь к мнению, что вывод типов это не более чем игрушки, кроме случаев типа LINQ, где юзаются автоматически сгенерированные анонимные типы.

Тем не менее, "баден-баден" тоже излишен: тип выражения всё равно выводится компиляторами большинства статически типизируемых языков хотя бы для проверки типов, а читаемость не страдает (ну разве что иногда полезно иметь базовый тип, но не для читаемости даже, а для мелкого рефакторинга), а с какой-нибудь STL без вывода типов вообще никуда (щас в одиннадцатом C++ можно заодно выводить не менее шаблонные типы возвращаемых значений). Иное дело, что достаточно вывода при инициализации и ни к чему выводить тип из использования, если бы не квазицитирование в "тех самых".

341
20 сентября 2011 года
Der Meister
874 / / 21.12.2007
Простите, не заметил.
Цитата: Alexander92
Что вы имеете в виду? Функция сама по себе по определению становится многозначной, я об этом.

Блин, ну это одно значение. Просто "тип" у него такой :)
Объяснюсь: изначально я озвучил понятие кортежа в ироничной форме - оно не упоминалось явно, а просто "несколько значений" вон в Форте.
Приятно, что всплыла порция зачётного матана :)

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог