كلوجر:إنشاء وظائف ديناميكيًا من الخريطة — هل حان وقت استخدام الماكرو؟

StackOverflow https://stackoverflow.com//questions/12654919

سؤال

لدي وظيفة تبدأ هكذا:

(defn data-one [suser]
    (def suser-first-name
       (select db/firstNames
            (fields :firstname)
            (where {:username suser})))
    (def suser-middle-name
        (select db/middleNames
            (fields :middlename)
            (where {:username suser})))
    (def suser-last-name
         (select db/middleNames
             (fields :lastname)
             (where {:username suser})))
    ;; And it just continues on and on...
        )

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

لذلك توصلت إلى ما يلي للبدء:

(def data-input {:one '[suser-first-name db/firstNames :firstname] 
                      '[suser-middle-name db/middleNames :middlename]
                      '[suser-last-name db/lastNames :lastname]})

(defpartial data-build [data-item suser]
    ;; data-item takes the arg :one in this case
     `(def (data-input data-item)
        (select (data-input data-item)
            (fields (data-input data-item))
            (where {:username suser}))))

هناك بالفعل بعض الأسئلة هنا:

- كيف يمكنني تفكيك مدخلات البيانات بحيث تقوم بإنشاء وظائف x عندما تكون x غير معروفة، على سبيل المثال.أن قيم :one غير معروفة، وأن كميات المفاتيح في إدخال البيانات غير معروفة.

- أعتقد أن هذا هو الوقت المناسب لإنشاء ماكرو، لكنني لم أقم ببناء واحد من قبل، لذلك أنا متردد في الفكرة.

ولإعطاء القليل من السياق، يجب أن تُرجع الوظائف قيمًا ليتم تفكيكها، ولكن أعتقد أنه بمجرد حل هذه القطعة، سيكون تعميم كل هذا ممكنًا:

(defpage "/page-one" []
    (let [suser (sesh/get :username)]       
    (data-one suser)
        [:p "Firat Name: " 
            [:i (let [[{fname :firstname}] suser-first-name]
                (format "%s" fname))]
        [:p "Middle Name: "  
            [:i (let [[{mname :emptype}] suser-middle-name]
                (format "%s" mname))]
        [:p "Last Name: " 
            [:i (let [[{lname :months}] suser-last-name]
                    (format "%s" lname))]]))
هل كانت مفيدة؟

المحلول

بعض الاقتراحات:

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

لذلك أود أن أقترح شيئًا مثل:

(def data-input [[:suser-first-name db/firstNames :firstname] 
                 [:suser-middle-name db/middleNames :middlename]
                 [:suser-last-name db/lastNames :lastname]])

(def data-build [data-input suser]
  (loop [output {}
         items (seq data-input)]
    (if items
      (recur
        (let [[kw db fieldname] (first items)]
          (assoc output kw (select db (fields fieldname) (where {:username suser})))) 
        (next items))
      output)))

لم يتم اختباره لأنني لا أملك إعداد قاعدة البيانات الخاصة بك - ولكن نأمل أن يمنحك ذلك فكرة عن كيفية القيام بذلك بدون وحدات ماكرو أو وحدات عالمية قابلة للتغيير!

نصائح أخرى

سؤال لطيف.بادئ ذي بدء، هنا ماكرو الذي طلبته: giveacodicetagpre.

يمكنك الاتصال به مثل هذا: giveacodicetagpre.

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


الآن، إذا كنت لا تمانع في التوصية بحل آخر، فمن المحتمل أن اختار استخدام وظيفة واحدة مغلقة حول التكوين.شيء من هذا القبيل: giveacodicetagpre.

بالمناسبة هناك طريقة أخرى لاستخدام Korma: giveacodicetagpre.

لمزيد من المعلومات، أوصي بشدة بالنظر إلى مصادر Korma.

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