1. Как в рантайме правильнее разграничить вызов нативных (реализованных на Java) функций и вызов функций на JavaScript (это весьма разные сущности)?
JsValue call(scope: JsScope, context: JsValue, args: ArrayList<JsValue>)
TypeError: бла-бла-бла is not a function
, а в классах функций (JsNativeFunction
и JsFunction
) переопредели его чтобы возвращал что-то.2. Как оптимальнее хранить scopes? Через Hashtable/HashMap в виде вектора (имитация стека) - нормальное решение?
3. Как правильно организовать поиск функций в цепочке прототипов объекта? Например, мы ищем функцию; она находится в прототипе, ссылку на который мы храним. Но при вызове такая функция должна работать с полями данных исходного объекта, а не прототипа, или прототипа прототипа и т.д. В JavaScript всё будет в такой ситуации работать корректно, а как такое грамотно эмулировать?
x.foo(42)
разворачивается во что-то типа этого:JsObject xVar = scope.getVar("x");
xVar
.attr("foo") // ищет атрибут в объекте или в прототипе
.call(scope, xVar, Arrays.asList(JsInt(42)));
call
- это и есть контекст, то есть объект у которого вызывается метод.4. Эффективный алгоритм разбора выражений тоже не помешал бы. Как быстро разобрать строку, зная приоритеты операторов, корректно выделить все круглые скобки, которые могут быть вложены друг в друга, и т.д. Ссылки на любую литературу, в том числе англоязычную, приветствуются.
* -> *
(то есть это должен быть дженерик с одним параметром) и для него должна быть реализована функция map
:map :: Functor f => (a -> b) -> (f a -> f b)
fmap
, а в Fantasy Land сигнатура выглядит так:map :: Functor f => f a ~> (a -> b) -> f b
map
должны выполняться определённые законы, не буду их копировать сюда, просто оставлю ссылку: https://github.com/fantasyland/fantasy-land#functorArray
— map
применяет функцию к каждому элементу массива.Future
— map
применяет функцию к значению когда оно зарезолвится.Maybe
— map
применяет функцию к значению, если оно существует, иначе возвращает Nothing
.function Foo() {
let counter = 0;
Object.defineProperty(this, "counter", {
get() {
return counter++;
}
})
}
const foo = new Foo();
foo.counter; // => 0
foo.counter; // => 1
Еще я понял, что ramda это самая близкая к фп библиотека , а другие что то типо либ общего назначения.
Подскажите с какой библиотеки лучше начать.
А может Elm?
Еще такая проблема , что я обычно читаю документацию с плагином google translate и нормально понимаю смысл, но с фп у меня так не выходит (пытался читать документацию ramda и underscore). Может сталкивались с переводами документаций или их подобиями?
от 1 до 1000 элементов
(def exists #(.exists (clojure.java.io/as-file %)))
(def process-files
(comp
(map #(do-something %)))
(filter #(exists (:path %))))
(sequence process-files audios)
import { compose, filter, into, map } from 'ramda';
const processFiles = compose(
map(audio => doSomething(audio)),
filter(audio => fs.existsSync(audio.path))
);
into([], processFiles, audios);
filterMap
, которая внутри будет императивной, но при использовании будет выглядеть вполне нормально:function filterMap(filterFn, mapFn) {
return arr => {
const newArr = [];
for (let x of arr) {
if (filterFn(x)) newArr.push(mapFn(x));
}
return newArr;
}
}
const processFiles = filterMap(
audio => fs.existsSync(audio.path),
audio => doSomething(audio)
);
processFiles(audios);
class Human {
constructor(name) {
this.name = name;
}
sayName() {
console.log(`My name is ${this.name}`);
}
}
function validBraces(text) {
const stack = [];
for (let c of text) {
if ('([{'.includes(c)) stack.push(c);
else if (')]}'.includes(c)) {
if ('([{'.indexOf(stack.pop()) !== ')]}'.indexOf(c)) {
return false;
}
}
}
return true;
}
function numberFormat(num) {
if (typeof num !== "string") {
return numberFormat(num.toString())
} else {
if (num.length < 4) {
return num
} else {
return numberFormat(num.slice(0, num.length - 3)) + " " + num.slice(num.length - 3)
}
}
}