2010-03-18 2 views
39

저는 거의 항상 스칼라 REPL 세션 또는 2 회의 오픈을 가지고 있습니다. 따라서 자바 또는 스칼라 클래스에 빠른 테스트를 쉽게 제공 할 수 있습니다. 그러나 클래스를 변경하고 다시 컴파일하면 REPL은로드 된 이전 클래스를 계속 사용합니다. REPL을 다시 시작하지 않고 클래스를 다시로드 할 수있는 방법이 있습니까?Scala REPL에서 클래스 또는 패키지를 다시로드하는 방법?

object Test { def hello = "Hello World" } 

우리는 그것을 컴파일하고 REPL 시작 : 우리가

에 소스 파일을 변경 다음

~/pkg/scala-2.8.0.Beta1-prerelease$ bin/scala 
Welcome to Scala version 2.8.0.Beta1-prerelease 
(Java HotSpot(TM) Server VM, Java 1.6.0_16). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> Test.hello 
res0: java.lang.String = Hello World 

그냥 구체적인 예를 제공하기 위해, 우리는 파일 Test.scala 있다고 가정
object Test { 
    def hello = "Hello World" 
    def goodbye = "Goodbye, Cruel World" 
} 

하지만 우리는 그것을 사용할 수 없습니다

scala> Test.goodbye 
<console>:5: error: value goodbye is not a member of object Test 
     Test.goodbye 
      ^

scala> import Test; 
<console>:1: error: '.' expected but ';' found. 
     import Test; 
+0

REPL보다 워크 시트의 이점이 있습니다. – nafg

답변

26

클래스 리로딩은 쉬운 문제가 아닙니다. 사실, JVM이 매우 어렵게 만드는 부분입니다. 그래도 몇 가지 옵션이 있습니다 :

  • 스칼라 REPL을 디버그 모드로 시작하십시오. JVM 디버거에는 메서드 수준에서 작동하는 몇 가지 기본 제공 다시로드가 있습니다. 그것은 당신이 준 사건으로 당신을 도울 수는 없지만, 그것은 메소드 구현을 변경하는 것과 같은 간단한 것을 처리 할 것입니다.
  • JRebel (http://www.zeroturnaround.com/jrebel)을 사용하십시오. JRebel은 기본적으로 JVM에 대한 과부하 클래스 리로딩 솔루션입니다. 멤버 추가/제거, 새 클래스/제거 클래스, 정의 변경 등을 처리 할 수 ​​있습니다. 수 없습니다 핸들은 클래스 계층 구조의 변경입니다 ( 예를 들어 수퍼 인터페이스 추가). 무료 도구는 아니지만 Scala 컴파일 단위로 제한된 보완 라이센스를 제공합니다.

불행히도이 두 가지 모두 Scala REPL의 구현 세부 사항에 의해 제한됩니다. 나는 JRebel을 사용하며 대개 트릭을 수행하지만 REPL이 다시로드 된 클래스를 반영하지 않는 경우가 여전히 있습니다. 여전히 아무것도 아닌 것보다 낫습니다.

+7

어떻게 디버그 모드에서 스칼라 복제를 시작 하시겠습니까? 내 프로젝트에 대한 스칼라 repl 시작하려면 sbt 사용하고 '콘솔'을 실행하고 있지만 어떻게 디버그 모드에서 수행 할 수 있는지 확실하지 않습니다. – mmrobins

36

이전 명령을 반복하지 않아도 되려면 클래스를 다시로드하는 방법이 있습니다. REPL은 명령 REPL 환경을 다시 시작하고 다시 이전의 모든 유효한 명령을한다

:replay 

있습니다. REPL이 리셋되면 클래스가 다시로드되므로 새로운 명령은 재 컴파일 된 클래스의 내용을 사용할 수 있습니다 (실제로 이전 명령은 사용되지 않습니다. 재 컴파일 된 클래스도 사용합니다).

이것은 일반적인 해결책은 아니지만 재 계산 가능한 상태로 개별 세션을 확장하는 유용한 바로 가기입니다.

참고 : 이것은 스칼라 REPL이 적용되지 않습니다. SBT 또는 다른 환경에서 실행하면 SBT 나 다른 환경 패키지가 클래스를 어떻게 패키지화하는지에 따라 작동하거나 작동하지 않을 수 있습니다. 실제로 사용중인 실제 클래스 경로에있는 내용을 업데이트하지 않으면 ' 일하지 마!

+0

분명히 집중적 인 세션에는 좋지 않지만 나는 이것을 좋아한다. 또한 테스트/TDD가 목표 인 경우 변경 사항이 파손되었는지 여부를 알 수 있음을 의미합니다. – Grogs

+4

나는 이것이 틀렸다는 것을 믿는다. ': replay'는 클래스를 다시로드하지 않습니다. –

+0

@AdamMackler에 동의합니다. 적어도 2.10.4에서는 다시로드하지 않는 것 같습니다. – mitchus

5

.... 스칼라 소스 파일을 다시로드 클래스와 컴파일 것이다 명령을 충족 당신에게 요구

:load path/to/file.scala 

는, 당신은 당신의 코드 이것은 나를 위해 작동

+1

'file.scala'의 맨 위에'package'가 정의되어 있다면이 방법이 유용할까요? Thanks –

5

을 재생할 수

있다 새 소스 파일 Test.scala 이런 식으로 뭔가를 보이는 경우

...

package com.tests 

object Test { 
    def hello = "Hello World" 
    def goodbye = "Goodbye, Cruel World" 
} 

먼저 새 변경 사항을 Scala 콘솔 (REPL)에로드해야합니다.

:load src/main/scala/com/tests/examples/Test.scala 

그런 다음 스칼라 콘솔에서 새 코드를 참조 할 수 있도록 패키지를 다시 가져옵니다.

import com.tests.Test 

지금, 단지 :load myfile.scala 넣어, 세션 :

scala> Test.goodbye 
res0: String = Goodbye, Cruel World 
+0

'Test.scala'의 상단에'package'가 정의되어 있지 않은 경우에만 저에게 적합합니다. 어떤 아이디어? 감사합니다 –

+0

모르겠다. 아마도 잘못된 패키지 경로 – cevaris

0

.scala 파일을 사용하면 REPL 전체 경로를 ommit 수 있습니다 시작 디렉토리에있는 경우를 다시 시작하지 않고 새로운 코드를 즐길 수 가져 오십시오.