복붙노트

[SCALA] 스칼라 - 가변 (VAR)에있어서의 파라미터를 참조

SCALA

스칼라 - 가변 (VAR)에있어서의 파라미터를 참조

편집 : 나는 여기 upvotes가 계속. 그냥 기록을 위해, 나는 더 이상이 중요하다고 생각합니다. 내가 그것을 게시 이후 나는 그것을 필요로하지 않았습니다.

나는 스칼라에서 다음을 수행하고 싶습니다 ...

def save(srcPath: String, destPath: String) {
    if (!destPath.endsWith('/'))
        destPath += '/'
    // do something
}

...하지만 난 destPath가 발입니다 beacuse 수 없습니다. VAR로 destPath를 선언 할 수있는 방법이 있습니까?

참고 :이 비슷한 질문이 있지만 영업 이익의 모든 단지 배열을 수정하고 싶었다.

다음과 같은 조언을하지 마십시오 :

나는 명령형 프로그래밍에서 유효 생각 (스칼라 오른쪽 모두 허용?)와 tmpDestPath 같은 것을 추가하는 것은 단지 혼란을 추가합니다.

편집 :하지 오해. 나는 문자열을 변경할 수 없습니다 내가 호출자의 데이터를 수정하지 않기 때문에 내가 참조에 대한 참조를하지 않으려는 것을 알고있다. 난 그냥 발신자가 내 문자열로 저를 준 문자열에 대한 로컬 참조 수정하려면 (예를. 오리지널 + '/'). 난 단지 현재의 방법의 범위에 그 값을 수정할. 이 자바에서 완벽하게 유효 봐 :

void printPlusOne(int i) {
    i++;
    System.out.println("i is: " + i);
    System.out.println("and now it's same: " + i);
}

나는 새로운 변수를 만들 필요가 없습니다 그리고 난 두 번 내가 + 1 계산 할 필요가 없습니다.

해결법

  1. ==============================

    1.당신은 할 수 없습니다.

    당신은 할 수 없습니다.

    당신은 여분의 VAR를 선언해야 (또는 더 많은 기능 스타일을 :-) 사용) 것입니다.

    단순한 예 :

    def save(srcPath: String, destPath: String) {
        val normalizedDestPath =
          if (destPath.endsWith('/')) destPath
          else destPath + '/'
        // do something with normalizedDestPath 
    }
    
  2. ==============================

    2.JVM은 당신이 정확하게 당신이 원하는 일을 할 수 없도록, (당신이 C ++에서이 작업을 수행 할 것입니다 방법입니다) 통과 참조에 의한 개체에 대한 포인터를 허용하지 않습니다.

    JVM은 당신이 정확하게 당신이 원하는 일을 할 수 없도록, (당신이 C ++에서이 작업을 수행 할 것입니다 방법입니다) 통과 참조에 의한 개체에 대한 포인터를 허용하지 않습니다.

    하나의 옵션은 새 값을 반환하는 것입니다 :

    def save(srcPath: String, destPath: String): String = {
      val newPath = (if (!destPath.endsWith("/")) destPath+'/' else destPath)
      // do something
      newPath
    }
    

    또 다른 래퍼를 만드는 것입니다 :

    case class Mut[A](var value: A) {}
    
    def save(srcPath: String, destPath: Mut[String]) {
      if (!destPath.value.endsWith("/")) destPath.value += '/'
      // do something
    }
    

    어떤 사용자가 다음 방식에 사용해야합니다. (물론, 그들은 "/ 여기에"(저장 유혹 할 것이다, 무트 ( "/이"))에 변경을 던져, 그러나 이것은 항상 사실입니다 것이다 패스 별 기준 함수 인수).

    편집 : 당신은 제안하는 비 전문 프로그래머들 사이에서 혼란의 가장 큰 소스 중 하나 무엇인지. 만약 함수의 인수를 수정할 때 즉,하면 로컬 복사본 (통과하여 값) 또는 원본 (패스 별 참조)를 수정 있습니까? 당신도 수정할 수없는 경우가 꽤 당신이 그 아무것도 로컬 복사본입니다 분명하다.

    그냥 그런 식으로 않습니다.

    val destWithSlash = destPath + (if (!destPath.endsWith("/")) "/" else "")
    

    그것은 가치가 실제로 무슨 일이 일어나고 있는지에 대한 혼란의 부족입니다.

  3. ==============================

    3.당신도 슬래시마다 추가에 대해 걱정할 필요가 없습니다 어쩌면 당신은, 당신을 위해 일을하는 타입 시스템을 얻을 수 있습니다 :

    당신도 슬래시마다 추가에 대해 걱정할 필요가 없습니다 어쩌면 당신은, 당신을 위해 일을하는 타입 시스템을 얻을 수 있습니다 :

    class SlashString(s: String) {
      override val toString = if (s endsWith "/") s else s + "/"
    }
    implicit def toSlashString(s: String) = new SlashString(s)
    

    지금 당신은 입력 문자열을 변경 전혀 코드가 필요하지 않습니다

    def save(srcPath: String, destPath: SlashString) {
      printf("saving from %s to %s", srcPath, destPath)
    }
    
    val src: String = "abc"
    val dst: String = "xyz"
    
    scala> save(src, dst)
    saving from abc to xyz/
    

    사실, 시작시 설정의 비트가있다, 그러나 이것은 버전 2.10에서 암시 적 클래스와 덜 그렇게 될 것입니다, 그리고 당신이 걱정하고 있었는지했다 방법, 모든 혼란을 제거합니다.

  4. ==============================

    4.String 객체는 스칼라 (자바)에서 변경할 수 있습니다. 내가 생각할 수있는 대안은 다음과 같습니다 :

    String 객체는 스칼라 (자바)에서 변경할 수 있습니다. 내가 생각할 수있는 대안은 다음과 같습니다 :

    두 번째 시나리오에서는 당신이 뭔가를 같이 할 것이다 :

    def save(srcPath: String, destPath: StringBuilder) {
        if (!destPath.toString().endsWith("/"))
           destPath.append("/")
        // do something
        //
    }
    

    편집하다

    만약 내가 제대로 이해하고, 로컬 변수로 인수를 사용하고 싶습니다. 모든 메소드 인수가 스칼라에서 발의이기 때문에 당신은 할 수 없습니다. 할 수있는 유일한 방법은 먼저 지역 변수에 복사하는 것입니다 :

    def save(srcPath: String, destPath: String) {
        var destP = destPath
        if (!destP.endsWith("/"))
           destP += "/"
        // do something
        //
    }
    
  5. ==============================

    5.여기에 몇 가지 제안입니다 :

    여기에 몇 가지 제안입니다 :

    1) 비트 함수를 업데이트

    def save(srcPath: String, destPath: String) {
      var dp = destPath
      if (!dp.endsWith('/'))
        dp+= '/'
      // do something, but with dp instead of destPath
    }
    

    2) 저장 호출하기 전에 사용하는 유틸리티 함수를 만듭니다

    def savedPath(path: String) = 
      if(path.endsWith("/")) 
        path
      else
        path + "/"
    
    //call your save method on some path
    val myDestPath = ...
    val srcPath = ...
    save(srcPath, savedPath(myDestPath))
    
  6. ==============================

    6.아니,이 스칼라에서 허용하지 않는다. 기타 (모든 좋은) 약간 낮은 수준의 해결 방법을 설명했다,하지만 난 더 높은 수준의 하나를 추가합니다. 문자열 정규화 목적의 바로 이런 종류의, 나는 접미사, 접두사, removeSuffix 및 removePrefix 같은 방법으로 scala.String에 포주 확장 주위를 유지한다. 접미사와 접두사 추가하거나 접미사 나 접두사가 이미 존재하지 않는 한, 다른에 하나의 문자열을 앞에 추가. 그것은 현재의 경우 removeSuffix 및 removePrefix는 끝에서 하나의 문자열을 제거하거나 다른의 시작, 명백한을한다. 사용 사례가 기록 될 것입니다

    아니,이 스칼라에서 허용하지 않는다. 기타 (모든 좋은) 약간 낮은 수준의 해결 방법을 설명했다,하지만 난 더 높은 수준의 하나를 추가합니다. 문자열 정규화 목적의 바로 이런 종류의, 나는 접미사, 접두사, removeSuffix 및 removePrefix 같은 방법으로 scala.String에 포주 확장 주위를 유지한다. 접미사와 접두사 추가하거나 접미사 나 접두사가 이미 존재하지 않는 한, 다른에 하나의 문자열을 앞에 추가. 그것은 현재의 경우 removeSuffix 및 removePrefix는 끝에서 하나의 문자열을 제거하거나 다른의 시작, 명백한을한다. 사용 사례가 기록 될 것입니다

    val normalizedPath = destPath.addSuffix("/") 
    

    당신은 데이터 분석 또는 파일 작업의 무리를 할 경우, 이러한 방법은 당신이 이제까지 그들없이했다는 것을 믿지 않을 것이다 너무 편리합니다.

  7. ==============================

    7.나는이 오래된 질문 알아요,하지만 당신은 아마도 인수 이름을 다시 사용하려는 경우 :

    나는이 오래된 질문 알아요,하지만 당신은 아마도 인수 이름을 다시 사용하려는 경우 :

    def save(srcPath: String, destPath: String) {
      ((destPath: String) => {
        // do something
      })(if (!destPath.endsWith('/')) destPath + '/' else destPath)
    }
    
  8. from https://stackoverflow.com/questions/9535821/scala-mutable-var-method-parameter-reference by cc-by-sa and MIT license