دالة مجهولة

في برمجة الحاسوب، تعد الدالة المجهولة Anonymous function ( دالة حرفية ، أو تجريد لامدا ، أو تعبير لامدا lambda expression) تعريف دالة لا يرتبط بمعرف. غالبًا ما تكون الدوال المجهولة قيمًا تمرر إلى دالات أعلى مرتبة، أو تُستخدم لإنشاء نتيجة لدالة أعلى رتبةً تحتاج إلى إرجاع دالة. إذا تم استخدام الدالة مرة واحدة فقط، أو لعدد محدود من المرات، فقد تكون الدالة المجهولة أخف من حيث البنية من استخدام دالة مسماة. الدوال المجهولة موجودة في كل مكان في لغات البرمجة الوظيفية (دالية) ولغات أخرى بدوال من الصنف الأولى، حيث تؤدي نفس الدور الذي تؤديه نوع الدالة كما تفعل الحرفيات لأنواع البيانات الأخرى.

نشأت الدوال المجهولة في عمل عالم الرياضيات ألونزو تشرتش في اختراعه لحساب تفاضل وتكامل لامبدا، حيث تكون جميع الدوال مجهولة، وذلك في عام 1936، أي قبل أجهزة الحاسوب الإلكترونية. في العديد من لغات البرمجة، يتم تقديم دوال مجهولة باستخدام الكلمة الرئيسية لامدا lambda، وغالبًا ما يشار إلى الدوال المجهولة باسم لامبدا أو تجريدات لامدا. كانت الدوال المجهولة سمة من سمات لغات البرمجة منذ عام 1958في لغة ليسب، وهناك عدد متزايد من لغات البرمجة الحديثة التي تدعم الدوال المجهولة.

أمثلة

جافا 
تدعم جافا الدوال المجهولة، المسماة تعبرات لامبدا، بدءًا من JDK 8.

يتكون تعبير لامدا من:

 قائمة مفصولة بفواصل من المعلمات الرسمية الموضوعة بين قوسين مثلاً (a,b).
 ورمز سهم .
 و جسم برمجي (في الطرف الثاني للسهم).

يمكن دائمًا حذف أنواع البيانات من المعلمات، كما يمكن حذف الأقواس إذا كان هناك معلمة واحدة فقط. يمكن أن يتكون الجسم البرمجي من عبارة برمجية واحدة أو كتلة برمجية كاملة. // بدون معلمات
() -> System.out.println("مرحباً يا عالم")

// مع معلمة (هذا المثال هو دالة تعريفية)
a -> a
 
// مع تعبير واحد
(a, b) -> a + b

// مع نوع بيانات محدد
(long id, String name) -> "id: " + id + ", name:" + name

// مع كتلة كود برمجي
(a, b) -> { return a + b; }

// مع عبارات متعددة، يحتاج ذلك كتلة برمجية
// هذا المثال يتضمن تعبيري لامبدا (الأول هو اغلاق دالي).
(id, defaultPrice) -> {
  Optional<Product> product = productList.stream().filter(p -> p.getId() == id).findFirst();
  return product.map(p -> p.getPrice()).orElse(defaultPrice);
} يتم تحويل تعبيرات لامبدا إلى «واجهات وظيفية (دالية)» (تُعرف على أنها واجهات تحتوي على طريقة مجردة واحدة فقط بالإضافة إلى واحدة أو أكثر من الأساليب الافتراضية أو الثابتة) ،  كما في المثال التالي: public class Calculator {
  interface IntegerMath {
    int operation(int a, int b);

    default IntegerMath swap() {
      return (a, b) -> operation(b, a);
    }
  }

  private static int apply(int a, int b, IntegerMath op) {
    return op.operation(a, b);
  }

  public static void main(String... args) {
    IntegerMath addition = (a, b) -> a + b;
    IntegerMath subtraction = (a, b) -> a - b;
    System.out.println("40 + 2 = " + apply(40, 2, addition));
    System.out.println("20 - 10 = " + apply(20, 10, subtraction));
    System.out.println("10 - 20 = " + apply(20, 10, subtraction.swap()));  
  }
} في هذا المثال، تم تعريف واجهة وظيفية تسمى IntegerMath . يتم تمرير تعبيرات لامبدا التي تنفذ IntegerMath في الطريقة ()apply ليتم تشغيله (تنفيذه). الأساليب الافتراضية مثل swap تعرف الطرق على الدوال.

قدمت جافا 8 آلية أخرى تسمى العنوان المرجعي للطريقة (the :: operator) لإنشاء لامدا على طريقة موجودة مسبقاً. لا يشير مرجع الطريقة إلى عدد أو أنواع القيم لأنه يتم استخراجها من الطريقة المجردة للواجهة الوظيفية. IntBinaryOperator sum = Integer::sum; في المثال أعلاه، تعلن الواجهة الوظيفية IntBinaryOperator عن طريقة مجردة int applyAsInt(int, int) ، لذا يبحث المجمّع عن طريقة int sum(int, int) في الصنف java.lang. Integer .

قيود جافا 
تحتوي تعبيرات جافا 8 على القيود التالية:

 يمكن ـللـ لامدا -ات أن تطرح استثناءات محددة، لكن هذه اللامدا-ات لن تعمل مع الواجهات التي تستخدمها Collection API.
 لا يمكن الوصول إلى المتغيرات داخل النطاق حيث يتم الإعلان عن لامدا فقط داخل لامدا إذا كانت نهائية بشكل فعال، أي إذا لم يتم تغيير المتغير داخل أو خارج نطاق لامدا.

المراجع

روابط خارجية 

 طرق مجهولة - متى يجب استخدامها؟ (مدونة عن دالة مجهولة في دلفي)
 تجميع تعبيرات لامدا: سكالا مقابل. جافا 8
 دوال مجهولة
 تعمل لامدا في لغات البرمجة المختلفة

أنواع البيانات
الوظائف الفرعية
برمجة وظيفية
حسابات اللامدا