سؤال

حسنا، لا الغش الآن.

لا، حقا، خذ دقيقة أو اثنتين وجرب هذا.

ماذا تفعل "المواقف"؟

تحرير: المبسطة وفقا لاقتراح CGRAND.

(defn redux [[current next] flag] [(if flag current next) (inc next)])

(defn positions [coll]
  (map first (reductions redux [1 2] (map = coll (rest coll)))))

الآن، ماذا عن هذا الإصدار؟

def positions(coll) {
  def (current, next) = [1, 1]
  def previous = coll[0]
  coll.collect {
    current = (it == previous) ? current : next
    next++
    previous = it
    current
  }
}

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

صحيح، الوصول إلى هذه النقطة. حسنا، يجب أن أكون صادقا وأقول إنني أتساءل عما إذا كنت أفهم رمز عباءة عندما أعود إليها بعد أشهر. بالتأكيد يمكنني التعليق على هيك من ذلك، لكنني لا أحتاج إلى التعليق على شفرة Java لفهمها.

لذلك سؤالي هو: هل هو مسألة الحصول على المزيد من استخدامات البرمجة الوظيفية؟ هل تم قراءة المعلمين البرمجة الوظيفية هذا الرمز وإيجاده نسيم لفهمه؟ أي إصدار فعل أنت تجد أسهل لفهم؟

تحرير: ما يفعله هذا الرمز هو حساب مواقع اللاعبين وفقا لنقاطهم، مع تتبع أولئك الذين يرتبطون. علي سبيل المثال:


Pos Points
1. 36
1. 36
1. 36
4. 34
5. 32
5. 32
5. 32
8. 30
هل كانت مفيدة؟

المحلول

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

وبالمثل، يمكنني قراءة اللغة الإنجليزية بسهولة أكبر من الإسبانية، ولكن هذا لا يقول أي شيء عن قابلية القراءة الجوهرية لهذه اللغات أيضا. (الإسبانية هو في الواقع ربما "لغة" أكثر قابلية للقراءة "من النوعين من حيث البساطة والاتساق، لكن ما زلت لا أستطيع قراءة ذلك). أنا أتعلم اليابانية الآن والحصول على هيك من الوقت الصعب، لكن المتحدثين اليابانيين الأصليين يقولون نفس الشيء عن اللغة الإنجليزية.

إذا أمضيت معظم حياتك في قراءة جافا، فستكون الأمور التي تبدو وكأنها Java أسهل في القراءة من الأشياء التي لا تفعل ذلك. حتى تنفق الكثير من الوقت في النظر إلى لغات Lispy التي تنظر إلى اللغات المشابهة، فمن المحتمل أن يظل هذا صحيحا.

لفهم لغة، من بين أشياء أخرى يجب أن تكون على دراية بها:

  • بناء الجملة ([vector] ضد. (list), hyphens-in-names)
  • المفردات (ماذا يفعل reductions يعني؟ كيف / أين يمكنك أن تبحث عنه؟)
  • قواعد التقييم (هل تعامل مع وظائف عمل كائنات؟ إنه خطأ في معظم اللغات.)
  • التعابير، مثل (map first (some set of reductions with extra accumulated values))

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

(use 'clojure.contrib.seq-utils)                                        ;;'
(defn positions [coll]
  (mapcat #(repeat (count %) (inc (ffirst %)))
          (partition-by second (indexed coll))))

إذا نظرنا إلى كود عباءة كتبت منذ عام، فأنا مروع في مدى سوء ذلك، لكن يمكنني قراءتها موافق. (لا يقول رمز عبيد الخاص بك أمر فظيع. لم يكن لدي مشكلة في قراءة ذلك على الإطلاق، وأنا لا guru.)

نصائح أخرى

وأنا أتفق مع تيموثي: أنت تقدم الكثير من التجريدات. إعادة صياغة التعليمات البرمجية الخاصة بك وانتهت بها:

(defn positions [coll]
  (reductions (fn [[_ prev-score :as prev] [_ score :as curr]] 
                (if (= prev-score score) prev curr))
    (map vector (iterate inc 1) coll)))

حول الكود الخاص بك،

(defn use-prev [[a b]] (= a b))
(defn pairs [coll] (partition 2 1 coll))
(map use-prev (pairs coll))

يمكن ببساطة عداد على النحو التالي:

(map = coll (rest coll))

تعديل: قد لا تكون ذات صلة بعد الآن.

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

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

هنا كيف أكتب إصدار عباءة:

(defn positions2 [coll]
  (let [current (atom 1)
        if-same #(if (= %1 %2) @current (reset! current (inc %3)))]
    (map if-same (cons (first coll) coll) coll (range (count coll)))))

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

Clojure One أكثر توافقا مع نظرة الأولى؛ على الرغم من أنه ربما أكثر أناقة. OO هي النتيجة التي تجعل اللغة أكثر "قابلة للاسترداد" في مستوى أعلى. يبدو أن اللغات الوظيفية تحتوي على أكثر "Algorithimc" (بدائية / ابتدائية) تشعر به. هذا فقط ما شعرت في الوقت الحالي. ربما سيغير ذلك عندما يكون لدي المزيد من الخبرة في العمل مع Clojure.

أخشى أن ننتصرنا في اللعبة التي يمكن أن تكون اللغة الأكثر إيجازا أو حل مشكلة في أقل خط التعليمات البرمجية.

المشكلة هي 2 طيات بالنسبة لي:

  1. ما مدى سهولة النظرة الأولى للحصول على شعور بما يفعله القانون؟ هذا مهم لصيحي التعليمات البرمجية.

  2. ما مدى سهولة تخمينها في المنطق وراء الكود؟ Verbose للغاية / اللطف؟ terse جدا؟

"اجعل كل شيء بسيط قدر الإمكان، ولكن ليس أكثر بساطة".

البرت اينشتاين

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

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

يدعم Groovy أنماط مختلفة من حل هذه المشكلة أيضا:

coll.groupBy{it}.inject([]){ c, n -> c + [c.size() + 1] * n.value.size() }

بالتأكيد لا تعيد عدلا ليكون جميلا ولكن ليس من الصعب فهمه.

أعلم أن هذا ليس إجابة على السؤال، لكنني سأكون قادرا على "فهم" الكود بشكل أفضل إذا كان هناك اختبارات، مثل:

assert positions([1]) == [1]
assert positions([2, 1]) == [1, 2]
assert positions([2, 2, 1]) == [1, 1, 3]
assert positions([3, 2, 1]) == [1, 2, 3]
assert positions([2, 2, 2, 1]) == [1, 1, 1, 4]

سيخبرني ذلك، سنة واحدة من الآن، ما من المتوقع أن يفعله الكود. أفضل بكثير من أي نسخة ممتازة من التعليمات البرمجية التي رأيتها هنا.

هل أنا حقا خارج الموضوع؟

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

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