JS каррирование валидность введенных данных
Как написать функцию, которая может быть вызвана следующим образом:
curryStrings('first')('second')('third')().
Результатом вызова данной функции должна являться новая строка, содержащая все переданные таким образом строки.
Если одно из значений не является валидной строкой (пустая строка - это валидная строка), то возвращать результат, полученный до текущего момента.
Также функция может принимать второй необязательный параметр. Он также должен являться валидной строкой. Результирующая строка должна содержать все переданные строки, разделённые значением separator.
concatStrings('first')('second')('third')()
//'firstsecondthird'
concatStrings('first', '123')('second')('third')()
//'first123second123third'
если переданный аргумент не является строкой, нужно выводить все предыдущие значения:
concatStrings('first')(333)('second')
///'first'
вот мой код, подскажите, пожалуйста, что я делаю не правильно?
const concatStrings = (p, q, r, s) => p + q + r + s;
function curry(fn) {
const N = fn.length;
let isValidString;
let resultString;
function innerFn(n, args) {
return function actualInnerFn(a) {
if (typeof a === 'string') {
if (n <= 1) {
return fn(...args, a);
}
}
if (typeof a !== 'string') {
return fn(args);
}
return innerFn(n - 1, [...args, a]);
}
}
/* if (!isValidString) {
return resultString;
} */
return innerFn(N, [])
}
const sum4 = curry(concatStrings);
console.log(sum4('first')('second')(123)('fourth'));
Надеюсь, я максимально понятно объяснила. Всем огромное спасибо за участие и помощь!
Ответы (1 шт):
Ультимативная реализация
но советую использовать с явным приведением к строке: ""+con(...)
function curry(func) {
let args = [], isFlagToReset = false;
let selfRetFunc = function(...str) {
if (isFlagToReset) {
isFlagToReset = false;
args = [];
}
args.push(str);
return selfRetFunc;
}
let getResult = function(isOrdinaryCall = false) {
if (isOrdinaryCall) return Function.prototype.toString.call(selfRetFunc);
isFlagToReset = true;
return func(args);
}
selfRetFunc.valueOf = getResult;
selfRetFunc.toString = getResult;
return selfRetFunc;
}
function concatSpec(strs) {
let separator = "", result = "";
for (let str of strs) {
if (str[0] && typeof str[0] !== "string") return result;
if (str[0]) result += str[0];
if (str[1]) separator = str[1];
result += separator;
}
return result;
}
let con = curry(concatSpec);
console.log(con("one"));
console.log(con("one")("two"));
console.log(con("one")("two")("three"));
console.log(con("one")("two")(3)("four"));
console.log(con("one")("two")("three")("four")("five"));
console.log(con("one", "-repeat-")("two")("three")("four")("five"));
console.log(con("", "-repeat-")()("three")("four")("five"));
let f = con("tes1-")("-test2");
console.log("Type of f is " + typeof f);
console.log(f);
console.log("Test f value: " + (f+""));
console.log("f.toString() is same: " + f.toString());
console.log("Get internal code: " + f.toString(true));
Самое простое ограничение для числа аргументов - указать наибольшее число аргументов при создании функции: curry(concat, 5) - ожидается 5 вызовов, но число может быть увеличено (условие: написать функцию для бесконечного каррирования).
isValid позволяет предотвратить исполнение целевой функции для всех вызовов, следующих после неверного, включая неверный (условие: если переданный аргумент не является строкой, нужно выводить все предыдущие значения).
Так как длина может не соответствовать ожидаемой, необходимо определять число вызовов с помощью callCount.
Заканчивать запись, когда встречается не строка
function curry(func, max) {
let strs = [], isValid = true, callCount = 0;
let selfRetFunc = function(str) {
if (callCount == 0) strs = [];
if (typeof str !== "string") isValid = false;
if (isValid) strs.push(str);
if (++callCount < max) return selfRetFunc;
isValid = true, callCount = 0;
return func(strs);
}
return selfRetFunc;
}
concat = (strs) => strs.join("");
let con5 = curry(concat, 5);
console.log(con5(1)("two ")("three ")("four ")("five "));
console.log(con5("one ")(2)("three ")("four ")("five "));
console.log(con5("one ")("two ")(3)("four ")("five "));
console.log(con5("one ")("two ")("three ")(4)("five "));
console.log(con5("one ")("two ")("three ")("four ")(5));
console.log(con5("one ")("two ")("three ")("four ")("five "));
Вставлять строковые представления не строк после каждого нового элемента
function curry(func, max) {
let strs = [], afterEveryArgs = [], callCount = 0;
let selfRetFunc = function(str) {
if (callCount == 0) strs = [];
if (typeof str !== "string") afterEveryArgs.push(str+"");
else {
strs.push(str);
strs.push(...afterEveryArgs);
}
if (++callCount < max) return selfRetFunc;
callCount = 0, afterEveryArgs = [];
return func(strs);
}
return selfRetFunc;
}
concat = (strs) => strs.join("");
let con5 = curry(concat, 5);
console.log(con5(1)("two ")("three ")("four ")("five "));
console.log(con5("one ")(2)("three ")("four ")("five "));
console.log(con5("one ")("two ")(3)("four ")("five "));
console.log(con5("one ")("two ")("three ")(4)("five "));
console.log(con5("one ")("two ")("three ")("four ")(5));
console.log(con5("one ")(2)("three ")(4)("five "));
Вставлять строки, которые были вторым аргументом, после каждого нового элемента, включая текущий
function curry(func, max) {
let strs = [], afterEveryArgs = [], callCount = 0;
let selfRetFunc = function(...str) {
if (callCount == 0) strs = [];
if (str[1]) afterEveryArgs.push(str[1]);
strs.push(str[0]);
strs.push(...afterEveryArgs);
if (++callCount < max) return selfRetFunc;
callCount = 0, afterEveryArgs = [];
return func(strs);
}
return selfRetFunc;
}
concat = (strs) => strs.join("");
let con5 = curry(concat, 5);
console.log(con5("one", "--repeat--")("two")("three")("four")("five"));
Вставлять строки, которые были вторым аргументом, после каждого нового элемента, включая текущий, причём количество вызовов определяется динамически (по стоп-слову)
function curry(func, stopElement = "\EOI") {
let strs = [], ret_strs = [], afterEveryArgs = [];
let selfRetFunc = function(...str) {
if (str[1]) afterEveryArgs.push(str[1]);
if (str[0] != stopElement) {
strs.push(str[0]);
strs.push(...afterEveryArgs);
return selfRetFunc;
}
ret_strs = [...strs];
afterEveryArgs = [];
strs = [];
return func(ret_strs);
}
return selfRetFunc;
}
concat = (strs) => strs.join("");
let con = curry(concat);
console.log(con("one", "--repeat--")("two")("three")("four")("five")("\EOI"));
console.log(con("one")("two")("three")("four")("five")("\EOI"));
Вставлять строки, которые были вторым аргументом, после каждого нового элемента, включая текущий, причём количество вызовов определяется динамически (по стоп-слову), если попадается не строка, то заканчивать запись и вывести всё, что было записано
function curry(func, stopElement = "\EOI") {
let strs = [], ret_strs = [], afterEveryArgs = [], isValid = true;
let selfRetFunc = function(...str) {
if (str[1]) afterEveryArgs.push(str[1]);
if (typeof str[0] !== "string") isValid = false;
if (str[0] != stopElement) {
if (isValid) {
strs.push(str[0]);
strs.push(...afterEveryArgs);
}
return selfRetFunc;
}
ret_strs = [...strs];
afterEveryArgs = [];
strs = [];
isValid = true;
return func(ret_strs);
}
return selfRetFunc;
}
concat = (strs) => strs.join("");
let con = curry(concat);
console.log(con("one", "--repeat--")("two")("three")("four")("five")("\EOI"));
console.log(con("one")("two")("three")("four")("five")("\EOI"));
console.log(con("one")("two")(3)("four")("five")("\EOI"));
console.log(con("one", "--repeat--")("two")("three")("four")(5)("\EOI"));