- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
import std.stdio;
class Parent{ }
class Another{ }
class Child: Parent
{
Another data;
alias data this;
this()
{
data = new Another;
}
}
void test(Parent t){writeln("Parent: ", t);}
void test(Another t){writeln("Another: ", t);}
void main() {
auto Me = new Child();
test(Me);
}
http://dlang.org/function.html#pure-functions
вот immutable объекты в STL/C++/етц как по были бы мне более полезны. но они там никогда не появятся, потому что полиморфизм производительность снизит. :(
Как immutable связан с полиморфизмом? Он делает теже пункты, что я назвал для чистых функций (в частности увеличивает производительность).
может быть. пока нужды в этом не видел. а приори я не против. :)
смахивает немного на фишку функциональных языков, где значение можно привязывать к переменной только раз.
> Как immutable связан с полиморфизмом?
я секретный фанат ObjC стиля. в С++ у тебя например `const vector<>` и `vector<>`. а в ОбжС `NSArray` и `NSMutableArray`, и NSMutableArray унаследован от immutable NSArray.
ключевая разница между языками в том что если тебе надо слобать кастом ридонли контейнер, то в С++ для поддержания совместимости с STL надо реализовавывать еще в добавок кучку левых методов для модификации. потому что `const`ность зависит от контекста, а не от самого объекта. в ObjC достаточно реализовать только методы для чтения, потому что констность есть свойстно самого контейнера. но для полноценной работы этого всего нужен полиморфизм, что бы от immutable класса можно было унаследовать mutable класс и перекрыть ридонли варианты методов - потому что представление данных в immutable и mutable контейнерах может отличатся.
неоднократно делал это в С++, но с ограниченым успехом. основная проблема как всегда это совместимость с STL, который хочет итераторы. тут то грабли и начинаются так как констноть итераторов зависит от контекста, а не от объекта...
В C++ всё веселее, ведь там есть попытка подтвердить иммутабельность объектов (хотя бы бинарную) на уровне компиляции. От этого решения есть как два плюса, так и минусы.
>Мутабельный массив не является иммутабельным по определению. *
* наследование подразумевает, что если , то , а тогда получается что - т.е. мутабельный массив является (по определению наследования и исходя из описанной выше иерархии NSArray и NSMutableArray) иммутабельным. Такой результат в реальной программе может привести к смерти брата.
поэтому для какого то блока мутабельный массив вполне является иммутабельным, и к смерти брата это не приведет
является ли в данном случае вовлечение наследования только для code reuse, или его тут действительно можно использовать - я бы пообсуждал
потому что недавно как раз имплементил нечто подобное, где мутабельный объект наследовался от иммутабельного (без костылей с виртуальностью)
А как в таком случае с многопоточностью? Если я захочу один и тот же массив в одну функцию передать, как мутабельный, а в другую - как иммутабельный, и функций будут выполняться параллельно - что произойдет?
http://govnokod.ru/12482#comment168293
Нужен NImmutableArray. Он же immutable в D. Он же непогрешимый, а не логический const. Для таких проблем с массивом при многопоточной работе - нет.
поэтому надо лочить r/w доступ к контейнеру (ну или копировать по значению/велосипедить cow, что попахивает)
что ты куришь? слишком много жабы??
само собой разумеется что мутабельный объект наследуется от немутабельного, что бы его можно было передавать как параметр туда где достаточен немутабельный объект.
таже самая фигня и в С++: не-конст объектом можно пользоватся и как не-конст и как конст, конст объектом можно пользоватся только как конст.
"В C++ всё веселее, ведь там есть попытка подтвердить иммутабельность объектов (хотя бы бинарную) на уровне компиляции."
много асма для С++ видел. некоторый даже в деталях расковыривал. разницы от констности в кодогенерации, по крайней мере на с++98, не видел.
В Scala, если идентификатор объявлен как var, то его значение позже можно заменить на другое (идентификатор/ссылка не является константой). Но при этом текущее значение может быть как мутабельным, так и иммутабельным.
Если идентификатор объявлен как val, то его значение нельзя заменить на другое (ссылка постоянна). Но при этом само значение, на которое указывает идентификатор, может быть как мутабельным, так и иммутабельным.
В большинстве языков такого различия не делается, отсюда бардак в головах (некоторых) программистов.
>само собой разумеется что мутабельный объект наследуется от немутабельного, что бы его можно было передавать как параметр туда где достаточен немутабельный объект.
Этого достаточно для соблюдения принципа подстановки Лисков ТОЛЬКО при условии, что передаваемый объект используется одним потоком. Если имеем многопоточное приложение, то у меня для вас плохие новости: когда мы передадим мутабельный объект под видом иммутабельного, то все наши предположения о нем, как об иммутабельном, в общем случае окажутся неверны. Вы сами можете догадаться, почему.
Более того, это действительно является совершенным бредом с семантической точки зрения ("мутабельный объект является иммутабельным"). Я пояснил это в http://govnokod.ru/12482#comment168282
а. ты о этом. не ну это само собой разумеется. но это проблема только для многопоточности. а в многопоточности за что ни возмись, все проблема. поэтому то многопоточность и остается нишей. только языки которым одного ядра мала ею и злоупотребляют. ;)
иммутабл объекты они мне больше полезны как утилита которая позволяет экономить память и избегать лишних копирований. потенциальная возможность наследования мутабл от иммутабл для меня всего лишь бонус. с мутабл объекта иммутабл копию всегда сделать можно (что уже является нормой для большинства языков и стандартных библиотек).
самое успешное использование иммутаблов у меня было в программе где жутко большой кусок текста (несколько гигов) зачитывался в память, пихался в доморощеную иммутабл строку, и потом по всей программе использовались иммутабл подстроки этой большой иммутабл строки.
http://dlang.org/const3.html
И опять же пришли предположительно, тк Роман не откликнулся, к скаловской иерархии:
это конструктор копирования и оператор присваивания, чтоли?
что имеется в виду под совместимость с stl?
способность использовать все стандартные фишки из например algorithm. так же как минимум синтаксическая совместимость с STL что бы в пользовательском коде сильно кастом контейнеры от STL контейнеров не отличались.
> это конструктор копирования и оператор присваивания, чтоли?
главные грабли - итераторы. и с ними идущие find()/begin()/end(). erase() по итератору. resize(). (push|pop)_(front|back).
да всего уже не помню. помню что GCCшные ошибки типа "невозможно инстанциировать темплейт потому что" и 20-50 строк кракозябель не были сильной помощью.
помню только мораль сей басни: если проект сидит на STL, то велосипед не стоит усилий.
итераторы легче сделать через boost.iterator_facade
а 20-50 строк нечитабельного текста ошибки - это, обычно, результат проверки на "концепт" типа RandomAccess или Bidirectional - как благодарность комитету, что не приняли нормальных концептов
> если контейнер иммутабелен, то какой по нему еще erase или resize?
про то же и речь. в С++/STL нет концепции immutable - поэтому приходится реализовывать лишние методы просто потому что в каком темплейте упоминается метод. по логике программы он не будет вызыватся, то как минимум заглушку надо добавлять, что бы темплейт мог инстанциироватся.
потому что другой темплейт класс на него ссылается. даже если методы которые на него ссылаются не используются, компилеры (некоторые? все? хез, у меня обмавалась компиляция с ошибкой и на гцц 3 и на паре комерческих) требуют/требовали наличие оного.
потому что Н лет назад именно вот такого типа код у меня и не компилировался.
все темплейты из algorithm работают и с сырыми указателями, поэтому все что нужно от итераторов - дереференс, инкремент, при рандом аксесс - смещение на n, ну и если он мутабелен - дереференс должен возвратить T&, если не мутабелен - не должен
поэтому есть в контейнерах iterator, а есть const_iterator, потому что в половине случаев стл контейнеры сами используются в ситуации, где они строго константны
там в algorithm вроде ни одной функции нет, которая бы не с итератором, а с контейнером работала
Категорию стасик_ассертом проверить и все. А вот то что нет отдельной ортогональной категории для writable и readable - это упущение.
Кто на свеженького?
http://ideone.com/rm3li
>246 days 20 hours ago
Свежачок свежачок, налетай, компиляй:
http://ideone.com/7xmyx
Свежачок свежачок, очень вкусный слушай:
http://ideone.com/sS9rc
LispGovno, ну как не стыдно?
alias data this;
И что слова alias в поцкалике нету?
То, что оно означает "синоним", то есть "два названия для одного и того же" (это я добавил, чтобы ты не подумал, что я залез в гуглопереводчик и скопировал оттуда умное слово, не зная его смысл), нихуя не проясняет того, как же всё-таки расположены поля в этой структуре.
>>как же всё-таки расположены поля в этой структуре.
Та нет никакой структуры