Здравствуйте, Kolesiki, Вы писали:
K>Поздно. Лет 15 назад он мог бы с кем-то пободаться, но сейчас — кому он нужен? (кроме маргиналов и админов локалхоста) K>Быдловеб прочно занят похапастами, незанятые области утыканы пестонорубями. Серьёзные сектора — все ожаблены или под ASP. На десктопе ему вообще делать нечего. K>На мой взгляд, Перл-6 — это проект ради проекта, какой-то самодостаточный мир олдфагов на ностальгирующем драйве. Жаль растрачивают усилия зазря...
На Perl пишут все те, кто хочет на нём писать. Если толпа на нём не ваяет всякий ширпотреб на широптребных либах,
то это не значит, что его не применяют в закрытых, никому не известных проектах. Perl ЯП уникальный, все остальные
ЯП, раскрученные для толпы и ширпотреба, не содержат и доли тех возможностей, что заложены в Perl.
Но толпа с явой-пхп-питон-сришарпом головного мозга об этом даже не догадывается, но мнение имеет.
Здравствуйте, Sheridan, Вы писали:
S>Ну так расссказал бы чего интересного, привел бы несколько примеров удобств... S>Ну или хотя бы линк на статью дай, где это есть.
Здравствуйте, Takadam, Вы писали:
T>Здравствуйте, Sheridan, Вы писали:
S>>Ну так расссказал бы чего интересного, привел бы несколько примеров удобств... S>>Ну или хотя бы линк на статью дай, где это есть.
T>Например, вот:
T>
T>>Можно передавать ассоц массив, в котором могут быть только ключи arg1 и arg2 и arg3 (optional). А ваших рубях и питонах такое есть?
S>А чем это отличается от передачи интерфейса?
тем что в динамических языках интерфейсов нет. с добрым утром.
S>И да, такое есть в typescript, только там ещё можно типы указать:
и в C#, и джаве и c++ и в еще куче статич. языков тоже есть. только мы говорим про руби и питон потому что perl 6 ближе к ним.
Здравствуйте, Takadam, Вы писали:
S>>А чем это отличается от передачи интерфейса? T>тем что в динамических языках интерфейсов нет. с добрым утром.
Это понятно, просто чем-то интересным это не выглядит.
S>>И да, такое есть в typescript, только там ещё можно типы указать: T>и в C#, и джаве и c++ и в еще куче статич. языков тоже есть. только мы говорим про руби и питон потому что perl 6 ближе к ним.
Typescript динамический язык.
Здравствуйте, Somescout, Вы писали:
S>Здравствуйте, Takadam, Вы писали:
S>>>А чем это отличается от передачи интерфейса? T>>тем что в динамических языках интерфейсов нет. с добрым утром. S>Это понятно, просто чем-то интересным это не выглядит.
а что выглядит, проверять в теле функции, какие ключи были переданы?
S>>>И да, такое есть в typescript, только там ещё можно типы указать: T>>и в C#, и джаве и c++ и в еще куче статич. языков тоже есть. только мы говорим про руби и питон потому что perl 6 ближе к ним. S>Typescript динамический язык.
тогда почему при объявление переменных указывается их тип?
Здравствуйте, Takadam, Вы писали:
S>>Это понятно, просто чем-то интересным это не выглядит. T>а что выглядит, проверять в теле функции, какие ключи были переданы?
Да я не спорю что полезно, просто... в статических языках такое и так есть, в динамических — см. ниже, тоже успели реализовать.
S>>>>И да, такое есть в typescript, только там ещё можно типы указать: T>>>и в C#, и джаве и c++ и в еще куче статич. языков тоже есть. только мы говорим про руби и питон потому что perl 6 ближе к ним. S>>Typescript динамический язык.
T>тогда почему при объявление переменных указывается их тип?
Это надмножество javascript с опциональной типизацией, для любого типа можно указать "any" и использовать как в обычном js.
Что мне особо нравится, вывод типа идёт по содержимому, а не по наследованию:
class User {
public constructor(
public Name:string,
public Title: string
) { }
}
class Group {
public constructor(
public Name:String,
public Options: number)
{ }
}
function printName(entity: {Name: string}) {
console.log(entity.Name);
}
// Несмотря на то что это разные классы, они удовлетворяют требованию о наличии поля Name
printName(new User("Test", "test"));
printName(new Group("Test", 1));
// Или вообще так:
printName({Name: "Inline" });
// При этом всё равно проверяются типы:
printName({Name: 123}); // Ошибка
// Можно сказать что Name может быть числом или строкой
function printName2(entity: {Name: string|number}) {
console.log(entity.Name);
}
// и тогда этот вызов будет корректным
printName2({Name: 123}); // Теперь не ошибка
Здравствуйте, Somescout, Вы писали:
S>Да я не спорю что полезно, просто... в статических языках такое и так есть, в динамических — см. ниже, тоже успели реализовать.
Ближайшие соседи perl 6 — это PHP, python, ruby. В них такое не поддерживается.
Typescipt можно сравнивать с дартом и js.
T>>тогда почему при объявление переменных указывается их тип?
S>Это надмножество javascript с опциональной типизацией, для любого типа можно указать "any" и использовать как в обычном js.
В джаве тоже можно указать object, но это ведь не делает джаву динамич языком.
Здравствуйте, Takadam, Вы писали:
T>Ближайшие соседи perl 6 — это PHP, python, ruby. В них такое не поддерживается.
Я не о том — вопрос был показать какую-нибудь интересную фичу, а эта фича хоть и неплоха но не сильно новая или интересная.
T>В джаве тоже можно указать object, но это ведь не делает джаву динамич языком.
Не в ту степь уходим, но если указать object это будет именно object, который можно только скастить во что-то другое. В ts указав any с объектом можно работать именно как с произвольным значением. Это именно указание не применять типизацию.
Здравствуйте, Mamut, Вы писали:
M>Слишком многословно, из-за чего все, что сложнее [x*x for x in list] становится нечитаемым, а создание сколько-нибудь сложных comprehension'ов — нетривиальным.
Для сложных есть yield.
M>
M># Python for if for if чтоа?
M>[(x,y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]
M>% Erlang. По сути, перечисление условий для получения X и Y.
M>[{X, Y} || X <- range(5), Y <- range(5), x rem 2 == 0, y rem 2 == 1 ]
M>
А какая семантика у Erlang варианта? Подозреваю что фильтры применяться после того как сгенерируются пары, то есть неэффективно. На Python так кстати тоже можно
>>> [(x,y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
>>> [(x,y) for x in range(5) for y in range(5) if x % 2 == 0 if y % 2 == 1]
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
>>> [(x,y) for x in range(5) for y in range(5) if x % 2 == 0 and y % 2 == 1]
[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
Здравствуйте, smeeld, Вы писали:
S>На Perl пишут все те, кто хочет на нём писать. Если толпа на нём не ваяет всякий ширпотреб на широптребных либах, S>то это не значит, что его не применяют в закрытых, никому не известных проектах.
Я бы сказал, что перл часто пользуется в задачах автоматизации, когда баша уже недостаточно, а что нибуть типя сей уже перебор.
Лично у меня на перлах нарисованы некоторые сервисы, автоматизирующие нужное мне. Например, я сейчас снимаю таймлапс с этой камеры, а так же таймлапсы некоторых статистик LHC. Сервис написан на перле.
Или вот, мой крайний проект: автоматизация майнкрафта при помощи эмуляции клавиатуры\мыша.
Питон в подобном деле не катит, ибо у него голва свёрнута на отступах, приходится дохрена отвлекаться на их соблюдение.
Руби... Хз, руби пока не трогал.
M>>Слишком многословно, из-за чего все, что сложнее [x*x for x in list] становится нечитаемым, а создание сколько-нибудь сложных comprehension'ов — нетривиальным. EP>Для сложных есть yield.
Что меняет yield?
Скрытый текст
M>>
M>># Python for if for if чтоа?
M>>[(x,y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]
M>>% Erlang. По сути, перечисление условий для получения X и Y.
M>>[{X, Y} || X <- range(5), Y <- range(5), x rem 2 == 0, y rem 2 == 1 ]
M>>
EP>А какая семантика у Erlang варианта? Подозреваю что фильтры применяться после того как сгенерируются пары, то есть неэффективно.
Здравствуйте, Mamut, Вы писали:
M>>>Слишком многословно, из-за чего все, что сложнее [x*x for x in list] становится нечитаемым, а создание сколько-нибудь сложных comprehension'ов — нетривиальным. EP>>Для сложных есть yield. M>Что меняет yield?
Позволяет вынести генерацию ленивого списка в отдельную функцию, в которой можно всё внятно расписать.
EP>>А какая семантика у Erlang варианта? Подозреваю что фильтры применяться после того как сгенерируются пары, то есть неэффективно. M>Это я постараюсь в течение дня посмотреть. Знаю пока то, что они разворачиваются в функции с паттерн матчингом и tail-recursion: http://www.erlang.org/doc/efficiency_guide/listHandling.html#id67562
Это скорей всего сахар для монады List, или аналога — и тут как раз важно чтобы guard был как можно раньше, чтобы сразу отсечь лишние ветки.
Здравствуйте, Sheridan, Вы писали:
S>Питон в подобном деле не катит, ибо у него голва свёрнута на отступах, приходится дохрена отвлекаться на их соблюдение.
Даже в языках где отступы не обязательны, код без них не читаем.
Все практики написания кода об этом пишут.
В любом случае их нужно соблюдать.
А любой вменяемый редактор умеет это делать автоматически и не нужно думать об этом.
Здравствуйте, _NN_, Вы писали:
_NN>Даже в языках где отступы не обязательны, код без них не читаем.
Полностью и категорически согласен.
Но питон пошел еще дальше. В итоге получается похоже на поездку к бабушке с "СПАСИБО, бабушка, не надо больше еды!!"
M>>Что меняет yield? EP>Позволяет вынести генерацию ленивого списка в отдельную функцию, в которой можно всё внятно расписать.
Внезапно откуда-то появились ленивые списки EP>>>А какая семантика у Erlang варианта? Подозреваю что фильтры применяться после того как сгенерируются пары, то есть неэффективно. M>>Это я постараюсь в течение дня посмотреть. Знаю пока то, что они разворачиваются в функции с паттерн матчингом и tail-recursion: http://www.erlang.org/doc/efficiency_guide/listHandling.html#id67562 EP>Это скорей всего сахар для монады List, или аналога — и тут как раз важно чтобы guard был как можно раньше, чтобы сразу отсечь лишние ветки.
В общем, прогнал я через компилятор, чтобы он выдал мне так называемый Core Erlang. По сути, разворачивается во вложенный цикл, и проверка идет для каждого элемента. То есть не после того, как пары сгенерированы, а во время генерации пар
Изначальный код
-module(lc).
-export([lc/0]).
lc() ->
[{X, Y} || X <- lists:seq(1, 5), Y <- lists:seq(1, 5), X rem 2 == 0, Y rem 2 == 1 ].
compile(lc, to_core):
Скрытый текст
module 'lc' ['lc'/0,
'module_info'/0,
'module_info'/1]
attributes []
'lc'/0 =
%% Line 5
fun () ->
%% Line 6
( letrec
'lc$^0'/1 =
fun (_cor10) ->
case _cor10 of
<[X|_cor1]> when 'true' ->
( letrec
'lc$^1'/1 =
fun (_cor11) ->
case _cor11 of
<[Y|_cor4]>
when try
let <_cor5> =
call 'erlang':'rem'
(X, 2)
in let <_cor6> =
call 'erlang':'=='
(_cor5, 0)
in let <_cor7> =
call 'erlang':'rem'
(Y, 2)
in let <_cor8> =
call 'erlang':'=='
(_cor7, 1)
in call 'erlang':'and'
(_cor6, _cor8)
of <Try> ->
Try
catch <T,R> ->
'false' ->
let <_cor12> =
apply 'lc$^1'/1
(_cor4)
in ( [{X,Y}|_cor12]
-| ['compiler_generated'] )
( <[Y|_cor4]> when 'true' ->
apply 'lc$^1'/1
(_cor4)
-| ['compiler_generated'] )
<[]> when 'true' ->
apply 'lc$^0'/1
(_cor1)
( <_cor11> when 'true' ->
( primop 'match_fail'
({'function_clause',_cor11})
-| [{'function_name',{'lc$^1',1}}] )
-| ['compiler_generated'] )
end
in let <_cor9> =
call 'lists':'seq'
(1, 5)
in apply 'lc$^1'/1
(_cor9)
-| ['list_comprehension'] )
<[]> when 'true' ->
[]
( <_cor10> when 'true' ->
( primop 'match_fail'
({'function_clause',_cor10})
-| [{'function_name',{'lc$^0',1}}] )
-| ['compiler_generated'] )
end
in let <_cor2> =
call 'lists':'seq'
(1, 5)
in apply 'lc$^0'/1
(_cor2)
-| ['list_comprehension'] )
'module_info'/0 =
fun () ->
call 'erlang':'get_module_info'
('lc')
'module_info'/1 =
fun (_cor0) ->
call 'erlang':'get_module_info'
('lc', _cor0)
end
Здравствуйте, Mamut, Вы писали:
M>>>Что меняет yield? EP>>Позволяет вынести генерацию ленивого списка в отдельную функцию, в которой можно всё внятно расписать. M>Внезапно откуда-то появились ленивые списки
А не от ленивого не так много толку — его можно и обычными циклами расписать. Структурно будет практически тоже самое.
M>В общем, прогнал я через компилятор, чтобы он выдал мне так называемый Core Erlang. По сути, разворачивается во вложенный цикл, и проверка идет для каждого элемента. То есть не после того, как пары сгенерированы, а во время генерации пар
Я о другом. После беглого взгляда — там ведь идёт проверка для каждой пары. Вот сколько раз у тебя берётся остаток от X-ов?
Здравствуйте, Sheridan, Вы писали:
S>Здравствуйте, _NN_, Вы писали:
_NN>>Даже в языках где отступы не обязательны, код без них не читаем. S>Полностью и категорически согласен. S>Но питон пошел еще дальше. В итоге получается похоже на поездку к бабушке с "СПАСИБО, бабушка, не надо больше еды!!"
Проблема больше чем надуманна.
Редакторы умеют всё делать нормально.
Возможно любимый nano не умеет, но редактировать в нём код по любому не очень удобно.
Для примера взять язык без отступов , скажем в том же C# инструменты типа Resharper-а форматируют всё с отступами и при написании кода не дают писать без них.
EP>А не от ленивого не так много толку — его можно и обычными циклами расписать. Структурно будет практически тоже самое.
Куда-то разговор ушел не в ту степь.
[List comprehensions в Питоне:] Слишком многословно, из-за чего все, что сложнее [x*x for x in list] становится нечитаемым, а создание сколько-нибудь сложных comprehension'ов — нетривиальным.
Здесь нет ни слова про ленивость или возможность расписать циклами.
M>>В общем, прогнал я через компилятор, чтобы он выдал мне так называемый Core Erlang. По сути, разворачивается во вложенный цикл, и проверка идет для каждого элемента. То есть не после того, как пары сгенерированы, а во время генерации пар
EP>Я о другом. После беглого взгляда — там ведь идёт проверка для каждой пары. Вот сколько раз у тебя берётся остаток от X-ов?
А какая семантика у Erlang варианта? Подозреваю что фильтры применяться после того как сгенерируются пары, то есть неэффективно.
Нет. Фильтры применятся не после того как сгенерируются пары.