Другая возможность могла бы состоять в том, чтобы использовать XmlReader и проверить на ошибочное количество> 0. Что-то вроде этого:
void CheckXml()
{
string _xmlFile = "this.xml";
string _xsdFile = "schema.xsd";
StringCollection _xmlErrors = new StringCollection();
XmlReader reader = null;
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationEventHandler += new ValidationEventHandler(this.ValidationEventHandler);
settings.ValidationType = ValidationType.Schema;
settings.IgnoreComments = chkIgnoreComments.Checked;
settings.IgnoreProcessingInstructions = chkIgnoreProcessingInstructions.Checked;
settings.IgnoreWhitespace = chkIgnoreWhiteSpace.Checked;
settings.Schemas.Add(null, XmlReader.Create(_xsdFile));
reader = XmlReader.Create(_xmlFile, settings);
while (reader.Read())
{
}
reader.Close();
Assert.AreEqual(_xmlErrors.Count,0);
}
void ValidationEventHandler(object sender, ValidationEventArgs args)
{
_xmlErrors.Add("<" + args.Severity + "> " + args.Message);
}
Ну, вы уже выяснили решение, поэтому всего несколько подсказок, чтобы объяснить поведение:
В Clojure (как и в Lisp, Scheme и т. Д.) Все является выражением, а выражение - либо атомом, либо списком. Что касается списков, руководство Clojure говорит
, что непустые списки считаются вызовами. в специальные формы, макросы или функции. Звонок имеет вид (операнды оператора *).
В вашем примере тело ((println x) (println x))
представляет собой список, а сам оператор является выражением, которое Clojure должно вычислить для получения фактического оператор. То есть вы говорите: «Оцените первое выражение и возьмите его возвращаемое значение как функцию для вызова второго выражения». Однако println
возвращает, как вы заметили, только nil
. Это приводит к исключению NullPointerException
, если nil
интерпретируется как оператор.
Ваш код работает с (do (println x) (println x))
, потому что do
- это специальная форма, которая оценивает каждое выражение по очереди и возвращает значение последнего выражения. Здесь do
- это оператор, а выражения с println
- это операнды.
Чтобы понять полезность такого поведения, обратите внимание, что функции являются первоклассными объектами в Clojure, например, вы можете вернуть функцию как результат другой функции. Например, возьмите следующий код:
(doseq [x '(1 2 3 4)] ((if (x > 2)
(fn [x] (println (+ x 2)))
(fn [x] (println (* x 3)))) x))
Здесь я динамически выясняю, какой оператор будет вызывать элемент в последовательности. Сначала вычисляется if
-выражение. Если x
больше двух, if
вычисляется как функция, которая печатает x + 2
, в противном случае вычисляется функция, выводящая x * 3
. Затем эта функция применяется к x
последовательности.
(doseq [x '(1 2 3 4)] ((if (x > 2)
(fn [x] (println (+ x 2)))
(fn [x] (println (* x 3)))) x))
Здесь я динамически выясняю, какой оператор будет вызывать элемент в последовательности. Сначала вычисляется if
-выражение. Если x
больше двух, if
вычисляется как функция, которая печатает x + 2
, в противном случае вычисляется функция, выводящая x * 3
. Затем эта функция применяется к x
последовательности.
(doseq [x '(1 2 3 4)] ((if (x > 2)
(fn [x] (println (+ x 2)))
(fn [x] (println (* x 3)))) x))
Здесь я динамически выясняю, какой оператор будет вызывать элемент в последовательности. Сначала вычисляется if
-выражение. Если x
больше двух, if
вычисляется как функция, которая печатает x + 2
, в противном случае вычисляется функция, выводящая x * 3
. Затем эта функция применяется к x
последовательности.
if
-выражение. Если x
больше двух, if
вычисляется как функция, которая печатает x + 2
, в противном случае вычисляется функция, выводящая x * 3
. Затем эта функция применяется к x
последовательности. вычисляется if
-выражение. Если x
больше двух, if
вычисляется как функция, которая печатает x + 2
, в противном случае вычисляется функция, выводящая x * 3
. Затем эта функция применяется к x
последовательности. Я вижу, что вы уже осознали проблему, однако обратите внимание, что вам не нужно делать:
(doseq [x '(1 2 3 4)] (println x) (println "x"))
Doseq (как следует из названия) уже выполняет:)