REPL이 Java에서 의미하는 것

클로저 클로저 나 스칼라 개발자이거나 과거에 LISP와 함께 일한 적이있을 것입니다. 그렇다면 일상 생활의 일부로 REPL을 사용했을 가능성이 높습니다. REPL 또는 read-eval-print-loop는 각 입력 라인을 읽고 해당 라인을 평가 한 다음 결과를 인쇄하는 쉘 인터페이스입니다. 즉각적인 피드백, 좋습니다!

REPL을 사용하면 대화식으로 코드를 작성하고 지체없이 실행하게됩니다. 2016 년 Java 9 릴리스는 JShell (코드 명 Kulla)이라는 완전한 기능의 REPL 환경을 제공합니다. 이 기사는 Java REPL에 대한 개요를 제공하고 Java 프로그래밍에서이를 사용하는 방법에 대한 몇 가지 가능성에 대해 설명합니다.

잠깐, Java에는 이미 REPL이 없습니까?

확실히 Java와 같은 기존 언어에는 REPL이 있어야합니다! 글쎄요, 사실, 모든 언어에 그것들이있는 것은 아니며 Java는 그것을 놓친 것들 중 하나입니다. 틀림없이 대부분의 언어보다 더 많은 의식과 상용구를 가진 Java는 개발자가 가장 적합한 언어 중 하나입니다. Java는 Java BeanShell의 형태로 한동안 약간 REPL과 유사한 것을 가지고 있었지만이 프로젝트는 다른 언어와 동등한 완전한 기능을 갖춘 REPL이 아닙니다. 전체 Java 언어 구문의 일부에 불과했습니다.

REPL로 처리 시간 단축

처리 시간과 피드백 루프를 최대한 단축하는 것은 개발자의 정신에 매우 중요합니다. REPL은이를 달성하고자하는 개발자에게 훌륭한 도구입니다. 개발자는 작업 결과를 즉시 볼 수있을 때 가장 생산적입니다. Java REPL을 사용하면 개발자는 코드를 작성하고 해당 코드를 실행 한 다음 빌드 등을 실행하기 위해 종료하지 않고도 즉시 코드를 계속 발전시킬 수 있습니다. Java를 사용하는 많은 시스템이 대화 형 REPL로 처리 할 수있는 복잡성을 넘어선 반면, JDK에 REPL이 있다는 것만으로도 누군가가 어딘가에서 놀라운 사용 사례를 즉시 찾을 수 있습니다. JShell이 ​​API를 공개한다는 사실은 기본적으로 IDE 개발자가이 REPL을 우리가 코드를 작성하는 데 사용하는 도구에 통합 할 수 있도록합니다.Java REPL이 모든 IDE의 일부가 될 때까지 기다리십시오!

JShell 시작하기

개발중인 REPL 인 Project Kulla를 사용하는 것은 마음이 약한 사람을위한 것이 아니라는 것을 인식하는 것이 중요합니다. JShell 이라고도하는 Kulla는 작성 당시 JDK 9 프리뷰 번들의 일부가 아니므로 Mercurial 프로젝트를 복제하고 JDK를 컴파일하고 JShell을 직접 컴파일해야합니다. 특히 일반적으로 JDK 소스 코드를 사용하지 않는 경우이 프로세스를 위해 한 시간을 할당하십시오. 경고를 오류로 비활성화해야하며 OSX에서 빌드하는 경우 freetype 라이브러리 용 XQuartz와 함께 XCode를 설치했는지 확인하십시오. Java 개발 환경에서 Project Kulla를 설치하고 실행하려면 아래 지침을 따르십시오.

1. Java 9 설치

JShell을 실행하려면 Java 9 용 최신 얼리 액세스 프리뷰 빌드를 다운로드 하여 설치해야합니다. Java 9를 다운로드 한 후 JAVA_HOME환경 변수를 설정 하고 실행 java –version하여 설치를 확인합니다. 이것은 특히 OSX에서 고통 스러울 수 있으므로 두 번 확인하는 것이 좋습니다!

2. Mercurial 및 Project Kulla 설치

Project Kulla는 OpenJDK 프로젝트이므로 Mercurial 저장소를 복제하여 컴파일해야합니다.

다음으로 Kulla 저장소를 복제합니다.

 hg clone //hg.openjdk.java.net/kulla/dev kulla 

그런 다음 빌드를 구성합니다.

 cd kulla bash ./configure --disable-warnings-as-errors make images 

3. REPL 컴파일 및 실행

다음은 REPL을 컴파일하는 코드입니다.

 cd langtools/repl; bash ./scripts/compile.sh 

그리고 그것을 실행하는 코드는 다음과 같습니다.

 bash ./scripts/run.sh 

앞서 언급했듯이 Java의 REPL 기능은 아직 일반 사용을위한 준비가되어 있지 않지만 초기 테스트 드라이브에 사용할 수 있습니다!

당신은 수학을

JShell이 ​​무엇을 할 수 있는지에 대한 초기 예제를 위해 다음을 사용하여 몇 가지 간단한 표현식을 평가 해 보겠습니다 java.lang.Math.

Listing 1. REPL로 수학 식 평가하기

 $ bash ./scripts/run.sh | Welcome to JShell -- Version 0.710 | Type /help for help -> Math.sqrt( 144.0f ); | Expression value is: 12.0 | assigned to temporary variable $1 of type double -> $1 + 100; | Expression value is: 112.0 | assigned to temporary variable $2 of type double -> /vars | double $1 = 12.0 | double $2 = 112.0 -> double val = Math.sqrt( 9000 ); | Added variable val of type double with initial value 94.86832980505137 

여기에서는 표현식을 평가하고 숫자의 제곱근을 찾은 다음 두 숫자를 더합니다. 이것은 가장 복잡한 코드는 아니지만이 /vars명령은 JShell 세션에서 생성 된 변수를 나열하는 기능을 제공 한다는 점에 유의해야합니다 . 달러 기호 ($) 표기법을 사용하여 할당되지 않은 표현식의 값을 참조 할 수 있습니다. 마지막으로 새 변수를 만들고 값을 할당 할 수 있습니다.

방법 정의

이제 더 흥미로워집니다. 이 예에서는 피보나치 수열을 계산하는 방법을 정의합니다. 메소드를 정의한 후 /methods명령 으로 정의 된 메소드를 확인합니다 . 마지막으로 코드 조각을 실행하여 배열을 반복하고 시퀀스의 처음 몇 개 숫자를 인쇄합니다.

Listing 2. 피보나치 수열 계산

 $ bash ./scripts/run.sh | Welcome to JShell -- Version 0.710 | Type /help for help -> long fibonacci(long number)  >> if ((number == 0)  | Added method fibonacci(long) -> /methods | fibonacci (long)long -> fibonacci( 12 ) | Expression value is: 144 | assigned to temporary variable $1 of type long -> int[] array = { 1,2,3,4,5,6,7,8 }; | Added variable array of type int[] with initial value [[email protected] -> for( long i : array ) { System.out.println(fibonacci( i )); } 1 1 2 3 5 8 13 21 

동일한 JShell 세션에서 Fibonacci 메서드의 정의를 재정의하고 동일한 코드를 실행할 수 있습니다. 이러한 방식으로 REPL을 사용하여 새 알고리즘을 빠르게 실행, 수정 및 테스트 할 수 있습니다.

Listing 3. 재사용을위한 REPL

 -> long fibonacci(long number) { >> return 1; >> } | Modified method fibonacci(long) -> for( long i : array ) { System.out.println(fibonacci( i )); } 1 1 1 1 1 1 1 

클래스 정의

다음 예제는 JShell에서 전체 클래스를 정의한 다음 표현식에서 해당 클래스를 참조하는 방법을 보여줍니다. 모두 REPL을 벗어나지 않습니다. 코드를 동적으로 생성하고 테스트하는 기능을 통해 새 코드를 빠르게 실험하고 반복 할 수 있습니다.

Listing 4. 동적 클래스 정의

 MacOSX:repl tobrien$ bash ./scripts/run.sh | Welcome to JShell -- Version 0.710 | Type /help for help -> class Person { >> public String name; >> public int age; >> public String description; >> >> public Person( String name, int age, String description ) { >> this.name = name; >> this.age = age; >> this.description = description; >> } >> >> public String toString() { >> return this.name; >> } >> } | Added class Person -> Person p1 = new Person( "Tom", 4, "Likes Spiderman" ); | Added variable p1 of type Person with initial value Tom -> /vars | Person p1 = Tom 

클래스를 동적으로 정의하는 기능은 강력하지만 개발자가 대화 형 셸에서 여러 줄로 된 대규모 정의를 작성하려고하는 것과는 다릅니다. 이것은 역사 의 개념 과 REPL의 상태를로드하고 저장하려는 것이 중요해지기 시작하는 곳입니다. /history명령을 사용하면 REPL에서 평가 된 모든 문과 식을 나열 할 수 있습니다.

Listing 5. / history 파악하기

 -> /history class Person { public String name; public int age; public String description; public Person( String name, int age, String description ) { this.name = name; this.age = age; this.description = description; } public String toString() { return this.name; } } Person p1 = new Person( "Tom", 4, "Likes Spiderman" ); Person p2 = new Person( "Zach", 10, "Good at Math" ); /vars p1 p2 /history 

그런 다음 REPL 히스토리를 파일에 저장하고 나중에 다시로드 할 수 있도록 이름을 지정할 수 있습니다. 예를 들면 다음과 같습니다.

 -> /save output.repl -> /reset | Resetting state. -> /vars -> /open output.repl -> /vars | Person p1 = Tom | Person p2 = Zach 

/save명령은, 파일에 REPL 기록을 저장 /reset명령은 REPL의 상태를 재설정하고, /open명령은 REPL에 대한 파일이 실행 상태로 읽습니다. 저장 및 열기 기능을 사용하면 다양한 REPL 시나리오를 구성하는 데 사용할 수있는 매우 복잡한 REPL 스크립트를 설정할 수 있습니다.

즉시 클래스 정의 편집

JShell은 또한 시작 정의 파일을 설정하고 정의를 자동으로로드 할 수 있습니다. REPL 히스토리를 이동하고 이름이 지정된 소스 항목을 편집 할 수 있습니다. 예를 들어이 예제에서 Person클래스 의 정의를 수정 하려면 /list/edit명령을 사용할 수 있습니다 .

목록 6. 사람 수정

 -> /l 1 : class Person { public String name; public int age; public String description; public Person( String name, int age, String description ) { this.name = name; this.age = age; this.description = description; } public String toString() { return this.name; } } 2 : Person p1 = new Person( "Tom", 4, "Likes Spiderman" ); 3 : Person p2 = new Person( "Zach", 10, "Good at Math" ); 4 : p1 5 : p2 -> /edit 1 

/edit명령을 실행 하면 클래스 정의를 변경하고 클래스를 즉시 업데이트 할 수있는 간단한 편집기가로드됩니다.

큰 문제는 무엇입니까?

Clojure 또는 LISP 프로그래머에게 일상적인 개발 방식에 대해 이야기하면 REPL 내에서 코딩되는 것을 볼 수 있습니다. 그들은 대부분의 개발 시간을 대화식으로 코드를 변경하는 데 소비하는만큼 스크립트를 작성하지 않고 실행합니다. 여유 시간이 몇 시간이면 Scala 또는 Clojure 개발자에게 REPL에 대해 문의하십시오. 그들이 작동하는 방식입니다.

Java's a different language from Scala or Clojure. Java developers are not spending days focused on single lines of LISP that might contain entire program structures in a few statements. Most Java programs require setup to function properly, and while recent changes to the language have reduced the line count of systems written in Java we're still measuring the complexity of our systems in thousands of lines of code. The simple Person example listed above isn't useful code, and most useful code in Java carries with it a complexity that's going to be difficult to fit into a REPL-based programming environment.

Scala and Clojure developers practice something that Clojure Programming author Chas Emerick calls "iterative development" that doesn't depend on a file-based workflow. Java developers depend on tens of libraries, complex dependency hierarchies, and containers like Tomcat or TomEE. For this reason I don't predict that REPL-oriented programming will overtake traditional Java development in an IDE. Instead I see the Java REPL providing a few distinct benefits and opportunities.

1. Learning Java: Because Java programs require so much setup it can be challenging for developers learning the language to understand the syntax quickly. Java 9's REPL will become the primary way that new developers come to grips with the basic syntax.

2. Experimenting with new libraries: Java has hundreds of useful open source libraries for everything from date and time manipulation to math libraries. Without a REPL, whenever a developer wants to understand a new library they inevitably create a few throwaway classes with the usual "public static void main" ceremony. With a REPL you can just fire it up and play without this overhead.

3. Rapid prototyping: This is closer to how most Clojure and Scala developers work iteratively, but if you are working on a focused problem, a REPL makes it easy to iterate quickly on changes to classes and algorithms. With a REPL you won't have to wait for a build to finish; you can tweak the definition of a class quickly, reset your REPL, and try it again.

4. Integration with build systems: Gradle provides an interactive "shell" mode, and the Maven community have shipped similar tools in the past. Developers looking to reduce build complexity could explore using a REPL as a tool to orchestrate other systems.

My final 2c

Java REPL은 Java 9로 업그레이드하는 사람들을 위해 향후 몇 년 동안 일상적인 개발에 영향을 미치기 시작할 것이라고 생각합니다. 또한 Java 커뮤니티가 완전히 적응하는 데 시간이 필요할 것이라고 생각합니다. 새로운 개발 스타일을 유지하고 REPL이 제공하는 도전과 기회를 모두 이해합니다. 대부분의 Java 개발자가 Clojure 프로그래밍 사촌과 같은 REPL 지향 개발로 전환 할 것이라고는 생각하지 않지만, REPL이 새로운 개발자가 Java를 배우는 방식에 영향을 미칠 것이라고 생각합니다. 새로운 Java 개발자가 REPL 내에서 처음으로 Java를 접하게되면 Java 기반 시스템을 빌드하고 프로토 타입하는 방법에 영향을 미치기 시작할 것입니다.

"REPL이 Java에서 무엇을 의미 하는가"라는이 이야기는 원래 JavaWorld에 의해 출판되었습니다.