понял кое-что
ivan_gandhi — 30.01.2014 Я уже забыл сколько лет учусь программировать понемножку.Вы, наверное, думаете, что вы уже умеете.
Скорее всего, вы ошибаетесь.
Но это неважно.
Вот что я понял.
Теория множеств навела сильную порчу на восприятие программирования вообще.
В частности, в головах прочно сидит такая идея, что возвращать нужно число, или что-то булево, или строку какую-нибудь. Даже если функция частичная.
Ну типа мы "память экономим". У нас 4 миллиарда байтов как минимум; мы наэкономим тыщу. Или даже миллион. Это бред; это преданья старины глубокой.
Теперь, если мы выкинем из головы этот бред про экономию памяти, то надо признать, что функции (частичные функции) не должны возвращать бессмысленное элементарное значение. А возвращать они должны значение, завёрнутое в специализированный контейнер.
Например,
indexOf(sub: String)(s: String):
SearchResult
, вот как надо. Причём этот
SearchResult
не должен иметь метода, возвращающего
этот самый индекс. Ниже я расскажу, что получается, если он такой
метод имеет. Нет, вместо этого, надо писать что-нибудь вродеindexOf(needle)(haystack) match { case FoundAt(i) => println(s"Hurray, we found it at $i!!!") case NotFound(what, where) => println(s"Oops, we tried to find <<$what>> in <<$where>>, but we failed. Oops.") }
На хаскеле народ так и пишет, не задумываясь. Да и везде, где патерн-матчинг есть.
Тем не менее, популярна т.наз. монада
Maybe
, aka
Option
. У Option[T]
в скале есть метод
get
. Недаром там параметр типа стоит; а то нафиг бы он
был нужен.Вот что такое этот
get
- это естественное
преобразование функтора Option
в функтор
Exception
- и всё.Надо нам это? Кому-то надо, но я убедился (сегодня утром), что мне лично это не надо.
И вообще, использование этих мейбеев, опшенов, боксов, моего класса
Result
- практика порочная; это практически то же
самое, что и использование примитивных типов и "кодов результата"
отдельно от результата. Типы же есть! Типы! Их и надо
использовать.А, вот пример:
До
def getOutOfPocketData:Props = { val tag = // redacted if (!loadPage(urlOfOutOfPocketPage)) { suspiciousError(s"Failed to load $urlOfOutOfPocketPage") NoProps } else if (!waitSelector(tag)) { suspiciousError("sFailed to fine $tag on $urlOutOfPocketPage") NoProps } else { val rawHtml = runJS(s"return document.querySelector('$tag').innerHTML") if (rawHtml.isBad) { suspiciousError(s"Failed to retrieve OOP: $rawHtml") NoProps } else { val html = rawHtml().toString val props = extractOopFrom(html) // debug(s"Got Props\n$props\n................... from\n$html\n=========") if (props.isEmpty) warn(s"Source was $html") props } } }
(проверяем сорс, парсить нечего, пишем в лог, возвращаем коллекцию пустых пропертей ("разбирайтесь мол")
после
def getOutOfPocketData:HtmlContentParser.ParseResult = { val tag = // redacted if (!loadPage(urlOfOutOfPocketPage)) NothingToParse(s"Failed to load $urlOfOutOfPocketPage") else if (!waitSelector(tag)) NothingToParse("sFailed to find $tag on $urlOutOfPocketPage") else { val rawHtml = runJS(s"return document.querySelector('$tag').innerHTML") rawHtml fold(source => extractOopFrom(source.toString()), bad => NothingToParse(s"Failed to retrieve OOP: ${bad.mkString}") } }
(проверяем сорс, парсить нечего, возвращаем именно это состояние - результата нету! (никаких пропертей))
|
</> |