LINUX.ORG.RU

Зачем нужны динамические языки?


0

0

Собственно не пойму. Вроде обещают более быструю разработку, но за счет чего? За счет того, что не надо писать тип при объявлении переменной? Так это ведь глупость, никакой скорости разработки это не добавит. Естественно, такие языки можно использовать только для прототипирования, но не проще ли сразу использовать язык, который обеспечит и скорость разработки и скорость выполнения, тем более, что динамический язык принципиально нельзя ускорить (имеется ввиду компилятор)? (я имею ввиду современные языки с выводом типов)

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

Как насчет вложенной quasiquote?
Там вообще позволено раскрываться в другие "макросы"?
А порядок вычисления?
А перекрывание внешних имен? Или такая же "гигиена", как в Scheme?
А если я намеренно захочу захватить имя?
Как оперировать символами и создавать новые?

guest-3484-2009
()
Ответ на: комментарий от guest-3484-2009

Соответственно, как интернить имена в другие пакеты?
Как я понял, "макросы" там не могут создавать абстракции модулями и типами.
Есть ли макросимволы? Есть ли локальные макросы? Есть ли ридер-макросы?

guest-3484-2009
()

Подозреваю, что нет.
А примеров не будет, пока.
Это вы лучше напишите once-only попробуйте.

(defmacro once-only ((&rest names) &body body)
  (let ((gensyms (loop for n in names collect (gensym))))
    `(let (,@(loop for g in gensyms collect `(,g (gensym))))
      `(let (,,@(loop for g in gensyms for n in names collect ``(,,g ,,n)))
        ,(let (,@(loop for n in names for g in gensyms collect `(,n ,g)))
           ,@body)))))

Кстати, как я понял, так как в хаскеле нет чего-то вроде &rest, то в "макросах" его тоже нет?
Соответственно, как обходить это?
Пример простенького with- макроса напишите:

(defmacro with-open-file ((var &rest open-args) &body body)
    (let ((,var (open ,@open-args)))
       (unwind-protect 
           (progn ,@body)
           (close ,var))))

guest-3484-2009
()
Ответ на: комментарий от guest-3484-2009

>Это вы лучше напишите once-only попробуйте

а можно для начала объяснить что оно делает? я не настолько хорошо знаю CL чтобы свободно это прочитать

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

кратко - гарантирует, что ни одно внешнее имя не будет захвачено символами из внутренних макросов.
В него иногда заворчивают другие макросы, если лень руками писать (gensym ...)

guest-3484-2009
()
Ответ на: комментарий от sf

> Хреновый пример? Напишите работающий - и вы увидите как "красив" C++.

Вполне нормально пишется. Просто вы его не умеето готовить. 
(Макросы тут стоят только для увеличения читабельности и не мешают типобезопасности)

// g++ test2.cxx && ./a.out
// output:
// int:2000111333 float:1e+33 char*:max_bound sizeof(test):127

#include <iostream>

template<typename T> T max_bound() { return T(); } /* g++ умеет тут выводить юзерскую ошибку*/

#define SET_MAX_BOUND(T,val) template<> T max_bound<T>() { return val; }
#define maxbound(T) max_bound<T>()

SET_MAX_BOUND(char, 127)
SET_MAX_BOUND(int, 2000111333)
SET_MAX_BOUND(float, 1e33)
SET_MAX_BOUND(char*, "my_max_bound")

int main()
{
    char test[maxbound(char)];
    std::cout << " int:" << maxbound(int) << " float:" << maxbound(float)
              << " char*:" << maxbound(char*) << " sizeof(test):" << sizeof(test) << '\n';
    return 0;
}

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

> В лисповой программе можно взять текст (функции), откомпилировать его, встроить машинный код в этот же образ (адресное пространство) и тут же вызвать. Это называется рантаймной генерацией кода. Я уже не знаю, как это проще объяснить.

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

Но если ты ОЧЕНЬ этого хочешь - GHC API тебе в руки. В частности, GHCi именно что компилирует на лету.

Miguel ★★★★★
()
Ответ на: комментарий от guest-3484-2009

> Кстати, как я понял, так как в хаскеле нет чего-то вроде &rest, то в "макросах" его тоже нет?

"&rest" - это такой убогонький способ реализации полиморфизма, который как бэ говорит "ну не шмогла я".

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

Вот так Лисп и обсирают, не понимая, что он из себя представляет... Зачем спорите, если предметом спора не владеете?

mv ★★★★★
()

>Вроде обещают более быструю разработку, но за счет чего?

Ну, например так. Есть таблица в БД. Нужно написать ORM-обвязку к ней.

В php я напишу только:

class forum_topic extends base_object_db
{
    function main_table() { return 'forum_topics'; }
    function main_table_fields()
    {
        return array(
            'id', 'title', 'create_time' => 'posted', 'forum_id',
        );
    }
}

Всё. Дальше могу использовать:

$topic = object_load('forum_topic', 12345);

echo $topic->title();

...

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

Писанины только на одном описании объекта будет больше в 3-4 раза.

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

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

Зря стараешься. Кто понимает, тот молча водку пьёт. Кто не понимает, тот... Ну не понимает, что толку попу рвать, объяснять? :) (Пусть (дальше (считают (Лисп (просто (языком (скобок)))))))

mv ★★★★★
()

Таки я начинаю верить в диагноз доктора den73 о монадизме головного мозга. Сиё расстройство блокирует у больного способность хотя бы по верхам прочитать в гугле или википедии информацию об аргументах, которые приводят оппоненты.

Чёрт, верните анонимусов на ЛОР... Они хоть безликие...

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

Никто ж не спорит, что лисповский eval в хаскеле к счастью не заменишь :]

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

Классно! Фиг с ним с явным указанием <параметра> :]

А можно еще добавить пример частичной специализации? Чтобы для любых const T * возвращало 0?

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

> Если бы я это писал на статическом языке, мне бы пришлось заранее в классе описывать все поля, сеттеры, геттеры к ним и привязку полей БД к полям класса. Писанины только на одном описании объекта будет больше в 3-4 раза.

Ничего подобного. Пишешь перловый скрипт из 5 строк, он тебе достает схему базы данных и из нее генерит классы. А дальше:

class topic: public perl_generated_topic { string output() { return ...... ;} };

причем в отличие от РНР не надо писать ненужное слово this и заодно и этот файл можно препроцессировать однострочником на перле, чтобы $var внутри строк превращалось в то, что надо.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от guest-3484-2009

> &rest это последний аргумент вариабельной длины.

Именно. То есть - средство одновременной реализации функций от различного числа аргументов. Иначе говоря - кособокой версии полиморфизма. Учи матчасть.

Кстати, в том же Хаскеле функции с разным числом аргументов делаются на раз.

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

> Вот так Лисп и обсирают, не понимая, что он из себя представляет... Зачем спорите, если предметом спора не владеете?

Иди учись. Может быть, тебе объяснят старшие, что подобная техника в ЛИСПе - last resort.

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

> Если бы я это писал на статическом языке, мне бы пришлось заранее в классе описывать все поля, сеттеры, геттеры к ним и привязку полей БД к полям класса.

Ещё раз: статическая типизация - далеко не всегда равняется плюсовому убожеству.

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

>Ещё раз: статическая типизация - далеко не всегда равняется плюсовому убожеству.

Ну да, на Форте такое тоже можно реализовать, расширяя классы в рантайме. Только писать задолбаешься :) В принципе, даже на Java через какой-нибудь asm сделать можно. Но всё это - нетипичные решения для таких языков и требуют больших накладных расходов при программировании.

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

>То есть - средство одновременной реализации функций от различного числа аргументов.
Нет, это средство реализации одной функции с различным числом аргументов.
Например, такова функция +
(+ 1 2)
(+ 1 2 3)
(+ 1 2 3 4 5 6 ...)
>Кстати, в том же Хаскеле функции с разным числом аргументов делаются на раз.

Вы не про "паттерн матчинг"? Ну это совсем замечательно - вместо одной функции пишем десять, по количеству дополнительных аргументов.
Или может про карринг(или как это там)?
Еще лучше - нагородим по созданию и вызову функции на каждый аргумент и сидим наддемся на конпелятор - авось оптимизирует такой говнокод.

Полиморфизм тут вообще никаким боком.
Полиморфизм это обобщенные функции.

guest-3484-2009
()
Ответ на: комментарий от sf

> А можно еще добавить пример частичной специализации? Чтобы для любых const T * возвращало 0?

Завтра разберусь... но мне сдается, что придется все-таки прилепить лишний параметр.

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

Скорее всего придется. Еще хуже с двойной частичной специализацией (Обычно надо сконвертить один тип в другой) - там точно придется вкатить 2й параметр. Для похожих вещей используется iterator_type_tag в __advance в stl.

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

> Ещё раз: статическая типизация - далеко не всегда равняется плюсовому убожеству.

А можно ли в хаскеле типы параметризовать натуральными числами без извращений вида succ(succ(succ()))? Чтобы сделать допустим тензор статически известного ранга (n,m), чтобы компилятор ругался при сложении тензоров разного ранга?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от guest-3484-2009

> Например, такова функция +
> (+ 1 2)

> (+ 1 2 3)

> (+ 1 2 3 4 5 6 ...)


> Полиморфизм тут вообще никаким боком.

> Полиморфизм это обобщенные функции.


В хаскеле есть функции работы со списками :]. Правда в них просто так не засунешь нетипизированный хлам.

Prelude> sum [1..100] -- дружно закрываем глаза на нестрогость sum
5050

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

> Скорее всего придется. Еще хуже с двойной частичной специализацией

Тогда напиши 2 примера на хаскеле (или дай ссылку).

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от guest-3484-2009

> Нет, это средство реализации одной функции с различным числом аргументов.

Терминологическая разница.

> Вы не про "паттерн матчинг"?

Нет, конечно.

> Еще лучше - нагородим по созданию и вызову функции на каждый аргумент и сидим наддемся на конпелятор - авось оптимизирует такой говнокод.

И заоптимизирует, причём с лёгкостью. В Хаскеле вызов функции - очень часто чрезвычайно дешёвая операция, гораздо дешевле, чем даже в C.

> Полиморфизм тут вообще никаким боком.

У лиспников очень часто наблюдается непонимание, что такое "полиморфизм" вообще.

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

> А можно ли в хаскеле типы параметризовать натуральными числами без извращений вида succ(succ(succ()))?

Без Template Haskell - нет, нельзя. Ну, или, опять же, очень аккуратно описать экзистеншиалсами.

Можно сделать почти десятичную систему - D1(D2(D3())) вместо 123.

> Чтобы сделать допустим тензор статически известного ранга (n,m), чтобы компилятор ругался при сложении тензоров разного ранга?

А зачем тебе тогда руками прописывать succ(succ...? Пусть компилятор сам понимает.

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

> Правда в них просто так не засунешь нетипизированный хлам.

HList, если очень хочется.

Miguel ★★★★★
()
Ответ на: комментарий от guest-3484-2009

> Полиморфизм тут вообще никаким боком. Полиморфизм это обобщенные функции.

Дельта-функция Дирака полиморфна!? о_0

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

> Можно сделать почти десятичную систему - D1(D2(D3())) вместо 123.

Ты еще попробуй напиши со своим D1(D2(D3())) аналог

template<int a, int b> T<a*b> operator* (T<a>, T<b>) {.....}

Особенно весело будет смотреть, как ты будешь реализовывавть код для умножения D7(D8(D3)) на D5(D6). (Т -- это тип для примера, а не тензор).

Так что не надо рассказывать про "плюсовое убожество".

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

Если надо - сделать несложно. Другой вопрос - зачем? Как мы уже выяснили, для тех же тензоров явно писать ранг не нужно.

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

> как ты будешь реализовывавть код для умножения D7(D8(D3)) на D5(D6)

Кстати, это вообще делать никто никогда не будет. Максимум, что будет сделано руками - таблица умножения Di на Dj. А дальше пойдёт реализация алгоритма умножения в столбик.

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

> Если надо - сделать несложно. Другой вопрос - зачем? Как мы уже выяснили, для тех же тензоров явно писать ранг не нужно.

C чего это вдруг? Я хочу например нулевой тензор ранга (3,5). Пишу:

tenzor<3,5> t=0;

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

> Кстати, это вообще делать никто никогда не будет. Максимум, что будет сделано руками - таблица умножения Di на Dj. А дальше пойдёт реализация алгоритма умножения в столбик.

Да-да, именно на все это будет весело смотреть. Тут еще можно предложить и другой варинт -- написать перевод в двоичную систему. Так что простор для размышлений и пустой траты времени -- очень большой... но вдохновлять будет, конечно, убожество плюсов, где просто пишешь T<a*b>

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

> C чего это вдруг? Я хочу например нулевой тензор ранга (3,5). Пишу:

А так ты будешь писать просто

t = nullTensor

И пусть компилятор сам понимает, какого оно ранга.

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

> но вдохновлять будет, конечно, убожество плюсов, где просто пишешь T<a*b>

...вместо того, чтобы возложить эту заботу на автомат.

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

> Сходу что в голову приходит - в лисповых ОО СУБД можно в рантайме поменять определение класса, и все готовые объекты лениво поменяются под новое определение. Вот тут, подозреваю, это во всю используется: http://franz.com/products/allegrocache/

Че-то мне не понятно, как лениво менять все объекты без жутких тормозов. Ведь это надо вставлять проверку "а не поменялось ли определение класса" на каждый вызов метода этого объекта, или как?

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

> А так ты будешь писать просто t = nullTensor И пусть компилятор сам понимает, какого оно ранга.

Не-не-не. Я написал t = nullTensor и дальше хочу отдать его функции, которая прочтет его ранг и заполнит чем-то уже в зависимости от его ранга. Короче, компилятор ранг не может определить.

Да, это по-твоему не функционально, но мне лень щас придумывать функционально. С нулевым тензором проблема -- куда его ни тки, везде получишь 0.

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

> хочу отдать его функции, которая прочтет его ранг и заполнит чем-то уже в зависимости от его ранга.

Ну и в чём, опять-таки, проблема? Тут у тебя не определение типа по числу, а определение числа по типу. Классы типов на то и придуманы.

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

> Ну и в чём, опять-таки, проблема? Тут у тебя не определение типа по числу, а определение числа по типу. Классы типов на то и придуманы.

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

Вот другой конкретный пример, слегка из другой оперы -- размерности (auto это из C++0x local type inference):

auto kilogramm=value(1,0,0);
auto metr=value(0,1,0);
auto second=value(0,0,1);
auto m1=1*kilogramm;
auto m2=2*kilogramm;
auto m3=m1+m2;
auto g = 10*metr/(second*second); // или Value<0,1,-2> g = 10*metr/(second*second); если без с++0х
auto E=m3*g*h;
auto x=m3+E; <--- вот тут будет ошибка компиляции

Тоже ведь не шибко удобно с классами типов?

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

> auto x=m3+E; <--- вот тут будет ошибка компиляции

Библиотека dimensional. Есть в Hackage. Я не смотрел, как она сделана, но примерно это она и делает.

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

>И заоптимизирует, причём с лёгкостью. В Хаскеле вызов функции - очень часто чрезвычайно дешёвая операция, гораздо дешевле, чем даже в C.
Это высказывание того же плана, что и то, которое утверждает что std::vector быстрее []. Курам на смех.
>У лиспников очень часто наблюдается непонимание, что такое "полиморфизм" вообще.

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

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