Re[5]: ЧАСТЬ 5: жизнь без препроцессора
От: c-smile Канада http://terrainformatica.com
Дата: 14.05.05 05:03
Оценка: 3 (1)
Здравствуйте, FR, Вы писали:

FR>Но с другой стороны inline функции более закрыты (вход параметры выход тоже один) а необдуманое использование миксинга может дать малопонятные побочные эффекты, то есть в миксинге сохраняются не только достоинства но и не достатки макросов.


В принципе да, но

№1:

A mixin has its own scope, even if a declaration is overridden by the enclosing one:


        int x = 4;

    template Foo()
    {
        int x = 5;
        int bar() { return x; }
    }

    mixin Foo;

    void test()
    {
        printf("x = %d\n", x);        // prints 4
        printf("bar() = %d\n", bar());    // prints 5
    }


И №2 подмешивание кода с помощью mixin это
достаточно редкое явление.
Собственно как и любая ручная оптимизация она требует
особого внимания.
Но зато эффективно.
Re[4]: ЧАСТЬ 5: жизнь без препроцессора
От: c-smile Канада http://terrainformatica.com
Дата: 14.05.05 05:11
Оценка: 9 (3)
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, AndrewVK, Вы писали:


AVK>>Здравствуйте, eao197, Вы писали:


E>>>Зря он так предполагает

E>>>Например, при логировании __FILE__ и __LINE__ здорово помогают. Как и макросы, кстати.

AVK>>Еще один важный кусок задач — кодогенераторы.


E>Да, я тоже хотел об этом сказать. Но поскольку в исходном сообщении ЗХ не было упомянута директива #line, то решил об этом не говорить. К тому же, при желании, кодогенераторы могут сами подсчитывать номера строк в генерируемом коде Хоть это и геморройно.


Зверь читает доку квадратно-гнездовым образом

Есть там это все:

http://www.digitalmars.com/d/lex.html (в конце)

Special Tokens
These tokens are replaced with other tokens according to the following table:
Special Token Replaced with...
__FILE__ string literal containing source file name
__LINE__ integer literal of the current source line number
__DATE__ string literal of the date of compilation "mmm dd yyyy"
__TIME__ string literal of the time of compilation "hh:mm:ss"
__TIMESTAMP__ string literal of the date and time of compilation "www mmm dd hh:mm:ss yyyy"

Re[5]: ЧАСТЬ 5: жизнь без препроцессора
От: Зверёк Харьковский  
Дата: 14.05.05 05:25
Оценка: :)))
Здравствуйте, c-smile, Вы писали:

E>>>>Зря он так предполагает

E>>>>Например, при логировании __FILE__ и __LINE__ здорово помогают. Как и макросы, кстати.

AVK>>>Еще один важный кусок задач — кодогенераторы.


E>>Да, я тоже хотел об этом сказать. Но поскольку в исходном сообщении ЗХ не было упомянута директива #line, то решил об этом не говорить. К тому же, при желании, кодогенераторы могут сами подсчитывать номера строк в генерируемом коде Хоть это и геморройно.


CS>Зверь читает доку квадратно-гнездовым образом


CS>Есть там это все...


Тьфу блин, точно пойду повешусь. Я же это все там видел!
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
Re[5]: GC в D
От: Cyberax Марс  
Дата: 14.05.05 05:56
Оценка:
FR wrote:

> Есть вопрос, я правильно понял что GC в D основан на сишном Boehm GC?


Не только "основан", а так и есть — натуральный Boehm GC. Причем сам D
не особо приспособлен для точного сборщика мусора — в последний раз,
когда я смотрел его спеку (примерно год назад), в D была поддержка
C-подобных union'ов и еще нескольких подобных фич. Ну и еще нет
стандарта на ABI для GC, и т.п.

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re: Снова D: Зверёк читает мануал
От: Кодёнок  
Дата: 16.05.05 06:14
Оценка:
           #include <stddef> 
           struct Foo { int x; int y; }; 

           off = offsetof(Foo, y); 

The D Way
An offset is just another property:

           struct Foo { int x; int y; } 

           off = Foo.y.offset;


А как тут быть, если `y` — класс имеющий член `offset` ?
Re[2]: Снова D: Зверёк читает мануал
От: c-smile Канада http://terrainformatica.com
Дата: 16.05.05 16:21
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>
Кё>           #include <stddef> 
Кё>           struct Foo { int x; int y; }; 

Кё>           off = offsetof(Foo, y); 

Кё>The D Way
Кё>An offset is just another property:

Кё>           struct Foo { int x; int y; } 

Кё>           off = Foo.y.offsetof; 
Кё>


Кё>А как тут быть, если `y` — класс имеющий член `offsetof` ?



Компилятор скажет нечто типа
".alignof property cannot be redefined"

Что ИМХО лучше чем если ты в C++ переопредилишь offsetof()
и компилятор молча это скушает.

alignof offsetof sizeof это predefined
property names — фактически ключевые слова.
Re[3]: Снова D: Зверёк читает мануал
От: Кодёнок  
Дата: 18.05.05 11:02
Оценка:
CS>Компилятор скажет нечто типа
CS>".alignof property cannot be redefined"

CS>Что ИМХО лучше чем если ты в C++ переопредилишь offsetof()

CS>и компилятор молча это скушает.
CS>alignof offsetof sizeof это predefined
CS>property names — фактически ключевые слова.

Понятно, хотя я бы предпочёл имена _offsetof, _alignof, _sizeof, _max, _min. Зачем воровать у программиста слова

А вот еще вопрос по foreach (компилятор качается):

Зачем переменной нужен тип, это оставляет старую проблему "нужен typeof":

foreach (int x; my_integers) ;


Для читабельности это плюс, но не в случае, если контейнер определён строкой выше

Переменная цикла — ссылка на элемент контейнера, или скопированное оттуда значение?
Re[4]: ЧАСТЬ 4: синтаксический сахар, синтаксический мусор..
От: Кодёнок  
Дата: 18.05.05 11:06
Оценка:
MS>"Все кому не лень" делают это по одной простой причине — в языках имеется тип "строка". В C++ такого типа не существует. Следовательно, switch/case по строке невозможен по причине отсутствия самой строки.

switch почти аналогичен if;else if;else if;else. Что мешает в С++ задействовать оператор == и выполнять switch для объектов произвольного типа? Заодно и не только константы можно будет использовать в case-метках. А нет оператора, так выдавать ту же ошибку, что и в оперторе if().

[c]
string s;
switch (s)
{
case this->stringSample: break;
case "a": break;
default: break;
}
Re[3]: Снова D: Зверёк читает мануал
От: WolfHound  
Дата: 18.05.05 12:41
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>alignof offsetof sizeof это predefined property names — фактически ключевые слова.

Неправильный подход.
Нужно ввести одно ключевое слово meta и далие с ним можно таварить тАкое...
Например заменить им все эти predefined property names
off = Foo.y.offsetof;

на
off = meta(Foo.y).offsetof;

Если туда добавить поле type то получаем typeof
meta(x+y*z).type t = x+y*z;

Если добавить поддержку коллекций времени компиляции то можно будет делать автоматическую сериализацию както так
[serializeble]
struct Foo 
{ 
    int x; 
    int y; 
    [non_serializeble]
    int tmp; 
} 
template<class T>
void serialize(T const& val, stream& st)
{
    static assert(meta(T).attributes.contains(meta(serializeble)));
    foreach(meta field in meta(T).fields)
        if(!field.attributes.contains(meta(non_serializeble)))
            st.serialize(field.const_ref(val), field.name);
}

Ну и так далие.
И отделались всего одним ключевым словом.

Если в D будет нечто подобное то он будет представлять некоторый интерес. Иначе
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Снова D: Зверёк читает мануал
От: Зверёк Харьковский  
Дата: 18.05.05 14:45
Оценка:
Здравствуйте, Кодёнок, Вы писали:

...
Кё>Зачем переменной нужен тип, это оставляет старую проблему "нужен typeof":
...
Кстати, typeof есть
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
Re[4]: Снова D: Зверёк читает мануал
От: Кодёнок  
Дата: 20.05.05 06:51
Оценка:
CS>>alignof offsetof sizeof это predefined property names — фактически ключевые слова.
WH>Неправильный подход.
WH>Нужно ввести одно ключевое слово meta и далие с ним можно таварить тАкое...
WH>Например заменить им все эти predefined property names
WH>off = Foo.y.offsetof;
WH>на
WH>off = meta(Foo.y).offsetof;
WH>Если туда добавить поле type то получаем typeof
WH>meta(x+y*z).type t = x+y*z;

А зачем? Почему не ввести специальный тип "Foo.x":

Foo f;
typeof(f) == Foo
Foo.sizeof == ...

typeof(f.x) == int
int.sizeof == ...
int.max == ...
int.min == ...

typeof(Foo.x) == спец.тип (не int)
typeof(Foo.x).alignof == ...
typeof(Foo.x).offsetof == ...
typeof(Foo.x).type == int

Что-то вроде указателя на член класса, но в compile-time.
Re[5]: Снова D: Зверёк читает мануал
От: WolfHound  
Дата: 20.05.05 07:59
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>А зачем? Почему не ввести специальный тип "Foo.x":

хъ
Кё>Что-то вроде указателя на член класса, но в compile-time.
Ты предлагаешь частный случай моего решения.
Зачем делать частный случай если можно сделать общий?
Болие того общий случай требует меньше зарезервированных слов в языке.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[17]: ЧАСТЬ 3: Конструкторы, деструкторы, и RAII
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.05.05 00:17
Оценка:
Здравствуйте, vdim

V>Умный указатель, это "заместитель" по GoF. Все паттерны по сути — костыли, они же трюки и приемчики.


+1

V>Управление памятью в Дельфи отнимает не больше чем в С++ только в GUI.


В дельфи есть компонентная модель и дизайнеры которые позволяют размещать компоненты визуально и контролируют их срок жизни. А обертки можо делать нра IUnknown. В общем, если подходить с умом, то жить можно. Но ЖЦ конечно рулит. Тут ни плюся ни делифи и рядом не стояли.
... << RSDN@Home 1.1.4 beta 7 rev. 457>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: ЧАСТЬ 4: синтаксический сахар, синтаксический мусор..
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.05.05 00:17
Оценка: 3 (1)
Здравствуйте, McSeem2, Вы писали:

MS>"Все кому не лень" делают это по одной простой причине — в языках имеется тип "строка". В C++ такого типа не существует. Следовательно, switch/case по строке невозможен по причине отсутствия самой строки.


Понятие строки в плюсах присутствует. Причем в двух экземплярах: 1) масива символов и литералов, 2) класс std::string. Ну, а то что создатели языка не очень то озаботились удобством программистов меня лично уже давно не удевляет.

MS>C# AFAIK тоже не позволяет писать switch/case по объектам произвольного типа. А как было бы прельстиво:


MS>
MS>class Key
MS>{
MS>   Key(int i, string s);
MS>   . . .
MS>   bool operator < (const Key&) ...
MS>};


MS>. . .

MS>switch(Key(i, s))
MS>{
MS>   case Key(1, "123"):
MS>   case Key(1, "124"):
MS>   . . .
MS>}
MS>


Согласен.

Однако в общем-то проблема легко решаема:
delegat void Handler();

class Key : IComparable
{
  Key(int i, string s);
  . . .
  override GetHashCode()...
    IComparable.CompareTo(...)...
};

Dictionary<Key, Handler> _map = Dictionary<Key, Handler>();

void Init()
{
    _map[new Key(1, "124")] = delegate { ... };
    _map[new Key(1, "123")] = delegate { ... };
}

void Test(Key key)
{
    _map[key]();
}


Более того с помощью данной техниаи можно создавать декларативные фрэймворки. Например, в редакторе кода который я сделал взамен Синтилы обработка клавиатурных сокращений делается сходным обрзом. Только описание соотвествия клавиатурных сокращений и соотвествующих функция задается ХМЛ-ем. При инициализации универсальный код считывает ХМЛ-писание и инициализирует мап делегатами ссылающимися на функции контроллера. За счет рефлексии удается создать делегаты по именам и по именам же перевести строку с описанием клавиатурных сокращений в соотвествующее ей значение перечисления Keys. Вечь код короче чем это описание. Его написание заняло час. А работа с клавиатурой стала очень простой и удобной.
... << RSDN@Home 1.1.4 beta 7 rev. 457>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: ЧАСТЬ 4: синтаксический сахар, синтаксический мусор..
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.05.05 00:17
Оценка:
Здравствуйте, Зверёк Харьковский, Вы писали:

ЗХ>Кстати, да. Первое моё движение, когда я узнал про свич по строкам в Ди — "а по произвольным классам?"

ЗХ>Узнав, что нельзя, "гестапа очень ругалась".
ЗХ>Вопрос: почему нельзя? Что этому мешает? У кого-нибудь есть логичный ответ?

Думаю, косность мышления. Строки действительно используются в качестве ключей очень часто. К тому же Шапр интерпртирует их как строеннй тип (хотя это и не совсем так). Принципиальных ограничений нет.
... << RSDN@Home 1.1.4 beta 7 rev. 457>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: ЧАСТЬ 3: Конструкторы, деструкторы, и RAII
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.05.05 02:33
Оценка:
Здравствуйте, vdimas, Вы писали:


V>Со всякими scope-контоллерами подобные алгоритмы не представляют трудностей, записываются "как под диктовку". В случае try-finally мы должны либо городить новый уровень вложенности на каждый №, либо усложнять блок finally, проверяя, что мы успели создать, а что нет. Получаем скорее деструктуризацию, чем структуризацию.


Вот бы глянуть на подобный реальный код. А то реально деструкторы в 99% случаев память особождают...
... << RSDN@Home 1.1.4 beta 7 rev. 457>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: ЧАСТЬ 4: синтаксический сахар, синтаксический мусор..
От: McSeem2 США http://www.antigrain.com
Дата: 21.05.05 03:48
Оценка: 1 (1)
Здравствуйте, VladD2, Вы писали:

VD>Понятие строки в плюсах присутствует. Причем в двух экземплярах: 1) масива символов и литералов, 2) класс std::string. Ну, а то что создатели языка не очень то озаботились удобством программистов меня лично уже давно не удевляет.


Согласен с твоими выводами (нижеудалеными), но возражаю по поводу наличия в C++ типа "строка". Нет такого типа в языке. Есть только некоторые соглашения, типа "массив байтов, завершающийся нулем можно считать строкой". Ну или массив интов в случае unicode. Компилятор ничего не знает ни об strcmp, ни о std::string. Соответственно, как можно строить switch/case по неизвестному типу? Язык не навязывает того, что строка обязана завершаться нулем, например. И поэтому, надо либо вводить в сам язык строгое понятие строки, либо (что лучше) возможность строить switch/case по произвольному типу.

Далее размышляем.
Таким образом, получается, что switch/case по строкам в любом языке является лишь полумерой. Как, например, реализовать switch/case с типом Date? Есть такой тип в C#? Нету. Есть только некий класс, который компилятор интерпретирует как любой другой класс. Конечно же, это абсурд — делать switch/case по конкретным датам. Но по месяцам, по кварталам или по дням недели это очень даже не абсурд. Соответственно, для такого типа, как DateTime нужен не просто switch, нужен switch по конкретным условиям (полям — месяц, квартал, день недели, время года, etc). А это уже ничем не отличается от switch/case по произвольному типу, с некими своими операциями сравнения.

И что характерно, в том же C++ или C# это можно было бы реализовать элементарно. Достаточно такого старого понятия, как "вычисляемый goto":
Date d(2005,05,05);
label qn[] = { q1=0, q2=1, q3=2, q4=2 };
swtitch(d.quarter(), qn)
{
   default: . . .
   q1: . . .
   q2: . . .
   q3: . . .
   q4: . . .
};


Фактически, switch это и есть вычисляемый goto, но только кастрированный и неспособный к развитию И при этом — не гарантирующий какую-либо оптимизацию. Все, что можно гарантировать — это O(N) и не более того. В то время, как вычисляемый goto железно обеспечивает O(1).
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[4]: Снова D: Зверёк читает мануал
От: c-smile Канада http://terrainformatica.com
Дата: 21.05.05 06:18
Оценка:
Здравствуйте, Кодёнок, Вы писали:


Кё>А вот еще вопрос по foreach (компилятор качается):


Кё>Зачем переменной нужен тип, это оставляет старую проблему "нужен typeof":


Кё>
Кё>foreach (int x; my_integers) ;
Кё>


Кё>Для читабельности это плюс, но не в случае, если контейнер определён строкой выше


Кё>Переменная цикла — ссылка на элемент контейнера, или скопированное оттуда значение?


foreach (int x; my_integers) sum += x;
foreach (inout int x; my_integers) x = 12;


Зачем тип? для всякого разного кастинга.
Re[6]: ЧАСТЬ 4: синтаксический сахар, синтаксический мусор..
От: Шахтер Интернет  
Дата: 21.05.05 17:54
Оценка: +1
Здравствуйте, McSeem2, Вы писали:

MS>Здравствуйте, VladD2, Вы писали:


VD>>Понятие строки в плюсах присутствует. Причем в двух экземплярах: 1) масива символов и литералов, 2) класс std::string. Ну, а то что создатели языка не очень то озаботились удобством программистов меня лично уже давно не удевляет.


MS>Согласен с твоими выводами (нижеудалеными), но возражаю по поводу наличия в C++ типа "строка". Нет такого типа в языке. Есть только некоторые соглашения, типа "массив байтов, завершающийся нулем можно считать строкой". Ну или массив интов в случае unicode. Компилятор ничего не знает ни об strcmp, ни о std::string. Соответственно, как можно строить switch/case по неизвестному типу? Язык не навязывает того, что строка обязана завершаться нулем, например. И поэтому, надо либо вводить в сам язык строгое понятие строки, либо (что лучше) возможность строить switch/case по произвольному типу.


MS>Далее размышляем.

MS>Таким образом, получается, что switch/case по строкам в любом языке является лишь полумерой. Как, например, реализовать switch/case с типом Date? Есть такой тип в C#? Нету. Есть только некий класс, который компилятор интерпретирует как любой другой класс. Конечно же, это абсурд — делать switch/case по конкретным датам. Но по месяцам, по кварталам или по дням недели это очень даже не абсурд. Соответственно, для такого типа, как DateTime нужен не просто switch, нужен switch по конкретным условиям (полям — месяц, квартал, день недели, время года, etc). А это уже ничем не отличается от switch/case по произвольному типу, с некими своими операциями сравнения.

MS>И что характерно, в том же C++ или C# это можно было бы реализовать элементарно. Достаточно такого старого понятия, как "вычисляемый goto":

MS>
MS>Date d(2005,05,05);
MS>label qn[] = { q1=0, q2=1, q3=2, q4=2 };
MS>swtitch(d.quarter(), qn)
MS>{
MS>   default: . . .
MS>   q1: . . .
MS>   q2: . . .
MS>   q3: . . .
MS>   q4: . . .
MS>};
MS>


MS>Фактически, switch это и есть вычисляемый goto, но только кастрированный и неспособный к развитию И при этом — не гарантирующий какую-либо оптимизацию. Все, что можно гарантировать — это O(N) и не более того. В то время, как вычисляемый goto железно обеспечивает O(1).


То же самое без всяких извращений.

switch( d.quarter() ) 
 {
  case 1 : ... break;
  case 2 : ... break;
  ...
  default: ...
 }


switch -- это и есть вычислимый goto. Только он мощнее. Поскольку метки могут быть непрерывным интервалом значений, в этом случае компилятор сгенерирует таблицу jam ов, или в случае, когда нет неперерывности -- двоичное дерево сравнений.
... << RSDN@Home 1.1.3 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[7]: ЧАСТЬ 4: синтаксический сахар, синтаксический мусор..
От: McSeem2 США http://www.antigrain.com
Дата: 22.05.05 02:05
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>switch -- это и есть вычислимый goto. Только он мощнее. Поскольку метки могут быть непрерывным интервалом значений, в этом случае компилятор сгенерирует таблицу jam ов, или в случае, когда нет неперерывности -- двоичное дерево сравнений.


Ты прав. Я тут сам запутался в своем словоблудстве. А хотел сказать нечто другое. Конструкция switch ничего не гарантирует. А хочется именно гарантированной оптимизации. И эту проблему как раз решает вычисляемый goto. Если у нас целый тип и диапазон значений непрерывен, используем как есть. Если же у нас строки или что другое, делаем бинарный поиск в явном виде и опять же отсылаем по вычисленной метке. Разница лишь в том, что switch гарантирует лишь O(N), а здесь мы сами принимаем решение — O(1), O(log N) или O(N).
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.