Alright У меня есть другой ответ здесь, и я думаю, что это один довольно инновационный.
В основном проблема с выполнением чего-то похожего на ответ Наомика заключается в том, что вы создаете функции каждый раз, когда вы объединяете методы вместе.
EDIT: Это решение имеет одинаковую проблему, однако этот ответ остается в образовательных целях.
Итак, здесь я предлагаю способ просто привязать новые значения к вашим методам, которые в основном являются независимыми функциями. Это дает дополнительное преимущество - возможность импортировать функции из разных модулей в новый объект.
Хорошо, так что вот оно.
const assoc = (prop, value, obj) =>
Object.assign({},obj,{[prop]: value})
const reducer = ($values, accumulate, [key,val]) => assoc(key, val.bind(undefined,...$values), accumulate)
const bindValuesToMethods = ($methods, ...$values) =>
Object.entries($methods).reduce(reducer.bind(undefined, ...$values), {})
const prepareInstance = (instanceMethods, staticMethods = ({})) => Object.assign(
bindValuesToMethods.bind(undefined, instanceMethods),
staticMethods
)
// Let's make our class-like function
const RightInstanceMethods = ({
chain: (x,f) => f(x),
map: (x,f) => Right(f(x)),
fold: (x,l,r) => r(x),
inspect: (x) => `Right(${x})`
})
const RightStaticMethods = ({
of: x => Right(x)
})
const Right = prepareInstance(RightInstanceMethods,RightStaticMethods)
Теперь вы можете сделать
Right(4)
.map(x=>x+1)
.map(x=>x*2)
.inspect()
Вы также можете сделать
Right.of(4)
.map(x=>x+1)
.map(x=>x*2)
.inspect()
У вас также есть дополнительное преимущество, которое позволяет экспортировать из модулей в качестве такого
export const Right = prepareInstance(RightInstanceMethods,RightStaticMethods)
Пока вы не получаете ClassInstance.constructor
у вас есть FunctorInstance.name
(примечание, возможно, потребуется polyfill Function.name
и/или не использовать функцию стрелки для экспорта на совместимость браузера с Function.name
целей)
export function Right(...args){
return prepareInstance(RightInstanceMethods,RightStaticMethods)(...args)
}
PS - Новые предложения Имя для prepareInstance приветствовало см GIST.
https://gist.github.com/babakness/56da19ba85e0eaa43ae5577bc0064456
Сообщите мне, если вы нашли способ, хотя! –
Имейте в виду, что обход - это просто определить фабричную функцию (с немного другим именем), которая просто возвращает новый Foo (arg); '. – jfriend00
Да, я рассмотрел это, но тогда есть асимметрия между именем конструктора и именем класса: { – naomik