Здравствуйте, _NN_, Вы писали:
_NN>В TypeScript на удивление как раз можно использовать void в параметрах обобщений:
Интересно. А есть какие-то правила "свертки" кода, если вместо типа оказывается void?
Не знаю typescript, но например если там в каком-то выражении используется value, которое оказывается типа void — что происходит с выражением?
Здравствуйте, NeoCode, Вы писали:
NC>Здравствуйте, _NN_, Вы писали:
_NN>>В TypeScript на удивление как раз можно использовать void в параметрах обобщений:
NC>Интересно. А есть какие-то правила "свертки" кода, если вместо типа оказывается void?
В спецификации не нашел явного упоминания: http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf
3.2.4 The Void Type
The Void type, referenced by the void keyword, represents the absence of a value and is used as the return type of functions with no return value.
The only possible values for the Void type are null and undefined. The Void type is a subtype of the Any type and a supertype of the Null and Undefined types, but otherwise Void is unrelated to all other types.
NOTE: We might consider disallowing declaring variables of type Void as they serve no useful purpose. However, because Void is permitted as a type argument to a generic type or function it is not feasible to disallow Void properties or parameters.
Не знаю как должно быть, но вот так можно:
interface A<T> {
f(x:number,a: T);
}
<A<void>>(null).f(1); // <> это приведение типа, т.е. в стиле C: ((A<void>)(null)).f(1)
А вот так уже нельзя
var a = <A<void>>(null);
a.f(1);
Ну и аналогично так правильно
interface A<T> {
f(x:number,a: T);
}
class B implements A<void> {
f(x:number) {}
}
А явно 'void' указывать нет:
interface A<T> {
f(x:number,a: T);
}
class B implements A<void> {
f(x:number, a:void) {}
}
new B().f(1); // Error
// Надо так
// new B().f(1, undefined);
NC>Не знаю typescript, но например если там в каком-то выражении используется value, которое оказывается типа void — что происходит с выражением?
Если аргумент сделать типом 'void' явно то будет явное использование.
И в этом случае нужно будет явно передать значение undefined или null.
Здравствуйте, _NN_, Вы писали:
_NN><A<void>>(null).f(1); // <> это приведение типа, т.е. в стиле C: ((A<void>)(null)).f(1) _NN>[/java] _NN>А вот так уже нельзя _NN>
_NN>var a = <A<void>>(null);
_NN>a.f(1);
_NN>
Я тут не прав.
<A<void>>(null).f(1) == (<A<void>>)((null).f(1))
А вот так действительно нельзя как и в случае переменной.
_NN>Насколько логично относиться к 'void' или 'Unit' как к обычному типу ?
Имхо, void вообще не имеет право на существование.
The void type, in several programming languages derived from C and Algol68, is the type for the result of a function that returns normally, but does not provide a result value to its caller.
То есть понятно, что void появился, как костыль. В случае, если everything is an expression, и все возвращает значение, то void не нужен. От слова совсем
M>Имхо, void вообще не имеет право на существование. M>То есть понятно, что void появился, как костыль. В случае, если everything is an expression, и все возвращает значение, то void не нужен. От слова совсем
Здравствуйте, Mamut, Вы писали:
M>Имхо, void вообще не имеет право на существование.
void это не тип, это "псевдотип". В действительности через void обозначается пустой список аргументов или вовзращаемых значений, 0-арный кортеж. То есть если есть функция foo(int,float) — у нее список аргументов "int,float" это тип? Нет, это не тип, это нечто более абстрактное — это кортеж, список сущностей времени компиляции (каждая из которых уже является типом). void точно также не тип, а список, только пустой.
Идея привести void к типу в общем полезная, но нужно помнить что это именно "псевдотип" и учитывать это, не требуя от void полностью вписываться в систему типов — тогда можно построить преемлемую модель использования void и аккуратно обойти все проблемы с ним.
Здравствуйте, D. Mon, Вы писали:
DM>Здравствуйте, NeoCode, Вы писали:
NC>>
function foo(void, int, void);
NC>>(такое может получиться, например, из шаблонной функции при подстановке void в параметры шаблона) NC>>Должен ли компилятор "сворачивать" ее к виду "foo(int)"?
DM>Мой ответ: нет, ни в коем случае. От этого опять куча проблем и граблей.
DM>И еще важный момент: нужно понимать, что f() — это не вызов функции без аргументов, а именно вызов с одним аргументом — (), он же void. Он потому так и называется (), не просто так. Поэтому f(void) не имеет никакого смысла, это же f (()), бессмысленная конструкция даже синтаксически. DM>А foo(void, int, void) принимает тупл из трех элементов, ни больше ни меньше.
Возникает следующий вопрос.
Считать ли выражения ((a, b), c) и (a, b, c) эквивалентными?
1. Если да, то получается правило такое, что мы можем вставить содержимое вложенных кортежей в текущий. Пусть a имеет тип void, то есть a = (). Тогда получается, что ((a, b), c) эквивалентно ((), b, c), а это эквивалентно (b, c) (в первом преобразовании первый элемент внешнего кортежа преобразовался в два элемента из вложенного кортежа, а во втором преобразовании первый элемент внешнего кортежа преобразовался в ноль элементов). В этой схеме полезным свойством является то, что скобки не принимают непосредственное участие в задании кортежа. Вместо этого кортеж определяется запятыми, а скобки играют роль группировки операторов как в арифметических выражениях.
2. Если считать эти выражения различными, возникает проблема с кортежем единичного размера. Будет ли ((a), c) эквивалентно (a, c)? Считаются ли ((a)), (a) и a эквивалентными? Остается два варианта — либо считать эти выражения различными, либо рассматривать кортеж из одного элемента специальным образом. Считать их различными кажется дико неудобно, а иметь специальные правила для единичного кортежа — костыль, который тоже вызовет кучу проблем и граблей.
В итоге нужно определиться, какое из решений вызывает меньше проблем и граблей. Я думаю, всё-таки лучше сворачивать пустые кортежи типа void, чем иметь специальные правила для кортежей из одного элемента.
Здравствуйте, Aleх, Вы писали:
A>Возникает следующий вопрос. A>Считать ли выражения ((a, b), c) и (a, b, c) эквивалентными?
Ни в коем случае. В некоторых языках, правда, эквивалентными считаются (a, (b, c)) и (a, b, c), что довольно удобно.
A>1. Если да, то получается правило такое, что мы можем вставить содержимое вложенных кортежей в текущий. Пусть a имеет тип void, то есть a = (). Тогда получается, что ((a, b), c) эквивалентно ((), b, c), а это эквивалентно (b, c) (в первом преобразовании первый элемент внешнего кортежа преобразовался в два элемента из вложенного кортежа, а во втором преобразовании первый элемент внешнего кортежа преобразовался в ноль элементов).
Это безобразие, которое вызовет массу проблем. Проблем не будет, если туплы считать размером от 2. (а) и () — не туплы. (а) это просто а. () — это значение своего типа () а.к.а unit.
A>2. Если считать эти выражения различными, возникает проблема с кортежем единичного размера. Будет ли ((a), c) эквивалентно (a, c)? Считаются ли ((a)), (a) и a эквивалентными? Остается два варианта — либо считать эти выражения различными, либо рассматривать кортеж из одного элемента специальным образом. Считать их различными кажется дико неудобно, а иметь специальные правила для единичного кортежа — костыль, который тоже вызовет кучу проблем и граблей.
Решение простое: не иметь кортежей единичного (и нулевого) размеров. Не так уж сложно, и никаких граблей.