سؤال

أنا أحاول clojure أنا في محاولة لمعرفة كيفية تنفيذ الخوارزمية التالية,

أنا أقرأ من تيار الإدخال أريد الاستمرار في القراءة حتى أنه ليس محدد حرف.

يمكنني أن أفعل هذا في جافا مع حلقة while ولكن أنا لا يمكن أن يبدو لمعرفة كيفية القيام بذلك في clojure?

while
   read
   readChar != delimiter

   do some processing....
end while
هل كانت مفيدة؟

المحلول

وأنا لا أعرف كلوجر، ولكن يبدو أن مثل نظام، فإنه يدعم "السماح حلقات":

(loop [char (readChar)]
   (if (= char delimiter)
       '()
       (do (some-processing)
           (recur (readChar)))))

وهذا الأمل هو ما يكفي للحصول على انك بدأته. أشرت إلى http://clojure.org/special_forms#toc9 للإجابة على هذا السؤال.

ملحوظة: أنا أعلم أن كلوجر يشجع آثار جانبية، لذلك يفترض تريد العودة شيئا مفيدا بدلا من '()

نصائح أخرى

والعمل على كلوجر 1.3.0، وعلى ما يستحق، يمكنك كتابة في حين حلقات في كلوجر الآن عن طريق القيام بشيء أقرب إلى

(while truth-expression
  (call-some-function))

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

وسوف يتم حلها عادة هذا النوع من المشكلة عن طريق إنشاء سلسلة من الرموز (الحروف في المثال الخاص بك) وتطبيق أو أكثر من الوظائف تسلسل كلوجر في (doseq، dorun، واتخاذ الوقت، الخ)

والمثال التالي يقرأ اسم المستخدم الأول من / الخ / باسود على يونكس مثل أنظمة.

(require '[clojure.java [io :as io]])

(defn char-seq
  "create a lazy sequence of characters from an input stream"
  [i-stream]
  (map char 
   (take-while
    (partial not= -1)
    (repeatedly #(.read i-stream)))))

;; process the sequence one token at a time
;; with-open will automatically close the stream for us 

(with-open [is (io/input-stream "/etc/passwd")]
  (doseq [c (take-while (partial not= \:) (char-seq is))]
    ;; your processing is done here
    (prn c)))

وخطرت لي هذه بروح line-seq. انها كسول تماما ويسلك أكثر من طبيعة وظيفية كلوجر لمن loop.

(defn delim-seq
  ([#^java.io.Reader rdr #^Character delim]
     (delim-seq rdr delim (StringBuilder.)))
  ([#^java.io.Reader rdr #^Character delim #^StringBuilder buf]
     (lazy-seq
       (let [ch (.read rdr)]
         (when-not (= ch -1)
           (if (= (char ch) delim)
             (cons (str buf) (delim-seq rdr delim))
             (delim-seq rdr delim (doto buf (.append (char ch))))))))))

عجينة كاملة .

حين حلقة عادة ما ينطوي قابلة للتغيير المتغيرات ، أيالانتظار حتى متغير يلبي شرط معين;في Clojure كنت عادة استخدام الذيل العودية (أي مترجم يترجم إلى حين-حلقة)

التالية ليست هي الحل ، ولكن هذا الاختلاف من أجل حلقة قد يكون مفيدا في بعض الحالات:

(for [a (range 100) 
      b (range 100) 
      :while (< (* a b) 1000)] 
    [a b]
  )

هذا سوف إنشاء قائمة من جميع أزواج من a و b حتى (< (* a b) 1000).التي سوف تتوقف بمجرد الشرط.إذا قمت باستبدال :مع :عندما كنت يمكن أن تجد كل من أزواج التي تلبي الشرط ، حتى بعد أن يجد واحد لا.

وخرجت مع هذا الإصدار:

(defn read-until
  [^java.io.Reader rdr ^String delim]
  (let [^java.lang.StringBuilder salida (StringBuilder.) ]
    (while
      (not (.endsWith (.toString salida) delim))
      (.append salida (str (char (.read rdr))))
    )
    (.toString salida)
  )
)

ويبدو لسلسلة، وليس حرف واحد كما محدد!

وشكرا!

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