LINUX.ORG.RU
ФорумTalks

Ну почему люди используют столь отстойные языки?!


0

0

Показали нам однажды на лекции пример макроопределения.

#define MIN(x,y) ((x) < (y) ? (x) : (y))

Ежу, читавшему On Lisp, понятно, что пример бажный (может произойти 
множественное вычисление аргументов). При этом, в мануале по cpp 
написано, что в стандартном С такой баг пофиксить невозможно.

На лиспе корректное определение выглядит так

(defmacro my-min (x y)
  (let ((x1 (gensym))
	(y1 (gensym)))
    `(let ((,x1 ,x)
	   (,y1 ,y))
       (if (< ,x1 ,y1)
	   ,x1
	   ,y1))))


А еще и говорят, что на С даже ногу можно прострелить... :/ А каком
 простреле ноги может идти речь, если даже с элементарными задачами 
язык справится не может?

Что тут ещё сказать можно... В фортунки чтоль...

Keiko
()

ПальцЫ в дверь проходить не мешают?

suser
()

Все упирается в кривизну рук и только. Если не умеешь пользоваться С - не пользуйся.

Shaman007 ★★★★★
()

ну ты даешь, сравнил жопу с пальцем

С и лисп совершенно разные языки

JB ★★★★★
()

> в стандартном С такой баг пофиксить невозможно.

В стандартном какого года?
Используйте inline-функции на здоровье!
Не нравиться что нужно ещё определить типы аргументов и вычисляемого значения?
Ну, тогда извините -- C не решает за программиста какой тип, где использовать, а чтобы избежать "множественного вычисления аргументов" необходимо сохранить результат вычисления в переменной заранее неизвестного типа.
А что касается "может" -- то ведь может и не произойти -- кто знает что там компилятор может творить?

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

> Все упирается в кривизну рук и только. Если не умеешь пользоваться С - не пользуйся.

Хорошо, как по твоему можно предотвратить множественное вычисление аргументов в макросах?

nsav-ng
() автор топика

Ответ простой: потому что забыли у тебя спросить

anonymous
()

>#define MIN(x,y) ((x) < (y) ? (x) : (y))

Справедливости ради стоит отметить, что это проблема не C а его стандартного "препроцессора", который действительно _чрезвычайно_ убог, и его используют, пожалуй, гораздо реже лиспа.

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

> Используйте inline-функции на здоровье!

Да, в данном примере это выход, но иногда функцию использовать невозможно.

Я не знаю точно, но преподша сказала, что этот макрос так определен в стандартных хедерах. Может и наврала, но если так, то это вообще 3.14здец...

> А что касается "может" -- то ведь может и не произойти -- кто знает что там компилятор может творить?

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

nsav-ng
() автор топика

А если учесть, что

> (defmacro my-min (x y) (let ((x1 (gensym))(y1 (gensym))) `(let ((,x1 ,x) (,y1 ,y)) (if (< ,x1 ,y1) ,x1 ,y1))))

на хаскеле выглядит примерно как

my_min a b | a < b = a

otherwise = b

становится непонятным, зачем так много людей используют Lisp:-}

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

> Она права.

Значит, в стандартных сишных хедерах определен бажный макрос. Что и требовалось доказать. Всем спасибо.

nsav-ng
() автор топика
Ответ на: комментарий от nsav-ng

> Значит, в стандартных сишных хедерах определен бажный макрос.

Вот. Будет о чем поговорить с симпатичной аспиранткой на защите лабораторок. Она вроде как любит этот недоязычок :))

nsav-ng
() автор топика
Ответ на: комментарий от Shaman007

Я тебе задал конкретный вопрос, а ты меня воспитывать начинаешь. Я ж даже пока еще флеймить не начал :)

Насколько я понял, проблема все же нерешаема.

nsav-ng
() автор топика

Хих :) А ты бесик попробуй, эта ваще супер язык :)))

Slackofil
()
Ответ на: комментарий от nsav-ng

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

Если тебе не к чему прицепится в С/C++, ты так и скажи.

Keiko
()
Ответ на: комментарий от nsav-ng

>>проблема все же нерешаема

Это не проблема. Проблема - это методы оптимизации интерополяции б-сплайнами. Кончай тусится в своём узком мирке. Такие "проблемы" нах никого не волнуют.

Keiko
()
Ответ на: комментарий от nsav-ng

Не надо пользоваться препроцессором для этих целей - и ваши нервы будут насыщены сератонином :-) И попытайся не употреблять слово "быдлоязычёк".

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

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

> Кончай тусится в своём узком мирке.

С чего ты взял, что мои интересы ограничиваются лишь сравнением макросистем различных ЯП?

nsav-ng
() автор топика
Ответ на: комментарий от nsav-ng

>>Если смотреть на звезды сидя на голой земле, то через пару недель заболеешь гемморроем и будет уже не до звезд :)

Моск вялый, рассшифруй плз.

>>С чего ты взял, что мои интересы ограничиваются лишь сравнением макросистем различных ЯП?

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

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

> Моск вялый, рассшифруй плз.

Задумываясь о высоком и вечном надо не забывать о том, на чем сидишь. Иначе потом будет не до высокого и до вечного.

nsav-ng
() автор топика
Ответ на: комментарий от Keiko

> Потому что, как я уже сказал, это не проблемы, а так, мелкие недостатки.

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

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

nsav-ng
() автор топика
Ответ на: комментарий от nsav-ng

макры... макры... макры ... Я уже говорил, меня больше математика обработки изображений интересует. Как например это будет на LISP'e ? Просто интересно.

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

> Я уже говорил, меня больше математика обработки изображений интересует.

Математика она и в африке математика. ЯП тут не причем.

> Как например это будет на LISP'e ? Просто интересно.

Что конкретно?

nsav-ng
() автор топика
Ответ на: комментарий от nsav-ng

ну вот скажем фильтр

void spread(const image &im, u32 amount)
{
    if(!checkImage(im) || im.w < 3 || im.h < 3)
        return;

    rgba *n = new rgba [im.w * im.h];

    if(!n)
        return;

    s32 quantum;
    s32 x_distance, y_distance;

    rgba *_rgba = (rgba *)im.data;

    memcpy(n, im.data, im.w * im.h * sizeof(rgba));

    quantum = (amount+1) >> 1;

    rgba *p, *q;

    for(s32 y = 0;y < im.h;y++)
    {
        q = n + im.w*y;

        for(s32 x = 0;x < im.w;x++)
        {
            x_distance = x + ((rand() & (amount+1))-quantum);
            y_distance = y + ((rand() & (amount+1))-quantum);
            x_distance = F_MIN(x_distance, im.w-1);
            y_distance = F_MIN(y_distance, im.h-1);

            if(x_distance < 0)
                x_distance = 0;

            if(y_distance < 0)
                y_distance = 0;

            p = _rgba + y_distance*im.w;
            p += x_distance;

            *q++ = (*p);
        }
    }

    memcpy(im.data, n, im.w * im.h * sizeof(rgba));

    delete [] n;
}


?

Keiko
()

> ожет произойти множественное вычисление аргументов

Пример если можно ? Что-то никак не осмыслю в чем проблема ..

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

>Кончай тусится в своём узком мирке.

И правда, биоробот он какой-то. :)

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

Не осилил :( Да и надо на весь код глядеть, а не на отдельную часть.

Если у тебя есть время, то прочитай введение из книги OnLisp. Там довольно неплохо рассказано про bottom-up дизайн, макры и т. п.

nsav-ng
() автор топика
Ответ на: комментарий от nsav-ng

>> а не на отдельную часть

это законченная, работающая функция.

image - это структура, где unsigned char *data, int w, int h
rgba - структура unsigned char r, g, b, a
s32 - int
u32 - unsigned int

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

> Пример если можно ? Что-то никак не осмыслю в чем проблема ..

#include <unistd.h>

int
foo(int n)
{
    sleep(n);
    return 10;
}

...
int a=20;
int b;
b=min(a,foo(a));

Сколько проспит программа при таком вызове?

nsav-ng
() автор топика
Ответ на: комментарий от Keiko

> это законченная, работающая функция.

Я понимаю, но все равно надо смотреть на весь код, для того, чтоб выделить нужные шаблоны, которые можно было бы заменить макрами. Именно тогда раскроется вся красота лисповских макросов. Дальше отсылаю тебя к OnLisp'у дабы потом меня не обвинили в плагиате умных мыслей.

nsav-ng
() автор топика
Ответ на: комментарий от Keiko

Отвратительно раздутый, нечитабельный код. Типичная поделка косолапого сишника...

anonymous
()

>#define MIN(x,y) ((x) < (y) ? (x) : (y))

>(defmacro my-min (x y) (let ((x1 (gensym)) (y1 (gensym))) `(let ((,x1 ,x) (,y1 ,y)) (if (< ,x1 ,y1) ,x1 ,y1))))

Мне например, первая запись гораздо понятнее, чем вторая (и я не одинок). В этом основная причина малораспостраненности Лиспа.

ps Макросы в С и макросы в Лисп --- две большие разницы, применение у них разное. Без макросов С может и обойтись (это по возможности даже желательно), Лисп без макросов несколько убог, чтоли :)

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

> Мне например, первая запись гораздо понятнее, чем вторая (и я не одинок).

Так они делают совершенно разные вещи. Первая - неправильная, в отличии от второй. Аналог первой на Лиспе будет такой:

(defmacro my-min (x y) `(if (< ,x ,y) ,x ,y))

> В этом основная причина малораспостраненности Лиспа.

Чушь бредишь. Тебе будет непонятна запись на любом неизвестном тебе языке. Так что ты просто заявил, что Лисп нераспространён потому, что его никто не знает. Тавтология-с.

> Лисп без макросов несколько убог, чтоли :)

Лисп без макр - это Схема. Не то чтобы очень убого - у Лиспа хватает и других средств абстракции, кроме макр.

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

> Мне например, первая запись гораздо понятнее, чем вторая (и я не одинок). В этом основная причина малораспостраненности Лиспа.

Первая запись неправильна. Поэтому ее понятность ни о чем не говорит. Вторая запись понятна всем, кто знаком с макросами в лиспе.

> Лисп без макросов несколько убог, чтоли :)

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

В СИ такой фокус не прокатит. Для добавления новых конструкций необходимо модифицировать компилятор :)

nsav-ng
() автор топика
Ответ на: комментарий от unDEFER

> А причём здесь макросы и "множественное вычисление аргументов"?

Ну это тебе домашнее задание. Подумай, почему loop нельзя реализовать как функцию. Если додумаешься, то подумай, в каких случаях макросы нельзя заменить функциями.

Множественное вычисление -- это один из недостатков макросов. Макросы гораздо сложнее функций, поэтому применять их надо лишь тогда, когда применить функцию нельзя, либо это приведет к потере эффективности.

nsav-ng
() автор топика

Пациент: Знаете доктор, когда я делаю вот так, то у меня вот тут болит.
Доктор: А вы так не делайте.

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

> Лисп без макр - это Схема

Там есть макры, но они убогие. Правда, предохраняют от дурацких ошибок.

nsav-ng
() автор топика
Ответ на: комментарий от nsav-ng

> Для добавления новых конструкций необходимо модифицировать компилятор :)

По сути макры - и есть расширение компилятора.

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

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

> Для Си никто не мешает тоже приделать более умный макропроцессор.

> Лисп тут лучше прочих только по той причине, что построен на S-выражениях, а всем другим приходится с текстовым представлением возиться

Таки мешает что-то приделать нормальный препроцессор. :)

nsav-ng
() автор топика
Ответ на: комментарий от nsav-ng

> Ну это тебе домашнее задание.
Ты мне не учитель, так не фиг.

> Подумай, почему loop нельзя реализовать как функцию.
А чем тебя здешний for не устраивает?

> Если додумаешься, то подумай, в каких случаях макросы нельзя заменить функциями.

Угу, вот в таких нельзя:

int variable_with_long_name_a;
int variable_with_long_name_b;

#define MIN(a,b) (variable_with_long_name_/**/a<variable_with_long_name_b)?variable_with_long_ name_/**/a:variable_with_long_name_/**/b;

Но тогда можно просто написать:

inline int min(int a, int b) {return (a<b)?a:b;}
#define MIN (a,b) min(variable_with_long_name_/**/a, variable_with_long_name_/**/b)

> поэтому применять их надо лишь тогда, когда применить функцию нельзя,

Ну, вот и не используй.

Но ты так и не привёл примера.
Самый первый твой пример являлся макросом на C с возможным множественным вычислением. Второй должен быть таким же.

unDEFER ★★★★★
()
Ответ на: комментарий от nsav-ng

> Ну это тебе домашнее задание. Подумай, почему loop нельзя реализовать как функцию. Если додумаешься, то подумай, в каких случаях макросы нельзя заменить функциями.

loop можно орагизовать и как функцию или квотирование в лиспе уже отменили ? Эффективность такого решения - вопрос другой. Да и вообще нормалный порядок редукции рулит ибо там с этими вопросами заморачиваешься по минимому

GameMagister
()
Ответ на: комментарий от nsav-ng

А, понял. Ну а если взять другой пример где такой результат ожидается ? Или если не ожидается то вроде как ничто не мешает этого предусмотреть, на лиспе вон тоже такое смастерить возможно.

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