LINUX.ORG.RU

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

Неужели ты думаешь, что в лиспе нет векторов, хеш-таблиц, что нельзя создавать свои типы данных, такие как деки и деревья? Не будь таким наивным. Это даже в чистом хаскеле есть. Там императивная монада IO позволяет делать практически все такие же структуры данных, что есть в си++ - и, что важно, будет работать примерно с той же скоростью (IO хорошо оптимизируется).

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

Тем не менее, есть разница в выборе выразительных средств, разница в том, как можно писать на лиспе и как на си++. Впрочем, надо признаться, что сейчас есть много лисперов, которые не знают и не признают ФП, и даже этим немного гордятся (let over lambda).

Для твоей начальной задачи сгодились списки (a-lists), и их выбор был правильным. Для новой озвученной тобою задачи, очевидно, нужны другие структуры данных, но это же банальность. Какой смысл к банальности придираться?

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

Да, ещё функции/классы в C++ не являются 'first class values'. Необходимость вникать в принципы ООП, всякие шаблоны/итераторы, чтобы хотя бы применять грамотно STL.

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

необходимостью заботы о выделении/высвобождении памяти.

я выше ни одного new/delete не написал в своих примерах, и в реальном коде тоже практически с ними не сталкиваюсь, так что тут нет необходимости, есть разные стратегии работы с памятью

Манипуляциями с указателями/ссылками(и различными тонкостями, связанными с этим, как например при передаче аргументов в функцию — происходит их копирование).

*,& - нет копирования, работаем с оригинальным объектом, ничего - есть копирование, куда уж проще, ну и назовешь сходу разницу между insert-after и ninsert-after в CL?

Всякие const/static/virtual. И т.д. и т.п.

о_О, примитивные же вещи

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

примитивные же вещи

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

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

Да, ещё функции/классы в C++ не являются 'first class values'

auto f = [](){ return «O'RLY?» };

Необходимость вникать в принципы ООП

нет ее, можешь писать как на чистом С, кстати у вас вон CLOS есть, ты ее не замечаешь?

всякие шаблоны/итераторы

странные претензии - у вас везде макросы и списки

чтобы хотя бы применять грамотно STL.

мы уже выше по треду выяснили, что STL не сложней вариантов на CL, как минимум никто не доказал обратное

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

понимаешь ли они становятся примитивными, когда у тебя уже накапливается опыт в C++.

да нет же, это действительно примитивщина, она даже в Java есть, а проще Java ЯП еще надо поискать

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

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

я знаю, что там много чего нет, а то, что можно создавать - везде можно

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

окай, сделаем вид, что кому-то действительно нужно сложить a+b+c+1+2, нет проблем, везде используем alist, теперь проект вырос, данных стало больше, alist тормозит - надо заменить на hash tables или свою уникальную реализацию, твои действия по поводу кода, который уже работает с alist?

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

Я смотрю, ты любишь задавать вопросы. Похвальное дело :)

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

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

А вернуть лямбду из функции можно?

~$ cat 1.cpp
#include <cstdio>

auto func() { return [](){ return "YA RLY!\n"; }; }

int main() {
    fputs( func()(), stdout );
}
~$ g++ -std=c++11 ./1.cpp
~$ ./a.out 
YA RLY!
wota ★★
()
Ответ на: комментарий от anonymous

Если знаешь STL и не знаешь CL, то безусловно.

ну про deque и hash tables никто не привел кода на CL, для первого сказали - нету, для второго - будет не так красиво набивать данные, обратный пример я приводил, без проблем приведу другие, если кто предложит задачку

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

Замыкания тоже поддерживаются?

~$ cat 1.cpp
#include <iostream>
#include <string>

auto func() { std::string s="YA RLY! v2\n"; return [s](){ return s; }; }

int main() {
	std::cout << func()();
}
~$ g++ -std=c++11 ./1.cpp
~$ ./a.out 
YA RLY! v2
wota ★★
()
Ответ на: комментарий от wota

будет не так красиво набивать данные

А у С++ будет не так красиво генерировать код с помощью макросов.

обратный пример я приводил

Ну, ты же понимаешь, что на детских примерах можно доказать всё, что угодно.

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

А у С++ будет не так красиво генерировать код с помощью макросов.

можно конкретную практическую задачу с примером на CL?

Ну, ты же понимаешь, что на детских примерах можно доказать всё, что угодно.

как раз на них доказать сложнее, но если даже на детских примерах есть затруднения - это уже интересно

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

можно конкретную практическую задачу с примером на CL?

У меня есть база данных mysql и функция query которая принимает строку, содержащую sql-запрос и возвращает ответ. Например:


mysql> desc host;
+-------+----------------------+------+-----+---------+----------------+
| Field | Type                 | Null | Key | Default | Extra          |
+-------+----------------------+------+-----+---------+----------------+
| id    | int(11)              | NO   | PRI | NULL    | auto_increment |
| host  | varchar(64)          | NO   | MUL | NULL    |                |
| port  | smallint(5) unsigned | YES  |     | NULL    |                |
+-------+----------------------+------+-----+---------+----------------+
(query "select * from host limit 1")

((((1 "10.10.200.32" 5060))
  (("id" :LONG 49667) ("host" :VAR-STRING 20489) ("port" :SHORT 49184))))

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

(defun mk-host (host)
  (let ((host (getf host :host))
        (port (getf host :port)))
    (insert-unique "host" host port)))

insert-unique это макрос, который принимает строку, содержащую имя таблицы в mysql и переменные в CL, совпадающие по имени с именами колонок в таблице mysql.

Напиши такой же макрос с помощью stl.

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

если даже на детских примерах есть затруднения

На примерах в пару десятков строк кода всё ООП нафиг не нужно, например.

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

Ты правда так делаешь? Правда пишешь такие макросы? И у тебя нормальные отношения с коллегами? Мдя...

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

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

Строго говоря, это не замыкание, т.к. строка будет тупо скопирована(перемещена?)... А если ты сделаешь замыкание по ссылке, то упадешь.

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

Функции и классы не должны быть first class values. Это никому ненужное извращение. Если хочешь поизвращаться - делай это самостоятельно, а в язык не надо пихать такие штуки. Тем более, что они нарушат принцип нулевой стоимости... Для функций есть лямбды, std::function, std::bind и пр. Для типов - пиши свое(ну или Qt используй, там почти что так для Q-типов).

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

Напиши такой же макрос с помощью stl

#define insert_unique( tbl, ... ) \
    [__VA_ARGS__]() \
    { \
        string query = string("INSERT INTO `") + tbl + "`(" + #__VA_ARGS__ + ") VALUES (" + join(__VA_ARGS__); \
        return db_->execute( query ).id; \
    }();

#define mk_host(...) insert_unique( "host", __VA_ARGS__ )

вероятно как-то так, но я б так не писал, просто потому-что завязываться на имя переменной - неправильно и чревато ошибками, я б жестко забил имена в структуру:

host h;
h.name = "localhost";
h.port = 80;
int id = mk_host( h );

или

int id = mk_host( { "localhost", 80 } );

если таки хочется сэкономить на коде

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

Строго говоря, это не замыкание, т.к. строка будет тупо скопирована(перемещена?)... А если ты сделаешь замыкание по ссылке, то упадешь.

если не нравится копирование (а тут чистая вкусовщина) - есть умные указатели

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

Ты наврал. Если ты пишешь auto у функции, то должен указать тип потом, через ->. И даже decltype ты не заюзаешь, ибо он не работает для лямбда-выражений(вот такой вот «вывод типов», как всегда плюсовики херню придумали). Придется возвращать std::function, а это минимум еще одно копирование/перемещение).

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

Ты наврал.

а ты поставь g++ 4.8 и проверь, если у тебя хоть немного достоинства есть - можешь извиниться потом

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

А вот у меня как-то не получилось заюзать ffi в лиспе, когда дифурами занимался.
Почитывай математику:-)

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

На хера испортили хороший язык ненужными лямбдами?!?

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

Дело не во вкусе. Замыкание предполагает работу с замыкаемым объектом, а в твоем коде это не так - ты будешь копировать. Для смартов тебе придется юзать динамическую память, а это в С++ медленно, GC же нет...

Строка будет скопирована в замыкание, а если строка большая? Почему, кстати, он ее не перемещает, а именно копирует? Правильно, потому что строку могут дальше использовать, а учесть то, что строка больше не нужна компилятору в данном случае не так просто... Да и не обязан ли он именно копировать по стандарту?

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

При чем тут gcc 4.8? Стандарт так требует, так что ты обязан указать тип после ->. А decltype не работает с лямбдами(вот же идиоты делали).

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

Для смартов тебе придется юзать динамическую память, а это в С++ медленно, GC же нет...

строки уже подразумевают динамическую память под буфер, смарты особо не повлияют

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

Так вот именно. У тебя итак буфер под строку, да еще и саму строку зачем-то в динамическую память пихать - не С++но это... Тем более, что как раз с маленькими объектами дефолтный распределитель херово работает.

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

При чем тут gcc 4.8? Стандарт так требует, так что ты обязан указать тип после ->

специально для тебя:

function<string()> func() { string s="YA RLY! v2\n"; return [s](){ return s; }; }

пример, где тебя не будет смущать auto, и вот она ужасная разница в скорости:

~$ cat 1.cpp
#include <functional>
#include <string>
using namespace std;

function<string()> func() { string s="YA RLY! v2\n"; return [s](){ return s; }; }

int main() {
	for( size_t i = 0 ; i < 10000000 ; ++i )
		func()();
}
~$ g++ -std=c++11 -Ofast ./1.cpp
~$ time ./a.out 

real	0m0.649s
user	0m0.644s
sys	0m0.004s
~$ cat 1.cpp
#include <functional>
#include <string>
using namespace std;

auto func() { string s="YA RLY! v2\n"; return [s](){ return s; }; }

int main() {
	for( size_t i = 0 ; i < 10000000 ; ++i )
		func()();
}
~$ g++ -std=c++11 -Ofast ./1.cpp
~$ time ./a.out 

real	0m0.458s
user	0m0.456s
sys	0m0.004s
wota ★★
()
Ответ на: комментарий от anonymous

Тем более, что как раз с маленькими объектами дефолтный распределитель херово работает.

~$ cat 1.cpp
#include <functional>
#include <memory>
#include <string>
using namespace std;

auto func() { auto s=make_shared<string>("YA RLY! v2\n"); return [s](){ return s; }; }

int main() {
	for( size_t i = 0 ; i < 10000000 ; ++i )
		func()();
}
~$ g++ -std=c++11 -Ofast ./1.cpp
~$ time ./a.out 

real	0m0.610s
user	0m0.608s
sys	0m0.000s

т.е. в реальных задачах будет вообще не заметна разница

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

Как раз наоборот, на твоих синтетических тестах разница невелика(но она есть), а вот в реальной жизни все это заметнее. Но не в том дело. Речь о том, что копирование - это не замыкание по определению. А замыкание по ссылке приводит к падению во многих случаях. Так о полноценных замыканиях, как в других языках(даже в D!), в С++ и речи быть не может.

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

а вот в реальной жизни все это заметнее

чистая фантазия, я как раз в реальной жизни постоянно использую профайлеры, да - бывают проседания в неожиданных местах, но никогда не видел таковых на умных указателях или std::function

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

я уже говорил - умные указатели

wota ★★
()
Ответ на: комментарий от ados
~$ time ./a.out 

real	1m0.481s
user	0m59.924s
sys	0m0.468s

рост линейный

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

Вспомни историю с auto_ptr.

да, он имел недостатки, причем не самые очевидные, потому его и заменили, С++ вообще далеко не идеален, кстати ты вроде присматривался к Rust - однозначное мнение уже есть?

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

да, он имел недостатки, причем не самые очевидные

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

Вся мощь и гибкость Си++ достигается комбинацией низкоуровневых опасных средств, и пока из осколков стекла сложишь мозаику - все пальцы изрежешь.

Rust - однозначное мнение уже есть?

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

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

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

а где не бывает ошибок? про любую ошибку/кривость в популярных ЯП можно так сказать

Вся мощь и гибкость Си++ достигается комбинацией низкоуровневых опасных средств, и пока из осколков стекла сложишь мозаику - все пальцы изрежешь.

единственное опасное средство как по мне - (полу)ручная работа с памятью, в С++17 планируют добавление GC, если доживем и ничего больше не взлетит - посмотрим, что получится

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

про любую ошибку/кривость в популярных ЯП можно так сказать

Даже и близко не про любую.

Вся мощь и гибкость Си++ достигается комбинацией низкоуровневых опасных средств

единственное опасное средство как по мне - (полу)ручная работа с памятью

_Комбинацией_ _низкоуровневых_ _опасных_ средств. Все три слова важны. Результат - известные загадки Саттера, которые, в сущности, имеют весьма логичные отгадки - после того, как запустишь wetware-интерпретатор Си++.

в С++17 планируют добавление GC

Вангую, что оно будет обвешано кучей малозаметных нетривиальных ограничений.

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

Вкорячат BoehmGC в стандарт?

нет

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

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

Даже и близко не про любую.

окей, есть ошибки, которые допускают «индусы», и которые ну очень очевидны

_Комбинацией_ _низкоуровневых_ _опасных_ средств. Все три слова важны.

все слова важны, только некоторые важней, работа с памятью - в их числе -

Вангую, что оно будет обвешано кучей малозаметных нетривиальных ограничений.

посмотрим, я тоже скептически настроен

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

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

ЯП это инструмент. Как молоток, или пассатижи, или микроскоп. Спорить о том какой ЯП абстрактно круче вне контекста конкретных задач так же глупо, как спорить о том что круче - молоток или пассатижи? Или все таки микроскоп?

//Ваш К.О.

AIv ★★★★★
()
Последнее исправление: AIv (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.