LINUX.ORG.RU

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


0

0

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

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

> > Какие могут быть вообще сравнения haskell с C++, если в последнем нельзя написать 2 функции с 1 сигнатурой но разными возвращаемыми значениями?

> Не понял, зачем это нужно? На пальцах объясни, или дай ссылку.

> До недавнего времени нельзы было иметь const T1 f(T2) одновременно с 
> T1 f(T2) -- это конечно неприятно (как стало в С++0х -- не знаю).

С const - хрен с ним. Это меня мало интересует (тем более это имеет смысл при только возврате
константных/неконстантных ссылок - это поддерживается текущим стандартом C++).

Больше интересует _нормальная_ параметризация.

Я могу написать
    template <class T> void f(const T &);
, но не могу
    template <class T> T f(void);
хотя казалось бы - причем здесь наследие C ? :]

Использовать это можно - и используется в более других языках.
Оно ж понятнее, чем
    template <class T> T f(T unused_shit_here_);

Пример на haskell: вызов полиморфной по возвращаемому параметру функции.

Prelude Data.Word> (maxBound, maxBound, maxBound) :: (Word8, Word16, Word32)
(255,65535,4294967295)

Посмотрите как "изящно" решают это во внутренностях STL:
* вводя во всякие *_traits целочисленные константы. А чтобы всунуть float или более сложную константу
(хотя-бы, чтобы сымитировать maxBound для non-integral типов) начинается веселье:
* раздувая прототип функции добавляя туда фиктивный полиморфный параметр

После таких "штучек" написанный код можно использовать только в рамках нагороженных костылей
(потому, что мало кто читает умные книжки :] и потому, что они решают проблемы C++, а не поставленную задачу).
Мало того - оно потом хрен везде компилится, но это уже совсем другая история :]

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

А потом осильте RWH: http://book.realworldhaskell.org/read/ , чтобы не писать впредь про "испорченность функциональной парадигмой" :]

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

> Больше интересует _нормальная_ параметризация. Я могу написать template <class T> void f(const T &); но не могу template <class T> T f(void); хотя казалось бы - причем здесь наследие C ?

Ты так и не объяснил 2 вещи:

1. зачем такое надо?

2. как компилятор будет вычислять (выводить) Т?

> Посмотрите как "изящно" решают это во внутренностях STL: * вводя во всякие *_traits целочисленные константы.

Разве *это*? Где пример? (по-моему совсем не это!)

З.Ы. А я-то надеялся что-то новое услышать...

З.Ы.Ы. А я нигде не говорил, что STL изящна, скорее наоборот

_____________________________________

Жду нормальный пример.

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

> А чтобы всунуть float или более сложную константу (хотя-бы, чтобы сымитировать maxBound для non-integral типов) начинается веселье: * раздувая прототип функции добавляя туда фиктивный полиморфный параметр

Так это типично функциональный дибилизм^W прием -- вместо заведения локальной *изменяемой* переменной раздуть прототип функции :-) (да, а потом требовать tail recursion elimination, гы-гы-гы)

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

> Так это типично функциональный дибилизм^W прием -- вместо заведения локальной *изменяемой* переменной раздуть прототип функции :-) (да, а потом требовать tail recursion elimination, гы-гы-гы)

Нормальные люди оборачивают это в монаду State и живут припеваючи.

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

> > А чтобы всунуть float или более сложную константу (хотя-бы, чтобы сымитировать maxBound для non-integral типов) начинается веселье: * раздувая прототип функции добавляя туда фиктивный полиморфный параметр

> Так это типично функциональный дибилизм^W прием -- вместо заведения локальной *изменяемой* переменной раздуть прототип функции :-) (да, а потом требовать tail recursion elimination, гы-гы-гы)

Причем тут рекурсия? Это ж статика шаблоннаю :] Откуда тут вообще рантайм? И элиминировать там нихера не надо - абы вычислилось.
А вообще в g++ уровень вложенности инстанцирования - пицот (500).

Но рекурсивная статика - это тоже весело.

Обычный вызов обычной статической полиморфной функции.

float maxBound();
int maxBound();

template <class T> half_of_max() {
    return (T)maxBound() / 2;
}

double a = (float)half_of_max();

Хреновый пример? Напишите работающий - и вы увидите как "красив" C++.
Если мало будет - могу ткнуть в "красавцев" из STL.

Про раздувание и дЕбилизм - ниасилил. Хочется переменной в haskell - заюзайте State. Она действительно простая, очень простая.

sf ★★★
()
Ответ на: комментарий от 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 ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

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

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

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

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

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

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

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

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

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

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

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