Попытка получить мои ноги влажными, используя TypeScript, и я продолжаю работать в trouble. old function resurfaced today и как упражнение, мне было любопытно, могу ли я преобразовать его в TypeScript. Пока это была полная боль в шее.Должен ли я указывать имена параметров для типов функций более высокого порядка в TypeScript?
declare type Ord = number | string;
// type signature for f sucks really bad
// (f: Ord => Ord => boolean) would be really nice, if possible
// but instead I have to give names (_) for the parameters? dumb
const arrayCompare = (f: (_: Ord) => (_: Ord) => boolean) => ([x,...xs]: Ord[]) => ([y,...ys]: Ord[]): boolean => {
if (x === undefined && y === undefined)
return true;
else if (! f (x) (y))
return false;
else
return arrayCompare (f) (xs) (ys);
}
// here the names of the parameters are actually used
const eq = (x: Ord) => (y: Ord) : boolean => x === y;
// well at least it works, I guess ...
console.log(arrayCompare (eq) ([1,2,3]) ([1,2,3])); // true
console.log(arrayCompare (eq) (['a','b','c']) (['a','b','c'])); // true
Поэтому вопрос конкретно о (см смелое)
const arrayCompare = (f: (_: Ord) => (_: Ord) => boolean) => ...
f
ожидает функции высшего порядка типа
Ord => Ord => boolean
Но если я использую этот тип Подпись
// danger !! unnamed parameters
(f: (Ord) => (Ord) => boolean)
машинопись Предположит Ord
как имени параметра и подразумеваемого тип any
// what TypeScript thinks it means
(f: (Ord: any) => (Ord: any) => boolean)
Конечно, это не то, что я хочу, но это то, что я в любом случае. Для того, чтобы получить то, что я на самом деле хочу, я должен указать имена параметров для функции высшего порядка
// now it's correct
(f: (_: Ord) => (_: Ord) => boolean)
Но c'mon, что не имеет никакого смысла. У меня есть только доступ к f
в этом контексте, а не к параметрам, которые f
будут связываться, когда я в конце концов называть его ...
Вопрос
Почему я должен предоставить имена для более высокого порядка функции в TypeScript?
Это не имеет смысла и делает сигнатуры функций длинными, уродливыми, трудными для записи и труднее читать.
UPDATE
«, насколько это имена параметров, рассмотрим функцию, которая принимает дозвона -> (номер -> номер -> номер) ->, таким образом, исходя исключительно по типам, которые вы выбрали: добавление, вычитание, умножение, деление, мощность, сравнение которых только один имеет смысл, теперь, если параметр обратного вызова имел имя add: (number -> number -> number), выбор был бы очевиден " - Aleksey Bykov
Я счастлив, что получил возможность ответить на это. Я могу назвать кучи больше функций с подписью (number -> number -> number)
.
first
,second
,mod
,min
,max
- битовые функции
&
,|
,xor
,<<
и>>
(x, y) => sqrt(sq(x) + sq(y))
(x, y) => x + x + y + y + superglobalwhocares
- и любой другие функции вы с сон вверх
Чтобы прояснить ситуацию, я не предлагаю, чтобы сам параметр функции не должен иметь имя. Я предлагаю параметры этого параметра функции в не должны быть даны имена ...
// this
func = (f: (number => number => number)) => ...
// not this
func = (f: (foo: number) => (bar: number) => number)) => ...
Почему? так как f
не знает параметров функции, которую я буду предоставлять.
// for the record, i would never name parameters like this
// but for those that like to be descriptive, there's nothing wrong with these
const add = (addend: number) => (augend: number) => number ...
const sub = (minuend: number) => (subtrahend: number) => number ...
const divide = (dividend: number) => (divisor: number) => number ...
const mult = (multiplicand: number) => (multiplier: number) => number ...
// I could use any of these with my func
func (add ...)
func (sub ...)
func (divide ...)
func (mult ...)
Я не мог представить имена для f
«s параметров в func
если бы я попробовал! Потому что кто знает, какую функцию я буду использовать? Все они уместны.
Если я пытаюсь поставить имена на них, я сукно воображения пользователя о том, что функция способна ...
// maybe the user thinks only a division function can be specified (?)
func = (f: (dividend: number) => (divisor: number) => number) => ...
dividend
и divisor
не являются хорошей подгонкой здесь, потому что любой из перечисленных функций выше будет соответствовать. В лучшем я мог бы сделать это
// provide generic name for f's parameters
func = (f: (x: number) => (y: number) => number) => ...
Но тогда какой смысл? Это не похоже на то, что x
и y
становятся связанными идентификаторами. И x
и y
не добавили описания - что, я полагаю, приводит меня к моим точкам: они не означают, чтобы иметь имя или описание. f
имеет ноль знание того, как мы можем его использовать, но это не имеет значения; до тех пор, пока он имеет интерфейс (number => number => number)
, то есть все мы заботимся о. И это самая полезная информация, которую мы можем предоставить пользователю нашего func
относительно параметра f
.
"Было бы довольно запутанным для функции, как:
foo(cb: (number, number) => (number, string) => boolean)
Что это делает" - unional
Одинаковые точные рассуждения применяются здесь. Помимо того факта, что (cb: (number, number) => (number, string) => boolean))
является плохо спроектированной функцией (сколько полезных функций четвертого типа (4-арности) смешанного типа вы можете назвать?), это не пункт. f
не может притворяться, что знает дескрипторы о бесчисленных функциях, которые я мог придумать, используя такую подпись.
Так что мой вопрос, почему, черт возьми, я должен указать открыто бессмысленных имена для параметра функции параметров?
Упражнение
Вы можете заменить _
со значимыми именами?
const apply2 = (f: (_: number) => (_: number) => number) => (x: number) => (y: number): number => {
return f (x) (y)
};
const sqrt = (x: number): number => Math.sqrt(x);
const sq = (x: number): number => x * x;
const add = (addend: number) => (augend: number): number => addend + augend;
const pythag = (side1: number) => (side2: number): number => sqrt(add(sq(side1)) (sq(side2)));
console.log(apply2 (add) (3) (4)); // 7
console.log(apply2 (pythag) (3) (4)); // => 5
Если нет, то вы можете сделать убедительные аргументы, почему такие имена должны присутствовать в вашей машинопись подписи?
Это уже 2 значительные проблемы для одной общей функции JavaScript - если для этого нет разумного средства, я честно не вижу, как TypeScript полезен для людей. – naomik
не было проблемы для объявления функции сортировки для массива в TS когда-либо: 'sort (значения: T [], compare: (one: T, another: T) => number): T []' –
Мы определяем «проблему» иначе - 'one' и' another' являются неиспользуемыми (* бесполезными *) идентификаторами. Они недоступны для использования функцией и служат только для того, чтобы сделать сигнатуру функции дольше и сложнее, чем она должна быть. – naomik