سؤال

أخيرا بدأت تعلم اللغات الوظيفية (EMACS LISP) وتشغيل تمييز واضح بين الوظائف والأشكال الخاصة مثل التحكم في التدفق، على سبيل المثال إذا.

هل هناك سبب أساسي / نظرية لماذا تكون الأشكال الخاصة مميزة عن الوظائف؟ هل توفر أي لغات وظيفية if?

شكرا

هل كانت مفيدة؟

المحلول

مع تقييم حريص التمييز مطلوب اللغات مع التقييم الكسول (أي Haskell) إذا وآخرون. يمكن أن تكون وظائف.

تقييم حريصة: يتم تقييم حجج الوظيفة قبل استدعاء الوظيفة، ويتم تمرير النتائج فقط إلى الوظيفة.

التقييم الكسول: حجج الوظيفة التي تم تقييمها إذا وفقط إذا تم الوصول إليها.

نصائح أخرى

إذا if كان وظيفة طبيعية، ثم كل من حججها ثم شكل و ال شكل آخر-سيكون على حد سواء يتم تقييمها قبل استدعاء if وظيفة، لأن هذه هي القاعدة تقييم الدالة: يقيم جميع الحجج لإنتاج القيم، قم بتوفير تسلسل القيم كوسائط كوسيط الوظيفة المعينة بواسطة الرمز الأول في القائمة.

بدلا من ذلك، مع if ما تريد القيام به هو تقييم واحد بالضبط واحد من ثم شكل و شكل آخر, ، ليس كليهما. من أجل قمع تقييم واحد أو آخر، تحتاج إما ماكرو أو نموذج خاص.

بلغات مثل EMACs Lisp Lisp و LISP المشتركة، أشكال خاصة بنيات مدمجة. لديهم قواعد تقييم مختلفة تدعو الوظيفة العادية. لاستدعاء الوظيفة العادية جميع الحجج يتم تقييمها. لذلك، لا يمكنك كتابة أي إذا كدالة عادية - تحدد الحالة البند الذي يتم تقييمه. عادة ما لا يمكنك كتابة النماذج الخاصة الخاصة بك - في LISP المشتركة، لا يوجد إنشاء لغة لتحديد نموذج خاص (على الرغم من أن التطبيقات الفردية يجب أن تكون قد نفذت تلك الموجودة بطريقة أو بأخرى. هذا يؤدي إلى وحدات الماكرو. مع وحدات الماكرو التي يمكنك كتابة تحويل سنوي الذي يحول تعبيرا واحدا إلى شخص آخر. لتكون قادرا على الكتابة إذا ككرو، يجب أن يكون لديك نموذج مشروط آخر، والذي يمكنك استخدامه للحصول على التعليمات البرمجية المحول. يوفر LISP الشرطية كإعدادات أساسية. دعونا نفترض أن يكون مثل هذا البناء الأساسي ، ثم يمكنك التوسع إذا في استخدام cond.

My-if as a macro في LISP المشترك:

(defmacro my-if (condition true-clause false-clause)
   `(cond (,condition ,true-clause)
          (t ,false-clause)))

وبالتالي

(my-if (foo-p) 'one 'two)

يتم توسيعها في

(cond ((foo-p) 'one)
      (t 'two))

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

في مخطط يمكنك الكتابة

(define (true t f)
  (t))

(define (false t f)
  (f))

(define (function_if c t e)
  (c t e))

وثم

(function_if true (lambda () 'true) (lambda () 'false))
==> true

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

لذلك، في بناء جملة مخطط مع المعلمات الوظيفية يمكنك تشفير المنطاقين على النحو التالي:

(define (true (t) (f))
  (t))

(define (false (t) (f))
  (f))

ثم وظيفة إذا أصبحت:

(define (function_if c (t) (e))
  (c (t) (e)))

و

(function_if true 'true 'false)
==> true

كمثال آخر، تعريف الوظيفة and يكون (define (and p (q)) (p (q) false)).

وبالمثل يمكنك تحديد or, not, while, for, ، ... كوظائف، باستخدام الترميز أعلاه من المنطمنون.

إجابة قصيرة: رقم

إجابة طويلة (إيه): (إذا ...) تتطلب التحكم في ترتيب التقييم للحجج. LISP، كونه لغة حريصة لا يمكن أن تفعل هذا في وظيفة.

الحل البديل: افعل ذلك في ماكرو:

(defmacro _if (cnd true false)
    (let (  (gcond (gensym))
            (gresp (gensym)))
        `(let ( (,gcond ,cnd) ;`#quotes
                (,gresp nil))        
            (and ,gcond       (setf ,gresp (multiple-value-list ,true)))
            (and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
            (values-list ,gresp))))

علي سبيل المثال:

[dsm@localhost:~]$ clisp -q
[1]> (defmacro _if (cnd true false)
    (let (  (gcond (gensym))
            (gresp (gensym)))
        `(let ( (,gcond ,cnd) ;`#quotes
                (,gresp nil))        
            (and ,gcond       (setf ,gresp (multiple-value-list ,true)))
            (and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
            (values-list ,gresp))))
_IF
[2]> (_if (= 1 1) (+ 2 3) "bar")
5
[3]> (_if (= 1 2) (+ 2 3) "bar")
"bar"
[4]> 

في scala من الممكن النموذج if مع التقييم الصحيح للتأثيرات الجانبية باستخدام حجج استدعاء الاسم.

def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart

هذه الميزة يمكن استخدامها لنموذج الكثير من هياكل التحكم الجديدة كذلك.

إذا كان يمكن أن تكون وظيفة في لغة وظيفية لها دلالات استدعاء الاسم (التقييم الكسول)، كما هو الحال في حساب التفاضل والتكامل Lambda أو Algol. في الواقع، أعتقد، في قلب العلاقة بين آلات تورينج ومماردا حساب التفاضل والتكامل كأسس مكافئة للحوسبة. ومع ذلك، في اللغات التي لها آثار جانبية (مثل المهام للمتغيرات) لا تستخدم الكثير متي الأشياء تحدث مهمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top