LINUX.ORG.RU

Впечатления рубиста от django


1

6

Долгое время писал под RoR и вот появилась работа под Django. Я поражён, это так неудобно.

1. По каждому чиху нужно писать импорты. На кой спрашивается? Это фреймвёрк для облегчения разработки или что?

2. Язык темплейтов это нечто ужасное. Вспоминаю ERB и как он прекрасен. Что бы написать темплейт надо учить этот корявый язык вместо того что бы использовать готовый, подсветки синтаксиса в темплейтах добиться не удалось.

3. Нет наследования всех контроллёров от одного (ApplicationController), таким образом совершенно не понятно как создать переменные доступные во всех темплейтах.


Вспоминаю ERB и как он прекрасен.

Лицоладонь... ассемблер наше всё...

Все в дебагер!

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

А речь не о структурной логике, а о синтаксисе.

«Структурная логика» — это что-то из соционики.

Язык состоит из синтаксиса и семантики. Куда твою структурную логику пристроить? Короче, мысль надо бы раскрыть.

Кстати, да. Хороший пример. Тоже отвратительные языки :)

Без комментариев. :)

Ужасный синтаксически язык может иметь массу поклонников.

Ага. Например, похапе. И петон. И JS.

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

Ага. Например, CL.

Характеристика читаемости синтаксиса языка никак прямо не связана ни с популярностью, ни с лёгкостью освоения…

Не знаю, зачем ты вытащил этот тезис про популярность — я вроде спорить и не собираюсь на сей счёт. Что до лёгкости освоения, то это, видимо, намёк на лёгкость освоения похапе (мнимую). Ну или если нет, то, опять же, не знаю, зачем этот тезис тут.

Теперь про читаемость. Вся «итить-колотить-нечитаемость!» Руби, как и остальных языков с богатыми возможностями метапрограммирования, сводится кому, что глаза петоно-похапе-программистов уже настроены на то, что минимальной смысловой единицей кода является абзац на треть страницы. Ну а как иначе. Циклы крутить вручную, итераторы перебирать и прочий мартышкин труд. (Ну в питоне с этим получше, конечно, дело обстоит. Но не слишком.)

В Руби же смысловые отрезки, удобные для чтения, в 2-5 раз короче, потому что код в несколько раз выразительнее. И отхватывая глазами по-привычке куски по полстраницы, они, разумеется, ничерта не могут в них понять.

А потом рассказывают байки про «я освоил синтаксис, но язык всё-равно нечитаемый!»

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

Да на что тут наезжать? Всем же пофиг, во сколько раз короче «смысловые отрезки» - важно, во сколько раз короче программы.

Впрочем... вот «смысловой отрезок» (чтение матрицы комплексных чисел из файла):

m = [[complex(s) for s in l.split()] for l in file("in").readlines()]

Перепиши это в 5 раз короче. Да хоть в 2 раза %)

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

Как-то так:

File.read('in').lines{|l|l.split.map(&:to_c)}
И таки да, короче получилось, но суть та же. Т.е. незачет. Но ты ж понимаешь, что на подобных коротких примерах никакой существенной разницы между питоном и руби не обнаружить. А теперь сравни питон и руби в плане аналогичного кода с пхп.

Кстати, как в правоверном питон-вэйе переписать такой метод?

def output_text(data)
	col_size = data.transpose.map{|col| col.map(&:size).max}
	puts data.map{|row|
		row.zip(col_size, [true, true]).map{|value, size, align_left|
			align_left ? value.ljust(size) : value.rjust(size)
		}.join(" | ")
	}
end

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

File.read('in').lines{|l|l.split.map(&:to_c)}

И таки да, короче получилось

Не-не-не, Дэвид Блейн, где мой 2-кратный выигрыш?

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

Ну, это ты говорил о «смысловых отрезках», а я о программах %)

Кстати, как в правоверном питон-вэйе переписать такой метод?

Я даже не понял, что делает эта штука. Толсто намекает «у вас в Питоне нету многострочных лямбд»? %)

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

Ну, это ты говорил о «смысловых отрезках», а я о программах %)

А где тут у тебя программа? :-D

Я даже не понял, что делает эта штука.

На входе матрица строк. Считаем ширину столбцов. Потом выплевываем на stdout красивую таблицу с выровненными столбцами, разделенными символом «|». В первых двух столбцах содержимое выравниваются по левому краю, в остальных по правому.

Толсто намекает «у вас в Питоне нету многострочных лямбд»? %)

Возможно, намекает, что питон не готов к FP. Но может ты меня переубедишь.

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

А где тут у тебя программа? :-D

Кхм. Что именно непонятно в:

tailgunner> Впрочем... вот «смысловой отрезок»

?

питон не готов к FP

Не готов, но отнюдь не из-за многострочных лямбд. Да и Руби готов не больше.

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

Кхм. Что именно непонятно в:

Ты уж определись. Или смысловые отрезки сравнивать. Или «всем пофиг. важно, во сколько раз короче программы.»

Не готов, но отнюдь не из-за многострочных лямбд.

Ага, там еще есть разработчик со странностями.

Да и Руби готов не больше.

Приведенный код написан в функциональной парадигме. Вопросы?

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

Ты уж определись. Или смысловые отрезки сравнивать. Или «всем пофиг

Это так называемая „ложная альтернатива“.

Приведенный код написан в функциональной парадигме. Вопросы?

О да. И определяет принадлежность к „функциональной парадигме“... что именно?

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

Это так называемая «ложная альтернатива».

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

О да. И определяет принадлежность к «функциональной парадигме»... что именно?

В данном куске кода мы видим:

  • Функции как first-class object.
  • Функционалы.
  • Отсутствие переменных в том смысле, в котором они наличествуют в ИП.
  • Чистота.
geekless ★★
()
Ответ на: комментарий от geekless

просто перевести мой сэмпл кода на питон.

Моего знания Руби не хватает для этого. А ботать Руби ради короткого спора на форуме... ты правда обо мне такого низкого мнения? %)

* Функции как first-class object.
* Функционалы.
* Отсутствие переменных в том смысле, в котором они наличествуют в ИП.
* Чистота.

Ну, тогда Питон тоже готов к ФП. Но... на самом деле, HOF - это еще не ФП. Где поддержка языком иммутабельности по умолчанию, ссылочной целостности, нормальных конструкторов типов, паттерн-матчинга? Фрагмент, приведенный тобой - это упражнение на тему «а вот мы щас всё сделаем на безымянных лямбдах». В таком стиле можно писать при наличии желания и самодисциплины, но язык тебе поможет только с HOF.

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

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

Моего знания Руби не хватает для этого.

Я ж тебе по-русски дал алгоритм, тут надо знание не руби, а питона. :}

Но... на самом деле, HOF - это еще не ФП. Где поддержка языком иммутабельности по умолчанию, ссылочной целостности, нормальных конструкторов типов, паттерн-матчинга? Фрагмент, приведенный тобой - это упражнение на тему «а вот мы щас всё сделаем на безымянных лямбдах». В таком стиле можно писать при наличии желания и самодисциплины, но язык тебе поможет только с HOF.

Не спорю. Но надо и понимать, что все эти парадигмы — довольно условная вещь. По сути же в вопросах ЯП есть два лагеря: лагерь ПравильногоСпособаПисатьКод (паскаль, питон, жава, хаскель и т.п.) и лагерь Метапрограммирования (лиспы, тикль, руби). Я определенно во втором. И для меня ФП и любая другая парадигма, это не столько о том, как это обеспечивается изнутри, сколько о том, как это выглядит. Language as interface. В данном случае ФП позволяет писать более наглядный код. Пусть даже это и не настоящее ФП. А вот на питоне так не выйдет — наглядность не повысится. В этом вся разница.

Кстати, код нечитабельный

Код читабельный.

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

Код написан в один присест, никакой отладки не было.

Вот в этом, понимаешь, и отличие в восприятии кода на языке. Ты ж не будешь делать отдельную отладку для каждого тривиального трехстрочного if-а? Вот и я для этого кода не буду делать. Мне тут всё очевидно и тривиально. А пиши я это на пхп или крестах — наверное пришлось бы. Это совсем другой уровень.

И более того,

наверняка был разбит на несколько операторов.

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

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

Ну а ты-то конечно очень аргументированные реплики подаешь.

Ну разбей по строкам:

File.read('in').lines { |line|
    line.split.map(&:to_c)
}

Или даже так:

File.read('in').lines {|line|
    line.split.map{|num|
        num.to_c
    }
}

Легче стало?

Если стало, то это тогда про «W/O-код» был бессмысленный бред, сродни тому, что, мол, «у вас код нечитаемый, потому что в if-ах вы скобочки неправильно ставите».

Если не стало, то рассказывай подробнее, где ты тут видишь W/O.

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

Я ж тебе по-русски дал алгоритм, тут надо знание не руби, а питона. :}

Everybody lies же.

для меня ФП и любая другая парадигма, это не столько о том, как это обеспечивается изнутри, сколько о том, как я эту парадигму понимаю

fixed

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

Да я не виляю. Объясняю как есть. То «ФП», которое у нас тут в примере, это не ФП в том понимании, которое ты указал. Я с этим и не спорю.

Но важно в рамках обсуждения не то, как это правильно называть. А что, эта «не-ФП»-парадигма реально помогает писать на Руби более наглядный и лаконичный код. А на питоне — не помогает.

geekless ★★
()

Имхо, erb, django-темплейты, smarty и прочие raw + вкрапления инородных яп, всё одно и тоже. А вот haml тема. С его использованием и вложенность тегов не поломается, и всякие там аглифаеры/минифаеры применяются прозрачно для продакшена.

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

Легче стало?

Нет. Потому что это — W/O

Если не стало, то рассказывай подробнее, где ты тут видишь W/O

В обилии синтаксического мусора, который сложно выделяется на общем фоне. Пайпы, фигурные скобки, постоянная смена стилистики (то цепочки объектов, то блоки, да ещё в аргументах). Всё это сильно затрудняет визуальный парсинг. Даже если ты насобачишься читать его — это не значит, что это хорошо.

Я могу тащить рюкзак весом 30 кг. Но я предпочитаю коммуникатор, помещающийся в карман брюк и готов спорить за каждый десяток грамм его веса.

Можно насобачиться визуально парсить даже Brainfuck. Но от этого он не станет комфортнее. А человек, которому противен Whitespace не обязательно имеет проблемы со зрением.

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

эта «не-ФП»-парадигма

Не следует говорить о «неготовности Питона к ФП», если ты и сам понимаешь, что под названием «ФП» у тебя своя личная парадигма.

более наглядный и лаконичный код

В этом топике 1 человек считает твой код читабельным и 2 человека считают твой код нечитабельным.

Ах да, и я всё еще хочу увидеть выигрыш в 5 раз %)

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

В обилии синтаксического мусора, который сложно выделяется на общем фоне.

Учитывая, что по сравнению с большинством ЯП, в Ruby вообще синтаксиса практически нет, это пять . :-D

Пайпы, фигурные скобки, постоянная смена стилистики (то цепочки объектов, то блоки, да ещё в аргументах).

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

Всё это сильно затрудняет визуальный парсинг.

Ага, то ли дело пых:

$result = explode("\n", file_get_contents("file"));
foreach($result as &$row)
{
	$row = explode(" ", $row);
	foreach($row as &$col)
	{
		$col = to_complex($col);
	}
	unset($col);
}
unset($row);
Всё просто и понятно! Сразу видно, что этот код делает. Никакого синтаксического мусора не выделяется на общем фоне. Пайпов нет, фигурные скобки никак не выбиваются из &$;-стилистики, а органично вписываются в её. А unset-ы так вообще прекрасно дополняют foreach и служат визуальным индикатором конца цикла — так и задумано. И вообще, код даже короче.

Я ничего не забыл?

Я могу тащить рюкзак весом 30 кг. Но я предпочитаю коммуникатор, помещающийся в карман брюк и готов спорить за каждый десяток грамм его веса.

Я заметил. :-D

А человек, которому противен Whitespace не обязательно имеет проблемы со зрением.

Опять пишешь реплики в ответ на какие-то свои фантазии?

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

Почему?

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

Ах да, и я всё еще хочу увидеть выигрыш в 5 раз %)

Вон рядом в другом комменте код на пхп. Увидишь там выйгрыш в 7 раз.

В этом топике 1 человек считает твой код читабельным и 2 человека считают твой код нечитабельным.

Курс КПСС верен потому что истинен. О чем это мы?

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

В этом топике 1 человек считает твой код читабельным и 2 человека считают твой код нечитабельным.

Можешь меня записать в число тех, кто считает этот код читабельным.

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

Вон рядом в другом комменте код на пхп. Увидишь там выйгрыш в 7 раз.

Я хоть и не знаю пыка, но вижу, что 7-кратный выигрыш - за счет пустых строк с '{', т.е. мошенничество. Кстати, в какой-то из версий пыха есть и map, и лямбда.

Курс КПСС верен потому что истинен. О чем это мы?

Ты почему-то решил снова отклониться от темы и для разнообразия поговорить о политике %)

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

Кстати, питоновский код менее читаем ещё и в силу своей инверсии.

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

Можешь меня записать

Перекличка рубистов объявляется открытой.

питоновский код менее читаем ещё и в силу своей инверсии.

ОК, но в посте, на который я отвечал, речь шла только о краткости. Уже потом я выразил сомнение в читабельности 4-строчного шашлыка из лямбд.

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

Я хоть и не знаю пыка, но вижу, что 7-кратный выигрыш - за счет пустых строк с '{', т.е. мошенничество.

7-кратный — без строк с '{'. А сними — 11-кратный. Как-то странно ты «видишь».

Кстати, в какой-то из версий пыха есть и map, и лямбда.

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

Ты почему-то решил снова отклониться от темы и для разнообразия поговорить о политике %)

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

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

Кстати, в какой-то из версий пыха есть и map, и лямбда.

А нет — вспомнил — map там в лучших традициях жанра называется array_map. А вот про лямбды не помню, пойду ман покурю.

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

Как-то странно ты «видишь».

Есть такое, да.

1: foreach(explode("\n", file_get_contents("file")) as &$row)
{
2:	foreach(explode(" ", $row) as &$col)
	{
3:		$col = to_complex($col);
	}
}

или синтаксис пыха допускает только foreach(var1 as var2)?

Ты почему-то решил отклониться от темы и поговорить о статистике из 3-х человек

Я говорил о читабельности кода, вообще-то. И слово «статистика» не использовал по вполне понятным причинам.

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

ОК, но в посте, на который я отвечал, речь шла только о краткости. Уже потом я выразил сомнение в читабельности 4-строчного шашлыка из лямбд.

Однострочник на руби с прямым порядком читаем, в отличие от однострочника на питоне с обратным порядком.

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

foreach(explode(«\n», file_get_contents(«file»)) as &$row)

А результат-то ты куда сохранишь?

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

Уже потом я выразил сомнение в читабельности 4-строчного шашлыка из лямбд.

Как раз после того, как не решился переводить его на питон. Очень уместно.

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

Однострочник на руби с прямым порядком читаем, в отличие от однострочника на питоне с обратным порядком.

(пожимая плечами) Для меня оба читаемы одинаково.

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

foreach(explode(«\n», file_get_contents(«file»)) as &$row)

А результат-то ты куда сохранишь?

Результат чего, file_get_contents или explode? И зачем его сохранять? Я и результат readlines нигде не сохранял.

Ну и unset-ы ты удачно не посчитал, ага.

Если мой вариант правилен, они не нужны. Впрочем, их нужность и вообще сомнительна.

Как раз после того, как не решился переводить его на питон

Утипути. Объясни мне, что конкретно значат transpose и zip, и завтра я переведу его на Python.

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

Ага, то ли дело пых

Для тебя ПЫХ — это образец для сравнения? o_O

В остальном — в теме уже было.

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

Результат чего, file_get_contents или explode? И зачем его сохранять? Я и результат readlines нигде не сохранял.

У тебя код на питоне — выражение, имеющее результат (распарсенную матрицу). Если конечно я правильно понимаю питон. Мой код на руби — аналогично, выражение, имеющее результат.

А тут foreach — оператор. Он ничего не возвращает.

Если мой вариант правилен, они не нужны. Впрочем, их нужность и вообще сомнительна.

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

Утипути. Объясни мне,

Да я ж попросил написать в питон-вэйе код для форматирования таблицы указанным образом. Не надо обезьяннить мой алгоритм один-в-один.

что конкретно значат transpose и zip

transpose — транспонирование матрицы. zip — поэлементное слияние двух или более массивов. ( [a b c], [x y z], [1 2 3] -> [[a x 1] [b y 2] [c z 3]]) По сути, почти тот же transpose.

Кстати, прочитал ман на лямбды пхп, и вот как оно получается:

array_map(function($line){
	return array_map(function($col){
		return to_complex($col);
	}, explode(" ", $line));
}, explode("\n", file_get_contents("file")));
Особенно мне нравится замечательный порядок аргументов у функций стандартной библиотеки пхп. Инопланетяне одобряют.

После такого не удивительно, что программисты «не понимают» лямбды.

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


Кстати, раз уж (хотя ни разу Пых не считаю образцом для подражания):

foreach(file("file") as $line)
	foreach(explode(" ", chop($line)) as $col)
		$col = to_complex($col);

Хотя непонятно, что ты с $col делать хочешь, а то и так можно:

foreach(file("file") as $line)
	array_map('to_complex', explode(" ", chop($line)));

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

Хотя непонятно, что ты с $col делать хочешь

С $col я ничего делать не хочу — по условию, мы его конвертируем из строки в объект (в комплексное число, или во что там было). И имеем в качестве результата двумерную матрицу таких объектов.

geekless ★★
()
Ответ на: комментарий от KRoN73
foreach(file("file") as $line)
	foreach(explode(" ", chop($line)) as $col)
		$col = to_complex($col);

Эээ... И что это? Код бессмысленный. Результат-то где будет?

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

Результат-то где будет?

Что ты на PHP написал, то я и изобразил.

С $col я ничего делать не хочу — по условию, мы его конвертируем из строки в объект

Ты, как-то, вообще unset для него делаешь в конце цикла.

На Ruby, вот, тоже не очевидно, что ты потом с результатом делаешь.

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

Что ты на PHP написал, то я и изобразил.

Возможно, я код криво нарисовал. Или ты не так понял.

Вопрос: ссылка не позволяет присваивая в себя значение, заменять объект, на который она ссылается?

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

Ты, как-то, вообще unset для него делаешь в конце цикла.

Я уничтожаю висящую ссылку, потому что пых её сам не уничтожает при выходе из цикла. А результат — в $result. Двумерная матрица. По идее.

На Ruby, вот, тоже не очевидно, что ты потом с результатом делаешь.

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

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

ссылка не позволяет присваивая в себя значение, заменять объект, на который она ссылается?

Погуглил. Позволяет. Помню значит еще что-то, всё правильно.

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