Re[5]: Дополнение/исправление
От: c-smile Канада http://terrainformatica.com
Дата: 04.05.05 16:20
Оценка: 5 (1) +2 :)
Здравствуйте, Сергей Губанов, Вы писали:

СГ>А разьве это не всегда так? Разьве деструктор может позвать кто-то еще кроме GC? Если да, то зачем?


СГ>(Например, в Component Pascal, вызвать финализатор может только GC и никто другой, это потому что виртуальный пустой метод FINALIZE()- экспортируется "только для реализации", но не для вызова).


В D как и в C++ есть оператор delete.
Но в D есть еще и GC при этом.

Что есть (GC и delete вместе) *очень* разумно.
Выделил — убери за собой.
Не можешь убрать сейчас? Ладно, тогда оставь дворнику.
Но труд дворника надо уважать. У него "много вас ходють".

Оптимистичный подход в стиле "А вот программуля "Радость garbage collector'а""
уж очень смотрится... некузяво... это тебе любой
советский инженер (ТМ) скажет.

Да, МcSeem?
Re[2]: Арифметические операции
От: moudrick Россия http://community.moudrick.net/
Дата: 04.05.05 18:06
Оценка:
MS>В высокоуровневых языках часто возникает ситуация "за лесом деревьев не видать".
MS>Взять, хотя бы простейшее выражение (операция целочисленного масштабирования):
MS>
MS>int v = a*b/c;
MS>

MS>a, b, c — все int. ... MUL ... DIV ... простую и эффективную последовательность инструкций mul/div. Таким образом, хотелось бы иметь что-то типа:
MS>
MS>v = a.muldiv(b, c);
MS>или 
MS>v = a.mulshift(b, 32); // - умножаем и берем старшие 32 бита
MS>

MS>Повторю еще раз — в рамках арифметической записи задача нерешаема в любом языке.

А что мешает ввести такой тернарный оператор:

(* / ) типа как ( ? : )


И при синт.разборе искать его сначала,
а если не найдется, то применить традиционные умножение/деление?

MS>Другая часто возникающая потребность — получение частного и остатка. ... DIV .... Но вот мы пишем:

MS>
MS>int lift = a/b;
MS>int rem  = a%b;
MS>

MS>И у нас нет ни малейшей гарантии того, что компилятор соптимизирует данную конструкцию в одну команду. А хотелось бы именно гарантии. Но для этого нужна специальная конструкция языка, причем весьма нетривиальная — с двумя взвращаемыми значениями.

Есть такой вариант:
c % o = d1 \ d2;
или
(c % o) = d1 \ d2;

где c и o являются lvalue соотв.типа.

Что скажут разработчики синтпарсеров и компиляторов,
не сильно ли навороченные эти две предложенные мной конструкции?
На предмет:
    a) непротиворечивости с традиционными
    б) легкости разбора
    с) а кто будет ими пользоваться?
?
Re[6]: Дополнение/исправление
От: LCR Россия lj://_lcr_
Дата: 04.05.05 19:04
Оценка:
c-smile:

CS>Да, МcSeem?

(Шёпот из-за угла: "Дайте человеку поработать ").

Играемся с памятью:
    MyObject o = new MyObject (200);
    delete o;
    o.method();    // segmentation fault

Результат ожидаемый. Ну может быть сообщение слишком лаконично.

    printf ("create an object\n");
    MyObject o = new MyObject (100);
    printf ("kill the object\n");
    delete o;
    printf ("dance on the grave %)\n");
    for (int i = 1; i <=100; i++)
        delete o; // segmentation fault

Результат ожидаемый, но где-то в аппендиксе теплилась надежда на то, что вдруг менеджер кучи помечает это место так, что можно удалять несколько раз. Ну или другое решение — объект в delete передаётся по ссылке, так что
    MyObject o = ...;
    delete  o;
    // o == null
    printf ("dance on... Where is the grave?!!! %)\n");
    for (int i = 1; i <=100; i++)
        delete o; // segmentation fault


Да, кстати, нуль можно удалять безболезненно.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re[3]: Снова D: Зверёк читает мануал
От: FR  
Дата: 04.05.05 19:55
Оценка: 20 (1)
Здравствуйте, Зверёк Харьковский, Вы писали:

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


FR>>У меня прямо дежавю какое то, все как в питоне


ЗХ>забавно а как это там выглядит?


Перегрузка операторов практически также:

__add__(self, other)
__sub__(self, other)
__mul__(self, other)
__div__(self, other)
__mod__(self, other)
__divmod__(self, other)
__pow__(self, other [, modulo])
__lshift__(self, other)
__rshift__(self, other)
__and__(self, other)
__xor__(self, other)
__or__(self, other)


сравнение и равенство тоже __cmp__(self, other)
также для ключей словарей нужно определять __hash__(self)
многие встроеные типы имют методы, например print "test".__add__(" string")
можно наследоватся от встроенных типов.
Re[7]: Дополнение/исправление
От: c-smile Канада http://terrainformatica.com
Дата: 04.05.05 23:31
Оценка:
Здравствуйте, LCR, Вы писали:

LCR>Играемся с памятью:

LCR>
LCR>    MyObject o = new MyObject (200);
LCR>    delete o;
LCR>    o.method();    // segmentation fault
LCR>

LCR>Результат ожидаемый. Ну может быть сообщение слишком лаконично.

Ну дык эта... D программинг (как и C++) это дело настоящих "мушшин" .

Я ж сказал: удаляй если уверен. Но в отличие от C++ ты можешь себе позволить
роскошь и не удалять.
Re[4]: Снова D: Зверёк читает мануал
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.05.05 01:34
Оценка: +1
Здравствуйте, uw, Вы писали:

uw>Что может быть проще и очевидней вот такого кода?


uw>
uw>class Task
uw>{
uw>    private int priority;
uw>    public int opCmp(Task t)
uw>    {
uw>        return priority - t.priority;
uw>    }
uw>}
uw>


Выговор с лишением зарплаты или премии. Такой код требует, чтобы числа были заведомо маленькими. Иначе переполнение и наязыках вроде С++ ты будешь искать ошибку годами.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Снова D: Зверёк читает мануал
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.05.05 01:34
Оценка: +1
Здравствуйте, c-smile, Вы писали:

CS>Ах это! Ну дык там диапазон возможных

CS>значений всего от -15 до 15 (Win32 thread priority levels)

Где там? uw предложил это как универсальное решение. Такие фишки нужно заранее оговаривать.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Снова D: Зверёк читает мануал
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.05.05 01:34
Оценка:
Здравствуйте, uw, Вы писали:

uw>Вообще в D есть контракты, так что для избежания патологических случаев можно делать так:

uw>
uw>class Task
uw>{
uw>    static const MaxPriority = // ...;
uw>    static const MinPriority = // ...;

uw>    public this(int priority_)
uw>    {
uw>        priority = priority_;
uw>    }

uw>    public opCmp(Task t)
uw>    {
uw>        priority - t.priority;
uw>    }

uw>    invariant
uw>    {
uw>        assert((priority >= MinPriority) && (priority <= MaxPriority));
uw>    }

uw>    private int priority;
uw>}
uw>


Скромный вопрос... А эти контракты проверяются когда? Если в рантайме, то это просто дурь. А если в компайлтайме, то не ясен механизм проверок.

Или это нечто вроде ассертов? Опять же может грохнуть в релизе...
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: ЧАСТЬ 3: Конструкторы, деструкторы, и RAII
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.05.05 01:34
Оценка:
Здравствуйте, eao197, Вы писали:

E>А можно пример, где нужно запретить вызов конструктора базового класса?


Это часть дизайна. Так же как возможность вызывать или нет методы базового класса из виртуального метода.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: ЧАСТЬ 3: Конструкторы, деструкторы, и RAII
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.05.05 01:34
Оценка:
Здравствуйте, Зверёк Харьковский, Вы писали:

ЗХ>ИМХО, если возникла такая ситуация, где ты от базового класса отнаследовался, а конструктор его вызывать не хочешь — нефик было наследоваться.

ЗХ>Если по-научному, то объект для которого не был вызван конструктор, не может предоставить вообще никаких гарантий непротиворечивости своего состояния. Это относится, в частности, и к базовому подобъекту.

А какие гарантии у объекта переопределяющего виртуальный метод? Надо вызывать базовый метод или нет?
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: ЧАСТЬ 3: Конструкторы, деструкторы, и RAII
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.05.05 01:34
Оценка:
Здравствуйте, LCR, Вы писали:

LCR>В Delphi конструктором назвали то, что в паттернах называется ObjectFactory...


Тогда уж FactoryMethod... В общем, ерунда это все. Это дизайнерское решение создателей языка. Оно неплохо работает на практике и доказывает, что С++ подход не тольк не единственный, но и далеко не лучший.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Зверёк читает мануал: properties
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.05.05 01:34
Оценка:
Здравствуйте, WinterMute, Вы писали:

CS>>Дополнение:


CS>>В D typedef вводит новый тип, а не алиас как в C++.


CS>>т.е.


CS>>
CS>>typedef uint Color; 
CS>>Color c; 
CS>>c += 28; // ошибка компиляции.
CS>>


WM>Не очень понятно, какой от этого выйгрыш?


Элементарный. Предположим у тебя есть два вида координат. Одни реальные, другие виртуальные. Логика у них идентичная, но данные у них не совместимы (координаты то в разных системах). Имея жесткое определение типа ты можешь определить один тип, а второй вывести из него. Далее останется написать методы преобразования и ты получашь готовое решение без шума и пыли.

Альтернативой является наследование. Но например, в C# наследования для структур нет. Да и наследование порой порождает кучу проблем.

WM>Вот чтобы хотелось увидеть от нового языка, это какой-нибудь хитрый способ наследования от базовых типов, чтобы можно было писать:


WM>
WM>class IdealInt : public int
WM>{
WM> //...
WM>};
WM>


У этого тоже есть куча проблем. Если язык декларирует "все является объектом" и предоставляет набор виртуальных методов у базового класса, то наследование вэлью-типов может привести к неоднозначностям.

К тому же появляются нехилые проблемы с приведением типов. Ведь наследник может иметь другой размер.
... << RSDN@Home 1.1.4 beta 4 rev. 351>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Арифметические операции
От: Шахтер Интернет  
Дата: 05.05.05 03:24
Оценка: 1 (1)
Здравствуйте, uw, Вы писали:

uw>Здравствуйте, Шахтер, Вы писали:


Ш>>Да и в С++ это не проблема.

uw>В C++ это именно проблема. Решение конечно есть(std::pair + make_pair), но оно далеко не идеально.

Используй структуры данных.

uw>А если возвращать не два, а три и больше значений, то C++ вообще отдыхает.


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

struct Mul
 {
  int hi;
  unsigned low;
    
  Mul(int a,int b);
 };
... << RSDN@Home 1.1.3 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[10]: Снова D: Зверёк читает мануал
От: Шахтер Интернет  
Дата: 05.05.05 03:24
Оценка: 16 (1)
Здравствуйте, uw, Вы писали:

uw>Здравствуйте, Шахтер, Вы писали:


Ш>>Если диапазон значений маленький, то да, но лучше на это не полагаться.


uw>Вообще в D есть контракты, так что для избежания патологических случаев можно делать так:

uw>
uw>class Task
uw>{
uw>    static const MaxPriority = // ...;
uw>    static const MinPriority = // ...;

uw>    public this(int priority_)
uw>    {
uw>        priority = priority_;
uw>    }

uw>    public opCmp(Task t)
uw>    {
uw>        priority - t.priority;
uw>    }

uw>    invariant
uw>    {
uw>        assert((priority >= MinPriority) && (priority <= MaxPriority));
uw>    }

uw>    private int priority;
uw>}
uw>


В данном случае, лучше реализовать opCmp как (priority<t.prioryty)?-1: (priority!=t.prioryty).
... << RSDN@Home 1.1.3 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[11]: Снова D: Зверёк читает мануал
От: uw  
Дата: 05.05.05 04:31
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Скромный вопрос... А эти контракты проверяются когда? Если в рантайме, то это просто дурь. А если в компайлтайме, то не ясен механизм проверок.


VD>Или это нечто вроде ассертов? Опять же может грохнуть в релизе...

В D (ассерты == исключения). Просто выбрасывается исключение AssertError. Если не ловить, то работает как ассерт.

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

Кстати диапазон допустимых значений в моем примере не так уж мал. [min_int/2,max_int/2] для очень многих задач вполне достаточно. Для беззнаковых чисел это вообще [0, max_int(!= max_uint)]. Бессмысленно даже говорить о том, что short или byte таким образом можно сравнивать абсолютно безболезненно. Для остальных случаев конечно потребуются сравнения, или можно как-нибудь задействовать int64.

P.S. Забавно, что все соглашаются, что может быть integer overflow и никто не обратил внимание на то, что код абсолютно не корректен(например отсутствие return в opCmp). Немножко не те языки уже начинают вырабатывать стойкие привычки.

Если кому нужно вот нормальный код, да еще и с тестированием производительности:
import std.perf, std.stdio, std.random;

class Task
{
    // (INT_MAX/2)
    static const int MaxPriority = 1073741823;
    // (INT_MIN/2)
    static const int MinPriority = -1073741824;

    public this(int priority_)
    {
        priority = priority_;
    }

    int opCmp(Object o)
    {
        Task t = cast (Task) o;
        return priority - t.priority;
    }

    public int Priority()
    {
        return priority;
    }

    public void Priority(int p)
    {
        priority = p;
    }

    invariant
    {
        assert((priority >= MinPriority) && (priority <= MaxPriority));
    }

    private int priority;
}


const int CHUNK_SIZE = 2000;
const int N_CYCLES = 100;

void main()
{
    HighPerformanceCounter t = new HighPerformanceCounter();
    t.start();
    Task[] tl;
    try
    {
        
        for (int i = 0; i < N_CYCLES; ++i)
        {
            for (int j = 0; j < CHUNK_SIZE; ++j)
                tl ~= new Task((rand() % (1073741823 * 2)) - 1073741824);
            tl.sort;
        }        
        // tl[0].Priority = 2147483647;
    }
    catch(Exception e)
    {
        writefln(e.msg);
    }
    t.stop();
    writefln("time elapsed : %d",t.milliseconds());
    foreach (Task t; tl)
        writefln("%d",t.Priority);
}
Re[6]: ЧАСТЬ 3: Конструкторы, деструкторы, и RAII
От: LCR Россия lj://_lcr_
Дата: 05.05.05 06:17
Оценка:
VladD2:

VD>Тогда уж FactoryMethod...

Термин эквивалентный ObjectFactory, btw.

VD>В общем, ерунда это все. Это дизайнерское решение создателей языка. Оно неплохо работает на практике и доказывает, что С++ подход не тольк не единственный, но и далеко не лучший.


Подход C++ также показал свою пригодность для программирования. Можешь поподробнее про это доказательство, а то что-то я не врубаюсь... На мой взгляд это дизайнерское решение ничего не доказывает.
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re: Снова D: Зверёк читает мануал
От: achmed Удмуртия https://www.linkedin.com/in/nail-achmedzhanov-9907188/
Дата: 05.05.05 06:38
Оценка:
Зверёк Харьковский пишет:

[....]

Манул пj языку не смотрел — некогда, сложность синаксиса, с точки зрения
создания "правильной среды разработки"
по примерам в форуме не могу оценить, можете сейчас оценить сложность
написания такой среды относительно Java и C++
( имеется в виду на сколько сложно будет сделать IDE которая бы парсила
код на лету, делал правильный автокомлит,
рефакторинг etc)
Posted via RSDN NNTP Server 1.9
Re[7]: Зверёк читает мануал: properties
От: Sergey Россия  
Дата: 05.05.05 07:20
Оценка:
Hello, LCR!
You wrote on Wed, 04 May 2005 16:14:37 GMT:

L> Но вопрос то не в этом. Если мы поставим квадратные скобки в любом

L> другом "междускобьи":
 L> typedef int (*mcfp)(int (*fp)(void* v1, void* v2), int& r) [];
 L> typedef int (*mcfp)[](int (*fp)(void* v1, void* v2), int& r);
 L> typedef int [] (*mcfp)(int (*fp)(void* v1, void* v2), int& r);
 L>

L> то такая простановка скобок в каждом из положений указанном выше
L> выглядит разумной. К моему несчастью всё, что мне кажестя
L> разумным, компилятор (с распечаткой стандарта в качестве ударного
L> механизма) таковым не считает.

Мне это тоже не нравится Мозги сломаешь, пока догадаешься, где какую
скобку лепить, а где звездочку. Только вот вся это возня со скобками
прекрасно обходится с помощью обсуждаемого typedef.

L> Я напомню, с чего всё начиналось. Начиналось с того, что я указал на

L> идеологический косяк в D, который он перенял из C касаемо объявлений
L> типов.

Вряд ли это можно назвать косяком. Собственно, выдумывать для typedef особый
синтаксис, отличный от синтаксиса объявлений переменных и типов мне не
кажется разумным. Т.е., если тип из предыдущего примера мы хотим объявлять
как
type mcfp = array of
(
  func : ( (func : (void , void ) -> int ), void * ) -> int
);

то объявлять (и инициализировать при необходимости) переменные по старому,
как
int (*mcfp[])(int (fp)(void v1, void* v2), int& r) = {foo, bar, 
0};

было бы глупостью. Ну а если поменять и это, сложновато будет
позиционировать D как наследника С

L> На что Зверёк мне возразил, и сказал, что дескать всё гладко (то есть

L> якобы определения для любых типов аналогичны typedef x y). Мой
L> последующий контраргумент касается того, что эта гладкость прокатывает
L> только для простых случаев, а рекурсивные определения наподобие
 type
 L> mcfp = .. /* anything you want */;
 L>

L> прозрачнее и одновременно сколь угодно расширяемы.

L> PS: у меня ещё одна ошибка была

L>>> typedef struct _tagS {....} S1; // определение типа S1!

Ошибка была только в комментарии и выводах. Без typedef это определение типа
_tagS и переменной S1. Simple declaration, однако К чему там было
написано про енум Е и класс С, я, честно говоря, вообще не понял. Для енумов
тоже можно использовать typedef, и это тоже будет выглядеть как объявление
переменной, перед которым написали declspecifier.

With best regards, Sergey.
Posted via RSDN NNTP Server 1.9
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[4]: ЧАСТЬ 3: Конструкторы, деструкторы, и RAII
От: Зверёк Харьковский  
Дата: 05.05.05 14:55
Оценка:
Здравствуйте, VladD2, Вы писали:

ЗХ>>ИМХО, если возникла такая ситуация, где ты от базового класса отнаследовался, а конструктор его вызывать не хочешь — нефик было наследоваться.

ЗХ>>Если по-научному, то объект для которого не был вызван конструктор, не может предоставить вообще никаких гарантий непротиворечивости своего состояния. Это относится, в частности, и к базовому подобъекту.

VD>А какие гарантии у объекта переопределяющего виртуальный метод? Надо вызывать базовый метод или нет?


Вопрос, конечно, интересный и неоднозначный. ИМХО, если объект наследника может модифицировать состояние базового подобъекта только через открытые и защищенные методы — этого достаточно для герентии непротиворечивости состояния оного подобъекта. Т.е. базовый метод вызывать не надо.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
Re[2]: Снова D: Зверёк читает мануал
От: Зверёк Харьковский  
Дата: 05.05.05 14:55
Оценка:
Здравствуйте, achmed, Вы писали:

A>Манул пj языку не смотрел — некогда, сложность синаксиса, с точки зрения

A>создания "правильной среды разработки"
A> по примерам в форуме не могу оценить, можете сейчас оценить сложность
A>написания такой среды относительно Java и C++
A>( имеется в виду на сколько сложно будет сделать IDE которая бы парсила
A>код на лету, делал правильный автокомлит,
A>рефакторинг etc)

В общем-то, — я не специалист разработки сред
Единственное, что могу сказать:

Major Goals of D
...
* Make D substantially easier to implement a compiler for than C++.
...
* Have a context-free grammar.
...

... << RSDN@Home 1.1.4 beta 6a rev. 436>>
FAQ — це мiй ай-кью!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.