كيف يمكنني تنفيذ وظيفة "تقليل الخريطة" كسول؟
سؤال
أحاول تنفيذ وظيفة "تخفيض الخريطة". أي أنه يجب أن يعيد تسلسلًا يتكون من نتيجة التقديم f
إلى أول 2 العناصر من coll
, ، تليها نتيجة التقديم f
إلى هذه النتيجة والبند الثالث في coll
, ، إلخ.
(def c [[0 0 0 0] [1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]])
(defn- sum-vector [v1 v2]
(map + v1 v2))
(defn reduce-map [f coll & acc]
(if (< (count coll) 2)
(if (empty? acc) coll acc)
(let [head (apply f (take 2 coll))
tail (drop 2 coll)]
(recur f (conj tail head) (conj acc head)))))
على سبيل المثال ، استدعاء هذه الوظيفة مثل هذه:
(reduce-map sum-vector c)
يجب أن تعود:
[[1 0 0 0] [1 1 0 0] [1 1 1 0] [1 1 1 1]]
(في الواقع ، من المحتمل أن يعيد العنصر الأول غير المعدل أيضًا ، لتقليد أفضل map
, ، لكن يمكنني إصلاح ذلك لاحقًا.)
الآن ، الآن ، هذا ما يعيده:
((1 1 1 1) (1 1 1 0) (1 1 0 0) (1 0 0 0))
كيف يمكنني "الدفع" في نهاية A (NY) seq؟
إذا استبدلت reduce-map
إلى عن على recur
, ، هذا ما يعود إليه:
(((1 1 1 1) ((1 1 1 0) ((1 1 0 0) ((1 0 0 0))))))
ماهو الفرق بين recur
والروح الحقيقية في الكود الخاص بي أعلاه؟
و، هل هناك طريقة مدمجة ، أو أفضل ، أو أكثر احتمالا ، للتنفيذ reduce-map
?
أخيرًا ، أود أن يكون تسلسل الإخراج كسولًا. هل ألف كل شيء في lazy-seq
?
المحلول
هذا يبدو وكأنه يشبه قليلا reductions
.
أما بالنسبة لـ "الدفع" في نهاية SEQ: في SEQS ، لا تملك "نهاية" ، راجع (iterate inc 0)
.
فيما يتعلق بـ "الدفع" في نهاية القائمة: لا يتم تصميم القوائم لذلك. استخدم ناقل. بذرة المتراكم الخاص بك مع []
, ، ليس nil
.
بما يخص lazy-seq
: استخدم العودية "الحقيقية" بدلاً من recur
. مثال هنا:
(defn integer-seq
[start]
(lazy-seq
(cons start (integer-seq (inc start)))))