LINUX.ORG.RU

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

В ООП то как раз, напротив, нет ограничений на иерархию

Ну возьмём твой любимый Smalltalk: Напиши класс, который при получении из коллекции выводит на экран сообщение.

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

не можешь каррировать метод

Кто запрещает?

Ну и чем принципиально отличается map от, скажем, zip?

ничем

Попробуй реализовать её методом

лови

Array.prototype.zip = function(array){
  return [this.map(function(x, i){return [x, array[i]]})]
}

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

Кто запрещает?

var partialMap = map(someFunc);
partialMap(someCollection);

Я запрещаю тебе делать это с someCollection.map() потому, что у someCollection нет метода partialMap без аргументов, который применяет именно someFunc.

this.map(function(x, i){return [x, array]})

Эмм. Твой код работает с массивами, не коллекциями.

Никто не гарантировал, что коллекция вообще умеет доступ по индексу. А ещё что у коллекции есть размер. В том же python3 это спокойно работает и умеет ленивость из коробки.

Попробуй ещё раз.

x3al ★★★★★
()
Последнее исправление: x3al (всего исправлений: 1)

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

 ((. map) . (.) . filter $ a) b =
((. map) . ((.) . filter) $ a) b =
(. map) ((.) . filter $ a) b =
(. map) ((.) (filter a)) b =
((.) (filter a)) . map $ b =
(.) (filter a) (map b) =
filter a . map b

После парочки таких упражнений шашлычный код становится более понятным. Однако, да, полезность умения ворочить комбинаторы в голове несколько сомнительна.

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

которые похожи в этом смысле на ФП

В ФП нет необходимости наследовать друг от друга объекты с разной логикой. Поэтому все жалобы на то, что он не может отнаследовать — это ООП-специфика. К слову, чем ему паттерн Builder вдруг стал ugly я тоже не понял.

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

Вообще то мой любимый не смоллток, а Io, смоллток я вообще толком не знаю. Просто привел как пример в числе ООП-языков.

Напиши класс, который при получении из коллекции выводит на экран сообщение.

Collection := Object clone do(
    getSlot_ := getSlot("getSlot")
    getSlot = method(name, getSlot_(name) print)
)

collection := Collection clone do (a := 1)
collection getSlot("a")  
somequest
()
Ответ на: комментарий от monk

Ага. Скрыли всю сложность за встроенными words и unwords и радуются. Воистину, хаскелль — язык для написания хелловорлдов и учебных примеров.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от monk

нет необходимости

нет возможности

//fixed

с разной логикой

с частично разной логикой

//fixed

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

нет метода partialMap

нет или есть — это все зависит от реализации

с массивами, не коллекциями.

так по ссылке которую ты дал то же самое.

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

Никто не гарантировал, что коллекция вообще умеет доступ по индексу. А ещё что у коллекции есть размер.

Это все фигня. Можно создать свою коллекцию, которая все что надо будет иметь.

умеет ленивость из коробки.

причем тут ленивость вообще?

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

Напиши класс, который при получении из коллекции выводит на экран сообщение.

Не. Должно быть

obj = MyObject clone
collection1 := List.with(1, obj)
collection2 := Map.with(a, 1, b, obj)

collection1 at(0)  // ничего, вернулось 1
collection1 at(1)  // выводит строку, вернулся obj
collection2 at("a")  // ничего, вернулось 1
collection2 at("b")  // выводит строку, вернулся obj

Если бы метод at принадлежал элементу, его можно бы было дополнить, но он принадлежит коллекции.

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

нет или есть — это все зависит от реализации

var square = R.map(x => x * x);
var double = R.map(x => 2 * x);
square([1, 2, 3]); // [1, 4, 9]
double([1, 2, 3]); // [2, 4, 6]

(ES6, Ramda). Ты предложишь добавлять .square и .double? Или как ты собираешься каррировать .map?

так по ссылке которую ты дал то же самое.

А в нормальных языках — нет, там нечто, что можно сейчас реализовать через for..of и @@iterator (и, наверно, велосипедную next()), но, поскольку при разработке JS была пропущена стадия проектирования — имеем что имеем.

x3al ★★★★★
()
Последнее исправление: x3al (всего исправлений: 3)
Ответ на: комментарий от somequest

Можно создать свою коллекцию, которая все что надо будет иметь.

Список чисел от N до бесконечности не имеет длину. Последовательность, генерируемая какой-либо функцией, не умеет доступ по индексу.

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

Каждую неделю добавлять в игнорлист? Уныло же.

Плюс в гугле (не от него, естественно) иногда узнаю что-то новое.

x3al ★★★★★
()
Последнее исправление: x3al (всего исправлений: 1)
Ответ на: комментарий от anonymous

«Сложность» здесь сказано не в том смысле, что «код сложен и непонятен», а в том, что «именно этот код представляет собой содержательное ядро программы».

Так вот, пример, приведённый monk'ом некорректен потому, что программа на плюсах по сути включает в себя реализацию разбиения на слова, в то время как в хаскелле она скрыта за стандартной библиотекой. Сравнивать выразительность и краткость языков на таком примере некорректно: это в лучшем случае сравнение загаженности стандартных библиотек ненужными высокоуровневыми сниппетами, которые имеют смысл только для применения в учебных примерах.

Так вот, если скопипастить реализации words и unwords (рекурсивно) в основной модуль, тогда можно заметить, что код на плюсах станет короче и понятнее кода на хаскелле.

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

Иногда для того, чтобы делать некие общие умозаключения, совершенно не нужно разбираться в синтаксисе конкретных языков.

Такой код читаем? (комментарий)

(Я вполне могу быть не прав, в каковом случае прошу разъяснить мне, без отсылок к «нуэтотынепоймёшь», в чём конкретно я не прав.)

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 5)
Ответ на: комментарий от intelfx

Python - тоже язык для написания хелловорлдов и учебных примеров?

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от intelfx

Иногда для того, чтобы делать некие общие умозаключения, совершенно не нужно разбираться в синтаксисе конкретных языков.

да, конечно, если «некие» = «ложные». Правда в этом случае не то, что в синтаксисе, вообще ни в чем разбираться не надо.

Так вот, если скопипастить реализации words и unwords (рекурсивно) в основной модуль, тогда можно заметить, что код на плюсах станет короче и понятнее кода на хаскелле.

давай я напишу реализацию на haskell без использования встроенных вещей и если она окажется короче той плюсовой, то с тебя сок.

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 1)
Ответ на: комментарий от intelfx

(Я вполне могу быть не прав, в каковом случае прошу разъяснить мне, без отсылок к «нуэтотынепоймёшь», в чём конкретно я не прав.)

а. «Воистину haskell только...» никак из наличия функций для работы со списками в stdlib не следует, и не является правдой в общем случае, например.

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

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

Скрыли всю сложность за встроенными words и unwords и радуются.

Анон дал уже одну ссылку, но я тебе дам лучше вот эту адовую сложность:

words = unfoldr (\s -> if null s then Nothing else Just . break (== ' ') . dropWhile (== ' ') $ s)
unwords = intersperse ' '

Воистину, хаскелль — язык для написания хелловорлдов и учебных примеров.

У мсье комплекс маленкого плюса?

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

хотя тут надо определиться, что считать встроенным, т.к. если свертки не покатят, то придётся в плюсах запретить использовать циклы. А на C-- к которому не придраться, получиться конечно менее лаконично, чем C++.

qnikst ★★★★★
()
Ответ на: комментарий от monk
Collection := Object clone do(
   with := method(o, o at := method(value := resend; (value type == "Number") ifFalse("foo" print); value); o)
)


collection1 := Collection with(list(1,"bar"))
collection2 := Collection with(Map with("a", 1, "b", "bar"))

collection1 at(0) println 
collection1 at(1) println 
collection2 at("a") println 
collection2 at("b") println 
/*
1
foobar
1
foobar
*/

только какое это отношение к делу имеет, я не понял.

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

Так вот, если скопипастить реализации words и unwords (рекурсивно) в основной модуль, тогда можно заметить, что код на плюсах станет короче и понятнее кода на хаскелле.

В чистом виде

isSpace :: Char -> Bool
isSpace = (== ' ')

break :: (a -> Bool) -> [a] -> ([a],[a])
break _ xs@[]           =  (xs, xs)
break p xs@(x:xs') = 
     if p x 
     then ([],xs)
     else let (ys,zs) = break p xs' in (x:ys,zs)

words :: String -> [String]
words s =  case dropWhile isSpace s of
                "" -> []
                s' -> w : words s''
                      where (w, s'') = break isSpace s'

unwords :: [String] -> String
unwords []              =  ""
unwords (w:ws)          = w ++ go ws
  where
    go []     = ""
    go (v:vs) = ' ' : (v ++ go vs)

revtext :: String -> String
revstr = unwords . reverse . words
 
revtext :: String -> String
revtext = unlines . map revstr . lines

Против (надо ли копипастить std::find, std::bind, std::equal_to, std::reverse?)

template <class BidirectionalIterator, class T>
void block_reverse_cpp11(BidirectionalIterator first, BidirectionalIterator last, T const& separator) {
   std::reverse(first, last);
   auto block_last = first;
   do {
      using std::placeholders::_1;
      auto block_first = std::find_if_not(block_last, last, 
         std::bind(std::equal_to<T>(),_1, separator));
      block_last = std::find(block_first, last, separator);
      std::reverse(block_first, block_last);
   } while(block_last != last);
}

   std::for_each(begin(str1), end(str1), [](std::string& s){
      block_reverse_cpp11(begin(s), end(s), ' ');
      std::cout << s << std::endl;
   });

Скажешь, версия на C++ всё равно понятнее?

monk ★★★★★
() автор топика
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от qnikst

давай я напишу реализацию на haskell без использования встроенных вещей и если она окажется короче той плюсовой, то с тебя сок.

Ну, я тоже хочу иметь возможность написать вундервафлю.

Требования какие к? Расход памяти, все дела.

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

Тебе бы уже пора понять, что нехорошо вклиниваться в беседы взрослых дядей, ступай поиграй в машинки.

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

Именно. Большая часть плюсового текста — это идентификаторы.

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

Вот эти все слова — тоже функции стандартной библиотеки или являются частью языка?

У мсье комплекс маленкого плюса?

Отнюдь.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Вот эти все слова — тоже функции стандартной библиотеки или являются частью языка?

1. Э-э-эм, стандартная библиотека — это разве не часть языка? Она же... это... стандартная.

2. А как быть тогда с BidirectionalIterator, std::reverse, std::placeholders, std::find_if_not, std::bind, std::equal_to, std::find, std::for_each и прочими?

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

только какое это отношение к делу имеет

В такой постановке (решении) никакого. Ты создаёшь свою коллекцию, а речь про объект в стандартных.

Хотя, строго говоря, постановка тоже не совсем корректная: объект не является параметром для at.

Давай возьмём, например, объект Directory и его метод at. Предположим, ты разработал своё объект, который хранит имя файла как список [каталог, подкаталог, ..., файл]. И тебе надо, чтобы твоим объектом было удобно пользоваться. В частности, должно работать Directory.at(myFile), Directory.exists(myFile), так как писать каждый раз Directory.at(myFile.asString) неудобно.

По твоему метод, тебе приходится для твоего файла делать отдельный тип myDirectory. Потом кто-то ещё делает superFile (хранящий метаданные) и делает свою superDirectory и т.д. А потом эти разные файлы оказываются в одной коллекции и тебе при обработке коллекции приходится проверять тип элемента и вызывать метод соответствующей *Directory.

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

я тебе дам лучше вот эту адовую сложность

Не поможет. Он скажет, что не хватает исходников unfoldr, break, dropWhile и intersperse

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

Стандартная библиотека написана на core language. Вот и различие.

Хотя всё равно неравноценно, потому что, например, в плюсах это std::bind (и placeholders), а в хаскелле, AFAIU, это ключевая фича самого языка, т. е. семантика встроена в компилятор. А так смотреть нужно; я не говорю, что предложенный плюсовый вариант подходит для сравнения выразительности языков.

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

Я говорю про расход на алгоритм в терминах этих ваших разных там нотаций. Речь о том, в частности, нужно in place или можно не in place, и так далее.

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

ты все понимаешь неправильно, в haskell стандартная библиотека написана на самом языке, исключение часть GHC.Exts работающая с примитивными типами (# - такая штука), и объясняющая всякие вещи компилятору, например inline/lazy, но ты это в обячных программах не увидишь. Так что unwords использовать можно.

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

Да везде стандартная библиотека написана на самом языке. Как раз поэтому, пользуясь ей, мы демонстрируем разве что предусмотрительность её авторов, но никак не выразительность самого языка.

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

я бы предпочел не in-place в данном случае, все ж в языке, который immutable by default использование мутабельности приводит к усложнению кода.

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

Повторяю, ты опять не понял, тут нету никакой семантики встроенной в компилятор. unwords это тоже самое, что в плюсах std::bind.

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

Нет, это ты меня не понял.

Во-первых, втф из " unwords это тоже самое, что в плюсах std::bind"? unwords и bind как бы совсем о разном; что ты имеешь в виду?

Во-вторых, я говорю вот о чём:

  • если в одном языке фича встроено в язык (== оператор языка), а в другом — в stdlib или вообще нет из коробки, мы разрешаем пользоваться stdlib'ом в этом случае (или пишем велосипед и разрешаем им пользоваться);
  • если в одном языке фича есть stdlib, а в другом её вообще нет из коробки, то мы запрещаем пользоваться stdlib'ом в этом случае (или копипастим из stdlib'а в свой код и учитываем при сравнении).

Makes sense?

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Во-первых, втф из " unwords это тоже самое, что в плюсах std::bind"? unwords и bind как бы совсем о разном; что ты имеешь в виду?

я имею ввиду, что или мне можно использовать uwords, или тебе нельзя std::*.

Makes sense?

На самом деле идею я понял, но не понял как разумно применить. Ты ведь не считаешь, что запрет на использованиеб например, for в программе на C++ будет разумным?

Впрочем, я даже не знаю, поскольку я не понимаю этого изменения выразительности языка по программам такого уровня.

qnikst ★★★★★
()
Последнее исправление: qnikst (всего исправлений: 2)
Ответ на: комментарий от monk

А потом эти разные файлы оказываются в одной коллекции и тебе при обработке коллекции приходится проверять тип элемента и вызывать метод соответствующей *Directory.

То есть претензия заключается в том что в одну коллекцию попадают объекты разных типов, в этом неудобство? То есть, лисповская list сделана неправильно?

Так ведь никто не мешает делать коллекции, которые хранят только один тип. Какое тут ограничение?

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

Не считаю. Поэтому мы разрешаем использовать хаскелльный «аналог циклов» (не знаю, насколько так вообще можно говорить по отношению к ФП), даже если это стандартная библиотека. Ну и наоборот: если в хаскелле можно использовать эти ваши higher-order functions (или что у вас там), то и в плюсах можно использовать std::bind.

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

Последовательность, генерируемая какой-либо функцией, не умеет доступ по индексу.

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

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

А как быть тогда с BidirectionalIterator, std::reverse, std::placeholders, std::find_if_not, std::bind, std::equal_to, std::find, std::for_each и прочими?

А там вообще некоторые вещи непонятно зачем написаны. Для решения конкретной задачи можно этот же код записать более понятно:

#include <algorithm>
#include <string>
#include <iostream>
 
using namespace std;

string block_reverse_cpp11(string what) {
   constexpr char separator = ' ';
   auto is_separator = []( char ch ) { return ch == separator; };
   auto last = end(what);
   auto block_last = begin(what);
   reverse(block_last, last);
   do {
      auto block_first = find_if_not(block_last, last, is_separator);
      block_last = find(block_first, last, separator);
      reverse(block_first, block_last);
   } while(block_last != last);
   return what;
}
  
int main() {
   string str1[] = 
    {
        "---------- Ice and Fire ------------",
        "",
        "fire, in end will world the say Some",
        "ice. in say Some",
        "desire of tasted I've what From",
        "fire. favor who those with hold I",
        "",
        "... elided paragraph last ...",
        "",
        "Frost Robert -----------------------"
    };
 
   for(auto & s : str1)
      cout << block_reverse_cpp11(s) << endl;
  
   return 0;
}

Нифига не лаконично как в хаскелле, но вполне себе вменяемо. Плюс к тому, C++ный вариант замену inplace делает.

eao197 ★★★★★
()
Последнее исправление: eao197 (всего исправлений: 1)
Ответ на: комментарий от intelfx

Makes sense?

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

То есть, грубо говоря, выйдет «a = f b» с одной стороны, и «a = f(b)» с другой.

Сравнить два исходных языка таким образом не получится.

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

не умеющих в надёжную внешнюю итерацию и в коллекции. Например, javascript

Что за внешняя итерация? Вообще-то в js есть итерабельные объекты, и Array, например, это итерабельный объект. причем тут map и filter?

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

Так более читаемо, да.

Сколько всего в плюсах появилось, однако... Всякие auto, constexpr, лямбды. Даже странно, зачем ради этого пришлось 2011го года ждать.

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