دعونا نتخيل موضوع التكوين الوظيفي ، وكذلك توضيح معنى مشغل / خط أنابيب التكوين.
TL ؛ د
يؤلف وظائف مثل رئيسه:

التطبيقات الشائعة compose
- عندما يتم استدعائها ، فإنها تنشئ وظائف جديدة وجديدة تعتمد على التكرار ، ما هي العيوب وكيفية التغلب عليها.
يمكنك اعتبار دالة الإنشاء كدالة خالصة تعتمد فقط على الوسائط. وبالتالي ، عند إنشاء نفس الوظائف بنفس الترتيب ، يجب أن نحصل على وظيفة مماثلة ، ولكن في عالم JavaScript هذا ليس كذلك. أي دعوة للتأليف - تُرجع وظيفة جديدة ، وهذا يؤدي إلى إنشاء المزيد والمزيد من الوظائف الجديدة في الذاكرة ، بالإضافة إلى مشاكل حفظها ومقارنتها وتصحيحها.
يجب القيام بشيء ما.
الدافع
يُنصح بشدة بعدم إنشاء كائنات جديدة وإعادة استخدام النتائج السابقة لوظيفة الإنشاء. تتمثل إحدى مشكلات مطور React في تطبيق shallowCompare ، والذي يعمل مع تكوين الوظيفة. على سبيل المثال ، ستنشئ دائمًا تركيبة إرسال حدث مع رد اتصال وظيفة جديدة ، مما سيؤدي إلى تحديث قيمة الخاصية.
ليس للتطبيقات الشائعة للتكوين هوية قيمة الإرجاع.
جزئيًا ، يمكن حل مشكلة هوية الأغنية عن طريق تدوين الحجج. ومع ذلك ، تظل مسألة الهوية الترابطية:
import {memoize} from 'ramda' const memoCompose = memoize(compose) memoCompose(a, b) === memoCompose(a, b)
بالطبع ، يساعد استخدام وظائف النقر في تصحيح الأخطاء التي لها تعبير واحد في النص. ومع ذلك ، من المستحسن أن يكون مكدس مكدس مسطحًا قدر الإمكان للتصحيح.
- تخلص من العودية ذات الصلة النفقات العامة:
التنفيذ العودية للتكوين الوظيفي له حمولة ، مما يخلق عناصر جديدة في مكدس الاستدعاء. عند استدعاء تكوين مكون من 5 وظائف أو أكثر ، يكون ذلك ملحوظًا بشكل ملحوظ. وباستخدام الأساليب الوظيفية في التطوير ، من الضروري بناء التراكيب من عشرات الوظائف البسيطة جدًا.
الحل
قم بعمل monoid (أو semigroupoid مع دعم لمواصفات الفئة) من حيث fantasy-land:
import compose, {identity} from 'lazy-compose' import {add} from 'ramda' const a = add(1) const b = add(2) const c = add(3) test('Laws', () => { compose(a, compose(b, c)) === compose(compose(a, b), c) // compose(a, identity) === a //right identity compose(identity, a) === a //left identity }
استخدام الحالات
- مفيد في تحفيظ التراكيب المركبة عند العمل مع المحررين. على سبيل المثال ل redux / mapStateToProps و
إعادة تحديد. - تكوين العدسات.
يمكنك إنشاء وإعادة استخدام العدسات المكافئة بدقة التي تركز في نفس المكان.
import {lensProp, memoize} from 'ramda' import compose from 'lazy-compose' const constantLens = memoize(lensProp) const lensA = constantLens('a') const lensB = constantLens('b') const lensC = constantLens('c') const lensAB = compose(lensB, lensA) console.log( compose(lensC, lensAB) === compose(lensC, lensB, lensA) )
- عمليات الاسترجاعات المحفوظة ، مع القدرة على تكوين الوظيفة النهائية لإرسال حدث.
في هذا المثال ، سيتم إرسال رد الاتصال نفسه إلى عناصر القائمة.
```jsx import {compose, constant} from './src/lazyCompose' // constant - returns the same memoized function for each argrum // just like React.useCallback import {compose, constant} from 'lazy-compose' const List = ({dispatch, data}) => data.map( id => <Button key={id} onClick={compose(dispatch, makeAction, contsant(id))} /> ) const Button = React.memo( props => <button {...props} /> ) const makeAction = payload => ({ type: 'onClick', payload, }) ```
تكوين كسول من مكونات React دون إنشاء مكونات ترتيب أعلى. في هذه الحالة ، ستنهي التركيبة البطيئة مجموعة الوظائف ، دون إنشاء عمليات إغلاق إضافية. هذا السؤال يقلق العديد من المطورين الذين يستخدمون مكتبة recompose.
import {memoize, mergeRight} from 'ramda' import {constant, compose} from './src/lazyCompose' const defaultProps = memoize(mergeRight) const withState = memoize( defaultState => props => { const [state, setState] = React.useState(defaultState) return {...props, state, setState} } ) const Component = ({value, label, ...props)) => <label {...props}>{label} : {value}</label> const withCounter = compose( ({setState, state, ...props}) => ({ ...props value: state, onClick: compose(setState, constant(state + 1)) }), withState(0), ) const Counter = compose( Component, withCounter, defaultProps({label: 'Clicks'}), )
Monads ومقدمي الطلبات (من حيث fantasy-land) مع تكافؤ صارم من خلال التخزين المؤقت نتيجة التكوين. إذا قمت بالوصول إلى قاموس الكائنات التي تم إنشاؤها مسبقًا داخل مُنشئ الكتابة ، فستحصل على ما يلي:
type Info = { age?: number } type User = { info?: Info } const mayBeAge = LazyMaybe<Info>.of(identity) .map(getAge) .contramap(getInfo) const age = mayBeAge.ap(data) const maybeAge2 = LazyMaybe<User>.of(compose(getAge, getInfo)) console.log(maybeAge === maybeAge2) // , //
لقد تم استخدام هذا النهج لفترة طويلة ، لقد قمت بتصميم المستودع هنا .
حزمة NPM: npm i lazy-compose
.
من المثير للاهتمام الحصول على ملاحظات حول إغلاق ذاكرة التخزين المؤقت للوظائف التي تم إنشاؤها في وقت التشغيل اعتمادًا على عمليات الإغلاق.
محدث
أتوقع أسئلة واضحة:
نعم ، يمكنك استبدال الخريطة بـ WeakMap.
نعم ، تحتاج إلى تمكين توصيل ذاكرة التخزين المؤقت لجهة خارجية كبرنامج وسيط.
يجب ألا ترتب مناقشة حول موضوع ذاكرات التخزين المؤقت ؛ لا توجد استراتيجية مثالية للتخزين المؤقت.
لماذا الذيل والرأس ، إذا كان كل شيء في القائمة - الذيل والرأس ، جزء من التنفيذ مع المذكرة على أساس أجزاء من التكوين ، وليس كل وظيفة على حدة.