Гибкие записи в статике
Feb. 21st, 2013 02:32 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Ребе
metaclass уже не первый раз поднимает эту тему: можно ли иметь строгую типизацию записей, но не объявляя их заранее? Вот пара примеров из используемых мною языков.
Первый пример: Haxe.
Язык со статической типизацией. Где типы не указаны, компилятор сам их выводит. Тут функция makeData производит значение анонимного типа с парой полей типа Int и String (тоже выведены). Другая функция использует данные из такой записи. Напрямую одна другую даже не вызывает. Все компиляется и работает гладко. Теперь если заменить строчку
var y:String = data.b;
на
var y:String = data.c;
то компилятор скажет:
C:\vc\player\src/Main.hx:876: characters 10-11 : { b : String, a : Int } should be { c : String, a : Int }
C:\vc\player\src/Main.hx:876: characters 10-11 : { b : String, a : Int } has no field c
C:\vc\player\src/Main.hx:876: characters 10-11 : For function argument 'data'
А если там поставить
var y:Bool = data.b;
то скажет
C:\vc\player\src/Main.hx:876: characters 10-11 : { b : String, a : Int } should be { b : Bool, a : Int }
C:\vc\player\src/Main.hx:876: characters 10-11 : Invalid type for field b :
C:\vc\player\src/Main.hx:876: characters 10-11 : String should be Bool
C:\vc\player\src/Main.hx:876: characters 10-11 : For function argument 'data'
Т.е. как раз мечтаемое: тип заранее не описываем, он выводится на месте описания данных, и все статически проверяется при использовании.
Второй пример: D.
Аналогичный код:
Чуть длиннее, но ненамного. Причем вместо tuple(99... можно было сразу писать data.a = 99;... Кстати, здесь конструктор типов Tuple и функция tuple - не ключевые слова языка, а чисто библиотечные штуки, входят в стандартную библиотеку.
В таком виде все компиляется гладко. Меняем
string y = data.b;
на
string y = data.с;
Компилятор отвечает "Error: no property 'c' for tuple '(int, string)'".
Если же поставить
bool y = data.b;
то говорит "Error: cannot implicitly convert expression (data._field_field_1) of type string to bool.
В общем, в приличных языках счастье есть, и даже без макросов. Ну а динамическая типизация для таких задач не нужна и даже вредна.
![[livejournal.com profile]](https://www.dreamwidth.org/img/external/lj-userinfo.gif)
Первый пример: Haxe.
function makeData() { return { a: 99, b : " bottles of beer" }; } function useData(data):Void { var x:Int = data.a; var y:String = data.b; trace(x, y); } ... var t = makeData(); useData(t);
Язык со статической типизацией. Где типы не указаны, компилятор сам их выводит. Тут функция makeData производит значение анонимного типа с парой полей типа Int и String (тоже выведены). Другая функция использует данные из такой записи. Напрямую одна другую даже не вызывает. Все компиляется и работает гладко. Теперь если заменить строчку
var y:String = data.b;
на
var y:String = data.c;
то компилятор скажет:
C:\vc\player\src/Main.hx:876: characters 10-11 : { b : String, a : Int } should be { c : String, a : Int }
C:\vc\player\src/Main.hx:876: characters 10-11 : { b : String, a : Int } has no field c
C:\vc\player\src/Main.hx:876: characters 10-11 : For function argument 'data'
А если там поставить
var y:Bool = data.b;
то скажет
C:\vc\player\src/Main.hx:876: characters 10-11 : { b : String, a : Int } should be { b : Bool, a : Int }
C:\vc\player\src/Main.hx:876: characters 10-11 : Invalid type for field b :
C:\vc\player\src/Main.hx:876: characters 10-11 : String should be Bool
C:\vc\player\src/Main.hx:876: characters 10-11 : For function argument 'data'
Т.е. как раз мечтаемое: тип заранее не описываем, он выводится на месте описания данных, и все статически проверяется при использовании.
Второй пример: D.
Аналогичный код:
auto makeData() { Tuple!(int, "a", string, "b") data = tuple(99, " bottles of beer"); return data; } void useData(T)(T data) { int x = data.a; string y = data.b; writeln(x,y); } ... auto t = makeData(); useData(t);
Чуть длиннее, но ненамного. Причем вместо tuple(99... можно было сразу писать data.a = 99;... Кстати, здесь конструктор типов Tuple и функция tuple - не ключевые слова языка, а чисто библиотечные штуки, входят в стандартную библиотеку.
В таком виде все компиляется гладко. Меняем
string y = data.b;
на
string y = data.с;
Компилятор отвечает "Error: no property 'c' for tuple '(int, string)'".
Если же поставить
bool y = data.b;
то говорит "Error: cannot implicitly convert expression (data._field_field_1) of type string to bool.
В общем, в приличных языках счастье есть, и даже без макросов. Ну а динамическая типизация для таких задач не нужна и даже вредна.