Что такое закрытый эквивалент идиомы Python & ldquo; if __name__ == '__main __' & rdquo ;?

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

25
задан Tim Gilbert 10 June 2009 в 00:07
поделиться

6 ответов

Многократно запускать сценарии Clojure из командной строки - это не идиоматично. REPL - лучшая командная строка. Clojure является Lisp, поэтому обычно запускают Clojure и оставляют один и тот же экземпляр работающим навсегда и взаимодействуют с ним, а не перезапускают его. Вы можете изменять функции в запущенном экземпляре по одной, запускать их и при необходимости вставлять их. Уход от утомительного и медленного традиционного цикла редактирования / компиляции / отладки - отличная особенность Lisps.

Вы можете легко написать функции для выполнения таких вещей, как запуск модульных тестов, и просто вызывать эти функции из REPL всякий раз, когда вы хотите их запустить, и игнорировать их в противном случае. В Clojure обычно используется clojure.contrib.test-is , добавляются ваши тестовые функции в пространство имен, а затем используются clojure.contrib.test-is / run-tests для их запуска. все.

Еще одна веская причина не запускать Clojure из командной строки состоит в том, что время запуска JVM может быть недопустимым.

Если вы действительно хотите запустить сценарий Clojure из командной строки, есть несколько способов сделай это. См. список рассылки Clojure для обсуждения.

Один из способов - проверить наличие аргументов командной строки. Учитывая этот foo.clj в текущем каталоге:

(ns foo)

(defn hello [x] (println "Hello," x))

(if *command-line-args*
  (hello "command line")
  (hello "REPL"))

Вы получите разное поведение в зависимости от того, как вы запускаете Clojure.

$ java -cp ~/path/to/clojure.jar:. clojure.main foo.clj --
Hello, command line
$ java -cp ~/path/to/clojure.jar:. clojure.main
Clojure 1.1.0-alpha-SNAPSHOT
user=> (use 'foo)
Hello, REPL
nil
user=>

См. src / clj / clojure / main.clj в исходном коде Clojure, если вы хотите увидеть, как это работает.

Другой способ - скомпилировать ваш код в файлы .class и вызвать их из командной строки Java. Для исходного файла foo.clj :

(ns foo
  (:gen-class))

(defn hello [x] (println "Hello," x))

(defn -main [] (hello "command line"))

Создайте каталог для хранения скомпилированного . файлы класса ; по умолчанию это ./ classes . Вы должны создать эту папку сами, Clojure ее не создаст. Также убедитесь, что вы установили $ CLASSPATH , чтобы включить ./ classes и каталог с вашим исходным кодом; Я предполагаю, что foo.clj находится в текущем каталоге. Итак, из командной строки:

$ mkdir classes
$ java -cp ~/path/to/clojure.jar:./classes:. clojure.main
Clojure 1.1.0-alpha-SNAPSHOT
user=> (compile 'foo)
foo

В каталоге classes теперь у вас будет куча файлов .class . Чтобы вызвать ваш код из командной строки (по умолчанию выполняется функция -main ):

$ java -cp ~/path/to/clojure.jar:./classes foo
Hello, command line.

На clojure.org имеется много информации о компиляции кода Clojure.

Также убедитесь, что вы установили $ CLASSPATH , чтобы включить ./ classes и каталог с вашим исходным кодом; Я предполагаю, что foo.clj находится в текущем каталоге. Итак, из командной строки:

$ mkdir classes
$ java -cp ~/path/to/clojure.jar:./classes:. clojure.main
Clojure 1.1.0-alpha-SNAPSHOT
user=> (compile 'foo)
foo

В каталоге classes теперь у вас будет куча файлов .class . Чтобы вызвать ваш код из командной строки (по умолчанию выполняется функция -main ):

$ java -cp ~/path/to/clojure.jar:./classes foo
Hello, command line.

На clojure.org имеется много информации о компиляции кода Clojure.

Также убедитесь, что вы установили $ CLASSPATH , чтобы включить ./ classes и каталог с вашим исходным кодом; Я предполагаю, что foo.clj находится в текущем каталоге. Итак, из командной строки:

$ mkdir classes
$ java -cp ~/path/to/clojure.jar:./classes:. clojure.main
Clojure 1.1.0-alpha-SNAPSHOT
user=> (compile 'foo)
foo

В каталоге classes теперь у вас будет куча файлов .class . Чтобы вызвать ваш код из командной строки (по умолчанию выполняется функция -main ):

$ java -cp ~/path/to/clojure.jar:./classes foo
Hello, command line.

На clojure.org имеется много информации о компиляции кода Clojure.

27
ответ дан 28 November 2019 в 21:45
поделиться

Я новичок в Clojure, но думаю, это обсуждение групп Clojure может быть решением и / или обходным путем, особенно сообщение Стюарта Сьерры от 17 апреля в 22:40.

1
ответ дан 28 November 2019 в 21:45
поделиться

В Common Lisp вы можете использовать условное чтение с функциями .

#+testing (run-test 'is-answer-equal-42)

Выше будет только чтение и выполнение во время загрузки, если список функций привязан к cl: * features * будет содержать символ: testing.

Например,

(let ((*features* (cons :testing *features*)))
   (load "/foo/bar/my-answerlib.lisp"))

временно добавит: testing к списку возможностей.

Вы можете определить свои собственные функции и контролировать, какие выражения будут использовать Common Lisp система читает и пропускает.

Кроме того, вы также можете:

#-testing (print '|we are in production mode|)
1
ответ дан 28 November 2019 в 21:45
поделиться

Возможно, вам стоит взглянуть на библиотеку test-is из clojure-contrib. Это не та идиома, но она должна поддерживать довольно похожий рабочий процесс.

0
ответ дан 28 November 2019 в 21:45
поделиться

Common Lisp и Clojure (а также другие Lisp) предоставляют интерактивную среду с REPL, и вам не нужны уловки вроде « если __name__ == '__main __' ». Для python существуют среды, подобные REPL: python из командной строки, ipython, режим python для Emacs и т. Д.

Вам нужно просто создать библиотеку, добавить в нее набор тестов (существует множество сред тестирования для Common Lisp; Я предпочитаю фреймворк 5am , обзор доступных фреймворков можно найти здесь ). Затем вы загружаете библиотеку, а в REPL вы можете делать с библиотекой все, что угодно: запускать тесты, вызывать функции, экспериментировать и т. д.

Когда вы обнаруживаете неудачный тест, вы исправляете его, перекомпилируете измененный код и продолжаете экспериментировать, выполняя тесты без перезапуска всего приложения. Это экономит много времени, потому что запущенное приложение могло накопить много состояния (оно могло создавать окна графического интерфейса, подключенные к базам данных, достигло критического момента, который нелегко воспроизвести), и вам не нужно перезапускать его. после каждого изменения.

Вот пример для Common Lisp (из моей библиотеки cl-sqlite):

Код:

(def-suite sqlite-suite)

(defun run-all-tests ()
  (run! 'sqlite-suite));'

(in-suite sqlite-suite)

(test test-connect
  (with-open-database (db ":memory:")))

(test test-disconnect-with-statements
  (finishes
    (with-open-database (db ":memory:")
      (prepare-statement db "create table users (id integer primary key, user_name text not null, age integer null)"))))
...

и интерактивный сеанс:

CL-USER> (sqlite-tests:run-all-tests)
.......
 Did 7 checks.
    Pass: 7 (100%)
    Skip: 0 ( 0%)
    Fail: 0 ( 0%)

NIL
CL-USER> (defvar *db* (sqlite:connect ":memory:"))
*DB*
CL-USER> (sqlite:execute-non-query *db* "create table t1 (field text not null)")
; No value
CL-USER> (sqlite:execute-non-query *db* "insert into t1 (field) values (?)" "hello")
; No value
CL-USER> (sqlite:execute-to-list *db* "select * from t1")
(("hello"))
CL-USER> 

Теперь предположим, что я обнаружил ошибку в sqlite: execute- к списку. Я перехожу к коду этой функции, исправляю ошибку и перекомпилирую эту функцию. Затем я вызываю фиксированную функцию и проверяю, что она работает.

0
ответ дан 28 November 2019 в 21:45
поделиться

Если вы говорите о «точке входа», вы, безусловно, можете сделать это:

(ns foo)

(defn foo [n]
  (inc n))

(defn main []
  (println "working")
  (println "Foo has ran:" (foo 1)))

(main)

Теперь произойдет следующее: каждый раз, когда этот код будет (load-file "foo.clj") 'd или (использовать' foo) или (require 'foo), тогда будет вызываться (main), что обычно не сделано.

Гораздо более распространенным является то, что файл кода может быть загружен в REPL, после чего основная функция будет вызвана пользователем.

-3
ответ дан 28 November 2019 в 21:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: