"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > تحسين وظيفة كاري TypeScript: من الأنواع الثابتة إلى الأنواع المتغيرة

تحسين وظيفة كاري TypeScript: من الأنواع الثابتة إلى الأنواع المتغيرة

تم النشر بتاريخ 2024-08-28
تصفح:618

Optimizing a TypeScript Curry Function: From Static Types to Variadic Types

Currying هي تقنية برمجة وظيفية تقوم بتحويل دالة ذات وسائط متعددة إلى سلسلة من الوظائف، كل منها يأخذ وسيطة واحدة. يعد هذا الأسلوب مفيدًا بشكل خاص لإنشاء المزيد من الوظائف المعيارية والقابلة لإعادة الاستخدام، مما يسمح بالتطبيق الجزئي للوسائط. في TypeScript، يتطلب تنفيذ دالة الكاري الفعالة إدارة الكتابة بعناية، خاصة عند التعامل مع عدد متغير من الوسائط.

في هذه المقالة، سنستكشف تطبيقين مختلفين لوظيفة الكاري في TypeScript. يستخدم الأول واجهات ذات أنواع ثابتة، بينما يتبنى الثاني نهجًا أكثر مرونة باستخدام واجهة واحدة مع أنواع متنوعة. سنقوم بتحليل الاختلافات بين هذين التطبيقين ومناقشة مزايا النهج الأكثر تحسينًا.

التنفيذ الأولي: واجهات ذات أنواع ثابتة

تعريف الواجهات

في التنفيذ الأول، قمت بتحديد سلسلة من الواجهات للتعامل مع الوظائف المتجانسة بأعداد مختلفة من الوسائط. تتوافق كل واجهة مع دالة بعدد محدد من الوسائط:

interface CurryFunction1 {
    (arg1: T1): R;
}

interface CurryFunction2 {
    (arg1: T1): CurryFunction1;
}

interface CurryFunction3 {
    (arg1: T1): CurryFunction2;
}

interface CurryFunction4 {
    (arg1: T1): CurryFunction3;
}

interface CurryFunction5 {
    (arg1: T1): CurryFunction4;
}

interface CurryFunction6 {
    (arg1: T1): CurryFunction5;
}
تنفيذ وظيفة الكاري

يتم تعريف وظيفة الكاري لاستخدام هذه الواجهات لوظائف الكاري مع ما يصل إلى ست وسائط:

function curry(fn: (arg1: T1, arg2: T2) => R): CurryFunction2;
function curry(fn: (arg1: T1, arg2: T2, arg3: T3) => R): CurryFunction3;
function curry(fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => R): CurryFunction4;
function curry(fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5) => R): CurryFunction5;
function curry(fn: (arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6) => R): CurryFunction6;
function curry(fn: Function) {
    return function curried(...args: any[]) {
        if (args.length >= fn.length) {
            return fn(...args);
        } else {
            return (...args2: any[]) => curried(...args, ...args2);
        }
    };
}
اختبار وظيفة الكاري

يتم بعد ذلك اختبار هذه الوظيفة للتأكد من أنها تعمل بشكل صحيح مع أعداد مختلفة من الوسائط:

function testCurry() {
    const add = (a: number, b: number) => a   b;
    const curriedAdd = curry(add);
    assert(curriedAdd(1)(2) === 3, 'Test curry function with 2 arguments');

    const add3Args = (a: number, b: number, c: number) => a   b   c;
    const curriedAdd3Args = curry(add3Args);
    assert(curriedAdd3Args(1)(2)(3) === 6, 'Test curry function with 3 arguments');
}
تحليل التنفيذ

على الرغم من أن هذا التنفيذ واضح ونموذجي لـ TypeScript، إلا أنه يحتوي على بعض القيود. والجدير بالذكر أنه يتطلب تعريف واجهات متعددة لكل عدد ممكن من الوسائط، مما يجعل التعليمات البرمجية زائدة عن الحاجة ويصعب صيانتها. بالإضافة إلى ذلك، فإن التعامل مع أكثر من ست وسيطات يتطلب إضافة المزيد من الواجهات، مما يزيد من التعقيد.

التنفيذ الأمثل: واجهة واحدة مع أنواع متنوعة

مقدمة إلى أنواع Variadic

لتحسين وظيفة الكاري، اعتمدت نهجًا أكثر ديناميكية باستخدام واجهة عامة واحدة مع أنواع متنوعة. يسمح هذا الأسلوب بمعالجة عدد عشوائي من الوسائط دون الحاجة إلى تحديد واجهة منفصلة لكل حالة.

تنفيذ وظيفة الكاري مع أنواع متنوعة

في هذا الإصدار المحسّن، يتم تنفيذ وظيفة الكاري باستخدام واجهة عامة واحدة تستفيد من الأنواع المتنوعة لـ TypeScript للتعامل مع عدد عشوائي من الوسائط:

type CurryFunction = T extends [infer A, ...infer Rest]
  ? (arg: A) => CurryFunction
  : R;

function curry(fn: (...args: T) => R): CurryFunction {
  return function curried(...args: unknown[]): unknown {
    if (args.length >= fn.length) {
      return fn(...args as T);
    } else {
      return (...args2: unknown[]) => curried(...([...args, ...args2] as unknown[]));
    }
  } as CurryFunction;
}
فوائد التنفيذ الأمثل
  1. تقليل التعقيد : باستخدام واجهة عامة واحدة CurryFunction، يلغي هذا التنفيذ الحاجة إلى إنشاء واجهات متعددة لكل عدد ممكن من الوسائط. وهذا يجعل الكود أكثر إيجازًا وأسهل في الصيانة.

  2. دعم عدد عشوائي من الوسائط : الاستفادة من الأنواع المتغيرة تسمح لهذه الوظيفة بدمج الوظائف مع أي عدد من الوسائط دون تعديل التنفيذ. وبالتالي فإن الوظيفة أكثر مرونة وقدرة على التكيف مع السيناريوهات المختلفة.

  3. تحسين الكتابة : تتيح الكتابة الديناميكية لـ TypeScript استنتاج أنواع الوسائط بدقة، مما يوفر فحصًا أقوى للنوع أثناء التطوير، ويقلل من مخاطر الأخطاء، ويحسن إكمال التعليمات البرمجية.

  4. اختبار وظيفة الكاري الأمثل
تم أيضًا اختبار هذا الإصدار من وظيفة الكاري للتأكد من أنه يعمل بشكل صحيح:


اختبار الوظيفةCurry() { const add = (a: number, b: number) => a b; const curriedAdd = curry(add); تأكيد(curriedAdd(1)(2) === 3, 'اختبار دالة الكاري باستخدام وسيطتين'); const add3Args = (a: number, b: number, c: number) => a b c; const curriedAdd3Args = curry(add3Args); تأكيد(curriedAdd3Args(1)(2)(3) === 6, 'اختبار دالة الكاري بثلاث وسائط'); const add4Args = (a: number, b: number, c: number, d: number) => a b c d; const curriedAdd4Args = curry(add4Args); تأكيد(curriedAdd4Args(1)(2)(3)(4) === 10, 'اختبار دالة الكاري بأربع وسائط'); }

function testCurry() {
    const add = (a: number, b: number) => a   b;
    const curriedAdd = curry(add);
    assert(curriedAdd(1)(2) === 3, 'Test curry function with 2 arguments');

    const add3Args = (a: number, b: number, c: number) => a   b   c;
    const curriedAdd3Args = curry(add3Args);
    assert(curriedAdd3Args(1)(2)(3) === 6, 'Test curry function with 3 arguments');

    const add4Args = (a: number, b: number, c: number, d: number) => a   b   c   d;
    const curriedAdd4Args = curry(add4Args);
    assert(curriedAdd4Args(1)(2)(3)(4) === 10, 'Test curry function with 4 arguments');
}

يعد الانتقال من بنية ذات واجهات متعددة إلى واجهة عامة واحدة مثالًا رائعًا لكيفية فهم وتطبيق مفاهيم TypeScript المتقدمة يمكن أن يؤدي إلى حلول أكثر أناقة وكفاءة.

بيان الافراج تم إعادة إنتاج هذه المقالة على: https://dev.to/francescoagati/optimizing-a-typescript-curry-function-from-static-types-to-variadic-types-2ma0?1 إذا كان هناك أي انتهاك، يرجى الاتصال بـ Study_golang @163.com حذف
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3