Search
Write a publication
Pull to refresh
0
0
Матвей Жданович @shamaniac

User

Send message
int f(int var, int other_var);

f(i, i++);
Насколько я понимаю сущность замыканий, они хранят переменные которые видны в блоке где объявляется лямбда функция. Переменные объявленные в лямбда функции будут переинициализированны. А переменные которые объявлены в том же блоке что и лямбда функция будут храниться.
Может я не прав, но тогда не понятна зачем эта бодяга с хранением по значению или ссылке.
Прошу прощения на самом деле я хотел написать

tr1::function<int(void)> f() {....}

Если вас волнует потеря памяти (я понимаю при работе с c++ это уже инстинкт =) то можно написать что-то вроде.
typedef tr1::function<int(void)> F;
pair<F, F> f() {
shared_ptrptr(new int(0));
return make_pair([=ptr](){ return (*ptr)++;}, [=ptr](){ return (*ptr)--;});
}
Понятно что такое решение ни полраза не потокобезопасно. Но с другой стороны мы получили пару функций связанных одной переменной без необходимости хранить эту переменную где-то еще.

У нас наблюдается терменологическая путаница. Есть лямбда функции. Они в данном контексте не более чем функции без имени. Так сказать «syntactic sugar». Но часто вместе с лямбда функциями используются замыкания. Замыкания как я представляю нужны для того чтобы сохранить часть переменных для последующего использования внутри лямбда функции.

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

например
void f(vector* v) {
hash_setbig_hash_set;
// fill big_hash_set
stable_partition(v->begin(), v->end(), [&big_hash_set](int i) { return big_hash_set.count(i); }

}

Если бы мне пришлось разрабатывать замыкания в c++, то я бы, скорее всего, остановился на том, чтобы все хранить по значению. Те кого это не устраивает могли бы передавать все через указатели (умные и не очень). В таком случае мой пример выглядел бы как

void f(vector* v) {
hash_setbig_hash_set;
// fill big_hash_set
hash_set* big_hash_set_ptr = &big_hash_set;
stable_partition(v->begin(), v->end(), (int i) { return big_hash_set_ptr->count(i); }

}

С другой стороны та реализация которую предлагают в стандарт мне тоже нравится.
Что-то у нас не выходит осмысленного обсуждения. Я привожу пример который хочется записать одной строчкой а вы мне объясняете что я ничего не понимаю и с указателями так работать нельзя. То ли у меня не получается выражать свои мысли то ли у вас их понимать а может и то и другое. Я думаю стоит свернуть дискуссию и признать что вы во всем правы =).
void f() {
int* ptr = new int(0);
return [=](){return (*ptr)++;};
}

по мне так все нормально с доступом к перемнной на стеке в текущем блоке и передавать ее надо по значению. В другом месте надо по ссылке передать. Так что не все понятно.
Хм компилятор который не заинлайнит container.end() в данном случае это что-то страшное =).
И да я рад возможности писать for_each с лямбдами, но опять же есть достаточно простые пути без него обойтись (даже на странном компиляторе =).
В коментариях много пишут про корявый синтаксис. Как по мне это достаточно удачная попытка вставить замыкания в язык без сборщика мусора. Компилятор мало знает про планы программиста о жизни переменных и о том считает ли он их «тяжелыми» или нет. Поэтому надо же как то указать что передается по значению а что по ссылке.

Насчет полезности: кроме очевидных примеров с stl функциями которые требуют функтор можно найти еще кучу применений. Например кода есть куски кода которые очень похожи, но если их вынести в отдельную функцию то надо передавать 28 переменных. В таком случае можно объявить лямбда функцию и вызывать ее прямо на месте.
Те же qt сигнали реализованные на tr1::function + лямбда функции были бы гораздо удобнее.

Вобщем по-моему замечательное дополнение к языку
Понятно что не только сортирую. Просто внятной заменой for_each и компании является обычный for. Что в конкретном случае удобнее зависит от многих факторов, но замена одного на другое обычно не принесет такой кучи проблем как написание своей реализации qsort.
ладно с for_each. То что можно в sort или stable_partition на месте написать что надо делать вот это будет замечательно.
Может кому поможет избежать потери времени:
emacs lisp не поддерживает оптимизацию хвостовой рекурсии. Т.е если писать работу со списками в функциональном стиле то скрипт будет вываливаться с чем-то вроде maximum recursion depth…
Я знаю человека который отказался от iphone во многом из-за кривой поддержки mms. В Швейцарии есть удобная услуга покупки билета прямо в поезде. После покупки приходит mms со штрихкодом, который и сканирует контролер.
И вообще говоря, странно выяснять нужна ли технология простому пользователю, применяя ее на хабраюзера. It люди это далеко не типичный пользователь.
Это врядли, иначе гугл бы давно разорился бы на бананах.
Хотя может они втихаря прикупили себе банановую республику.
Блин я в опасности я слишком близко подошел к тайне гугла. ААА куда вы меня тащите, грязные обезья…
В гугло переводчике работают статистические алгоритмы
Вот кусок статьи с cnet news.cnet.com/8301-1023_3-10005605-93.html

Wanted: More Rosetta Stones
Google's translation technique essentially relies on having as many Rosetta Stone-like documents as possible. The more documents it has in two languages, the better able it is to match words and phrases from one language to another, according to a recent speech by Jeff Dean, a Google fellow who works Google's computing infrastructure.
«By computing statistics over all words and phrases, you...get a model of word-by-word and phrase-by-phrase replacements,» Dean said. Machine translation often produces awkward results today, but «the impact of having a really large language model makes the sentences flow a lot more easily.»

В кратком пересказе чем больше документов переведенных на разные языки тем точнее работает гугло переводчик.
Так что врядли страшные русские/американские шовинисты решили досадить несчастным прибалтам. Это скорее показатель того, что мало в сети доступно переводов на литовский и латышский языки.
Было бы здорово добавить кнопочку "удалить дубликаты" по которой как-то нормализовать названия (удалить все амперсанды диакритические знаки, перевести все к маленьким буквам итд) а потом грохнуть дубликаты. Как пример где это очень надо: по запросу "von bondies" в плеер валиться 40 вариантов написания песни C'mon-C'mon.
Раз уж упомянута возможность хранить данные в Silverlight Isolated Storage, то стоило бы вспомнить и про google gears.
Эхх. Отправил комментарий, и понял, что написал по сути тот же foreach =(
Больше не буду умничать за полночь.
Может просто не забывать про замыкания, тогда можно написать что-то вроде

StringBuilder res = new StringBuilder();
mylist.ForEach(delegate(TestClass t)
{
res.Append((t.getString().Length != 0) ? t.getString() + "\n" : "");
});

Согласен, не совсем функциональный стиль, но как-то лучше того что написал автор статьи.

Если хочеться в функциональном стиле, то надо один раз написать что-то вроде

public delegate T1 AccumulateDelegate<T1, T2>(T1 prev, T2 value);

static T1 Accumulate<T1, T2>(IEnumerable<T2> l, T1 init_val, AccumulateDelegate<T1, T2> functor)
{
T1 res = init_val;
foreach (T2 t2 in l)
{
res = functor(res, t2);
}
return res;
}

И можно писать

string res2 = Accumulate(mylist, "", delegate(string prev, TestClass tc)
{
return prev + ((tc.getString().Length != 0) ? tc.getString() + "\n" : "");
});


И еще про питон, как функциональный язык. Лямбда функции там могут состоять только из одного выражения =(
стоимость + батарея

Information

Rating
Does not participate
Registered
Activity