LINUX.ORG.RU

Задачка для ума. Из С++, но язык значения не имеет - главное типизация


1

2

Есть функция. Она должна в списке объектов найти объект по заданым свойствам.

Что делать, если функция не нашла объект?

Бросить исключение - не хочется. Понятие пустого объекта нет.

★★★★
Ответ на: комментарий от namezys

> Возвращаются объекты разного типа?

Возвращается «Maybe a», это полиморфный тип. «a» там может быть любым типом, в зависимости от ситуации.

sanuda
()
Ответ на: комментарий от namezys

> Зачем?

За тем что это решение задачи.

anonymous
()
Ответ на: комментарий от namezys

> Ну я о том же

Очевидно, если условия задачи требуют, чтобы объект был сконструирован, и одновременно с этим требуют, чтобы он сконструирован не был, то задача некорректна, т.к. решения не существует.

anonymous
()
Ответ на: комментарий от namezys

Тогда все понятно. И, пожалуй, не очень интересно.

trex6 ★★★★★
()

Я знаю решение твоей проблемы! Просто перепиши свою функцию в continuation-passing-стиле - то есть добавь к ней параметром указатель на функцию принимающую объект типа, соответствующего результату данной и в случае успеха вызывай из этой функции функцию по переданному указателю с найденным элементом. Что-то типа:

void find (prop p, list l, my_fun_type f) {
 ...
 if (...) f(x); 
}

ander-skirnir
()

>Понятие пустого объекта нет.

При желании ты можешь даже завести пустой типизированный объект, но в плюсах это будет чрезжопие с шаблонами

_________

//wfrr

anonymous
()
Ответ на: комментарий от SSZB

А метод должен вернуть std::string, ага?

делаем так:

[code]Res<T>{ T getValue() boolean isNull() }[/code]

и возвращаем его сколько влезет и вылезет.

_________

//wfrr

anonymous
()
Ответ на: комментарий от anonymous

Ну так это и есть boost::optional (Maybe, Option из других языков).

Begemoth ★★★★★
()
Ответ на: комментарий от ander-skirnir

Лол, месье получает приз.

anonymous
()
Ответ на: комментарий от LamerOk

Никак :) Но с практической точки зрения что int, что std::size_t почти одно и тоже, например:

std::size_t idx = 0;
vec[idx-1]; // кто мне здесь даст по рукам до того как случиться что-то очень плохое?
при этом std::size_t не позволяет вернуть -1, а SIZE_MAX много букв. :) Лучше везде в подобных случаях использовать int, а не std::size_t. В Qt правильно сделали.

P.S. Maybe вещь годная...

SSZB
()
Ответ на: комментарий от SSZB

> с практической точки зрения что int, что std::size_t почти одно и тоже, например:

С практической точки зрения, ты путаешь _размер_ массива и _смещение_ в нем.

LamerOk ★★★★★
()

Поставь, наконец, задачу формально! Без слов «хочется»

malbolge ★★
()
Ответ на: комментарий от Begemoth

В любом случае: хоть unsigned int более правильно для размеров и индексов, но жизнь это не упрощает, а ограничения создает... Unsigned int в целом (и std::size_t в частности) не нужен.

SSZB
()

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

typedef void (*TOnSearchSuccess)(void* userdata, const SearchResult& result);

void Search(arguments, TOnSearchResult cb, void* userdata);

gzh
()
Ответ на: комментарий от SSZB

но жизнь это не упрощает, а ограничения создает...

Итераторы ещё лучше.

std::size_t

Он нужен, т.к. позволяет писать код не привязанный к конкретной платформе.

Begemoth ★★★★★
()
Ответ на: комментарий от SSZB

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

int тоже создаёт ограничения - он позволяет индексировать только часть массива (для справки, на amd64, sizeof(int) == 4, т.е. массив ограничен 2^31 эелментами).

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

> int тоже создаёт ограничения - он позволяет индексировать только часть массива (для справки, на amd64, sizeof(int) == 4, т.е. массив ограничен 2^31 эелментами).

Я, наверное, не совсем понятно выразился: я не против std::size_t как yet another fucking pseudonym, я против того, что оно unsigned. Хотя про «на amd64, sizeof(int) == 4» не знал, спасибо. Конечно, признаю, в Qt косяк, но в stl тоже косяк (с std::size_t как unsigned).

SSZB
()
Ответ на: комментарий от SSZB

в stl тоже косяк (с std::size_t как unsigned)

В STL используются итераторы, и знаковость std::size_t там не нужна. Кстати, я как-то совсем забыл про std::ssize_t, он как-раз знаковый.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

Семантически возвращение «пустого итератора» эквивалентно возвращению пустого объекта, т.ч. в определенном смысле это противоречит условию (так или иначе появляется понятие «пустого объекта», пусть даже объекта другого типа). Затем, кто-то должен будет управлять временем жизни итератора. Что касается «уродования кода» - не вполне ясно, что Вы имеете в виду. В зависимости от ситуации и используемых библиотек можно сделать лаконичнее, я просто схему привожу. А вообще - man iteratee, http://www.haskell.org/haskellwiki/Enumerator_and_iteratee

gzh
()
Ответ на: комментарий от gzh

Семантически возвращение «пустого итератора» эквивалентно возвращению пустого объекта

Не пустого итератора, на итератора на элемент, следущий за последним, так что эквивалентности нет.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

По смыслу это эквивалентные вещи. Что за «последний элемент», откуда он возьмется? Если «последнего элемента» нет, - чему равен итератор, следующий за ним? Так или иначе, вам нужно будет ввести некоторое искусственное значение - в данном случае для итератора.

Что более важно, до каких пор ваш итератор должен оставаться валидным? В STL итераторы остаются валидными, пока жив контейнер, и плюс еще известные ограничения в зависимости от типа контейнера. В условии об этом ничего не сказано. Соответственно, решение, основанное на том, чтобы возвращать итератор из контейнера STL, будет так или иначе ограничивать реализацию поиска: в общем случае контейнер нельзя будет изменять, пока клиент не воспользуется итератором, который ему вернули. Эти детали протокола невозможно учесть в API. Напротив, идиома iteratee полностью свободна от всевозможных «дополнительных соглашений».

gzh
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.