سؤال

يبدو أنه رائع لا يدعم break و continue من خلال الإغلاق.ما هي أفضل طريقة لمحاكاة هذا ؟

revs.eachLine { line -> 
    if (line ==~ /-{28}/) {
         // continue to next line...
    }
}
هل كانت مفيدة؟

المحلول

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

وأفضل نهج (على افتراض انك لا تحتاج القيمة الناتجة).

revs.eachLine { line -> 
    if (line ==~ /-{28}/) {
        return // returns from the closure
    }
}

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

revs.eachLine { line -> 
    if (!(line ==~ /-{28}/)) {
        // do what you would normally do
    }
}

وهناك خيار آخر، يحاكي ما تستمر تفعل عادة في مستوى بايت كود.

revs.eachLine { line -> 
    while (true) {
        if (line ==~ /-{28}/) {
            break
        }
        // rest of normal code
        break
    }

}

واحد وسيلة ممكنة لدعم كسر هو عن طريق الاستثناءات:

try {
    revs.eachLine { line -> 
        if (line ==~ /-{28}/) {
            throw new Exception("Break")
        }
    }
} catch (Exception e) { } // just drop the exception

وقد تحتاج إلى استخدام نوع استثناء مخصصة لتجنب اخفاء استثناءات الحقيقية الأخرى، وخاصة إذا كان لديك معالجة أخرى يجري في تلك الفئة التي يمكن أن رمي الاستثناءات الحقيقية، مثل NumberFormatExceptions أو IOExceptions.

نصائح أخرى

والإغلاق لا يمكن كسر أو الاستمرار لأنها ليست حلقة بنيات / التكرار. وبدلا من ذلك فهي أدوات تستخدم لمعالجة / تفسير / التعامل مع منطق تكرارية. يمكنك تجاهل نظرا التكرارات بمجرد عودته من إغلاق دون معالجة كما في:

revs.eachLine { line -> 
    if (line ==~ /-{28}/) {
            return
    }

}

ولا يحدث الدعم استراحة على مستوى إغلاق ولكن بدلا من ذلك فهذا يعني ضمنا من دلالات استدعاء الأسلوب قبلت الإغلاق. باختصار هذا يعني بدلا من استدعاء "كل" شيء من هذا القبيل على مجموعة الذي يهدف إلى معالجة المجموعة الكاملة يجب عليك الاتصال عثور التي سوف نقوم بمعالجة حتى يتحقق شرط معين. معظم (جميع؟) الأوقات التي يشعرون بالحاجة إلى كسر من إغلاق ما كنت حقا تريد القيام به هو العثور على حالة محددة خلال التكرار الخاص مما يجعل العثور على طريقة مباراة ليس فقط احتياجات منطقية ولكن أيضا نيتك. للأسف بعض API يفتقرون إلى الدعم لطريقة الاكتشاف ... ملف على سبيل المثال. فمن الممكن أن كل الوقت الذي يقضيه بحجة الطقس اللغة ينبغي أن تشمل استراحة / مواصلة كان من الممكن أن تنفق بشكل جيد إضافة طريقة الاكتشاف لهذه المناطق المهملة. سيكون شيئا مثل firstDirMatching (اختتام ج) أو findLineMatching (اختتام ج) أن تقطع شوطا طويلا والإجابة على 99 +٪ من "لماذا لا يمكنني كسر من ...؟" الأسئلة التي يطفو على السطح في القوائم البريدية. التي قال أنها تافهة لإضافة هذه الأساليب نفسك عن طريق MetaClass أو الفئات.

class FileSupport {
   public static String findLineMatching(File f, Closure c) {
      f.withInputStream {
         def r = new BufferedReader(new InputStreamReader(it))
         for(def l = r.readLine(); null!=l; l = r.readLine())
             if(c.call(l)) return l
         return null
      }
   }
}

using(FileSupport) { new File("/home/me/some.txt").findLineMatching { line ==~ /-{28}/ }

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

إذا كنت قبل خلق ثابت استثناء كائن في جافا ثم رمي (ثابت) استثناء من داخل الإغلاق وقت التشغيل تكلفة الحد الأدنى.الحقيقي تكبد التكلفة في خلق الاستثناء وليس في رميها.وفقا مارتن Odersky (مخترع سكالا) ، العديد من JVMs يمكن فعلا تحسين رمي تعليمات واحدة يقفز.

هذا يمكن استخدامها لمحاكاة استراحة:

final static BREAK = new Exception();
//...
try {
  ... { throw BREAK; }
} catch (Exception ex) { /* ignored */ }

استخدام عودة إلى تواصل و أي إغلاق كسر.

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

محتوى الملف:

1
2
----------------------------
3
4
5

رائع الكود:

new FileReader('myfile.txt').any { line ->
    if (line =~ /-+/)
        return // continue

    println line

    if (line == "3")
        true // break
}

الإخراج:

1
2
3

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

RX-جافا الذي يمكن ان تتحول إلى iterable في لملاحظتها.

وبعد ذلك يمكنك استبدال <م> مواصلة مع تصفية و <م> كسر مع takeWhile

وهنا مثال:

import rx.Observable

Observable.from(1..100000000000000000)
          .filter { it % 2 != 1} 
          .takeWhile { it<10 } 
          .forEach {println it}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top