태그 보관물: programming-languages

programming-languages

왜 그렇게 많은 언어가 가치를 지니고 있습니까? 값에 의해 전달 된 것 C와 같은

당신이 항상 값에 의해 전달 된 것 C와 같은 명시적인 포인터 조작이 심지어 언어 (당신은 할 수 있습니다 참조로 전달할하지만 기본 동작이 아니다).

이것의 장점은 무엇입니까, 왜 그렇게 많은 언어가 값으로 전달되고 다른 언어 가 참조로 전달 됩니까? (확실하지는 않지만 Haskell이 참조로 전달된다는 것을 이해합니다).



답변

값으로 전달하는 것은 실수로 매개 변수를 분석법 / 기능으로 수정할 수 없기 때문에 참조로 전달하는 것보다 안전합니다. 함수에 제공하는 변수에 대해 걱정할 필요가 없기 때문에 언어를보다 간단하게 사용할 수 있습니다. 당신은 그들이 변경되지 않을 것을 알고 있으며, 이것은 종종 당신이 기대하는 것 입니다.

이 경우, 원하는 매개 변수를 수정하려면이 명확 (포인터를 전달)을 만드는 몇 가지 명시 적 작업이 필요합니다. 이렇게하면 모든 호출자가 약간 다르게 호출하도록하고 ( &variableC에서) 변수 매개 변수가 변경 될 수 있음을 명시 적으로 만듭니다.

따라서 변수에 명시 적으로 표시되어 있지 않은 한 함수가 변수 매개 변수를 변경하지 않는다고 가정 할 수 있습니다 (포인터를 전달해야 함). 이것은 대안보다 안전하고 깨끗한 솔루션입니다. 구체적으로 할 수없는 경우가 아니라면 모든 것이 매개 변수를 변경할 수 있다고 가정하십시오.


답변

값별 호출 및 참조 별 호출은 오래 전에 매개 변수 전달 모드로 오인 된 구현 기술입니다.

처음에는 FORTRAN이있었습니다. 서브 루틴이 매개 변수를 수정할 수 있어야하고 FORTRAN이 처음 정의 될 때 프로그래밍에 대해 충분히 알려지지 않았기 때문에 서브 루틴이 매개 변수를 수정할 수 있어야하기 때문에 FORTRAN은 참조 별 호출 만있었습니다.

ALGOL은 이름 별 호출 및 값별 호출을 제안했습니다. 값별 호출은 변경되어서는 안되는 것들 (입력 매개 변수)을위한 것입니다. 이름 별 호출은 출력 매개 변수를위한 것입니다. Call-by-name은 주요 그릇으로 밝혀졌고 ALGOL 68은 그것을 떨어 뜨 렸습니다.

PASCAL은 가치 별 통화 및 기준 별 통화를 제공했습니다. 프로그래머가 매개 변수 스택을 날리지 않도록 큰 객체 (일반적으로 배열)를 참조로 전달한다고 컴파일러에게 알려주는 방법을 제공하지는 않았지만 객체를 변경해서는 안됩니다.

PASCAL은 언어 디자인 어휘에 대한 포인터를 추가했습니다.

C는 메모리에있는 임의의 개체에 대한 포인터를 반환하도록 kludge 연산자를 정의하여 값별 호출을 제공하고 참조 별 시뮬레이션 호출을 제공했습니다.

이후의 언어는 대부분 디자이너가 다른 것을 본 적이 없기 때문에 C를 복사했습니다. 이것이 바로 가치 별 통화가 인기있는 이유 일 것입니다.

C ++은 C kludge 위에 kludge를 추가하여 참조 별 호출을 제공합니다.

이제 값별 호출 대 기준 별 호출 대 포인터 별 kludge의 직접적인 결과로 C와 C ++ (프로그래머)는 const 포인터와 const에 대한 포인터 (읽기 전용)가있는 끔찍한 두통이 있습니다. 사물.

에이다는이 악몽을 피할 수있었습니다.

Ada에는 명시적인 값별 호출 대 참조 별 호출이 없습니다. 오히려 Ada는 매개 변수 (읽지 만 쓸 수는 없음), 매개 변수 (읽기 전에 반드시 기록해야 함) 및 어떤 순서로든 읽고 쓸 수있는 매개 변수를 가지고 있습니다. 컴파일러는 특정 매개 변수가 값 또는 참조로 전달되는지 여부를 결정합니다. 프로그래머에게 투명합니다.


답변

참조에 의한 통과는 의도하지 않은 동작을 유발할 때 추적하기가 불가능하기 때문에 매우 미묘한 의도하지 않은 부작용을 허용합니다.

특히, 값에 의해 전달 final, static또는 const입력 매개 변수는 버그가 사라의이 전체 클래스를 만든다.

불변 언어는 더 결정 론적이며, 무슨 일이 일어나고 있는지, 어떤 기능에서 나오는지에 대해 추론하고 이해하기가 더 쉽습니다.


답변

왜 그렇게 많은 언어가 가치를 지니고 있습니까?

큰 프로그램을 작은 서브 루틴으로 나누는 요점은 서브 루틴에 대해 독립적으로 추론 할 수 있다는 것입니다. 패스 바이 레퍼런스는이 속성을 손상시킵니다. (공유 변경 가능 상태와 마찬가지로)

당신이 항상 값에 의해 전달 된 것 C와 같은 명시적인 포인터 조작이 심지어 언어 (당신은 할 수 있습니다 참조로 전달할하지만 기본 동작이 아니다).

실제로 C는 항상 값으로 전달되며 참조로 전달되지 않습니다. 당신은 어떤 주소를 가지고 그 주소를 전달할 수 있지만, 그 주소는 여전히 값으로 전달 될 것입니다.

이것의 장점은 무엇입니까, 왜 그렇게 많은 언어가 값으로 전달되고 다른 언어 가 참조로 전달 됩니까?

통과 기준을 사용하는 데는 두 가지 주요 이유가 있습니다.

  1. 여러 반환 값 시뮬레이션
  2. 능률

개인적으로 # 1은 가짜라고 생각합니다. 거의 항상 잘못된 API 및 / 또는 언어 디자인에 대한 변명입니다.

  1. 여러 개의 반환 값이 필요한 경우 시뮬레이션하지 말고 지원하는 언어 만 사용하십시오.
  2. 여러 반환 값을 튜플과 같은 가벼운 데이터 구조로 패키징하여 여러 반환 값을 시뮬레이션 할 수도 있습니다. 언어가 패턴 일치 또는 파괴 바인딩을 지원하는 경우 특히 효과적입니다. 예 : 루비 :

    def foo
      # This is actually just a single return value, an array: [1, 2, 3]
      return 1, 2, 3
    end
    
    # Ruby supports destructuring bind for arrays: a, b, c = [1, 2, 3]
    one, two, three = foo
    
  3. 종종 여러 개의 반환 값이 필요하지 않습니다. 예를 들어, 인기있는 패턴 중 하나는 서브 루틴이 오류 코드를 리턴하고 실제 결과는 참조로 다시 쓰여지는 것입니다. 대신 오류가 예상치 않은 경우 예외를 발생 시키거나 Either<Exception, T>오류가 예상 되는 경우를 반환 해야합니다. 다른 패턴은 작업이 성공했는지 여부를 알려주고 실제 결과를 참조로 리턴하는 부울을 리턴하는 것입니다. 다시 말하지만 실패가 예상치 못한 경우 대신 예외를 처리해야합니다. 예를 들어 사전에서 값을 찾을 때 실패가 예상되는 경우 대신 예외를 리턴해야 Maybe<T>합니다.

값을 복사 할 필요가 없으므로 참조 별 전달이 값별 전달보다 더 효율적일 수 있습니다.

(확실하지는 않지만 Haskell이 참조로 전달된다는 것을 이해합니다).

아니요, Haskell은 참조로 전달되지 않습니다. 또한 가치를 전달하는 것도 아닙니다. 기준 별 통과 및 값별 통과는 모두 엄격한 평가 전략이지만 Haskell은 엄격하지 않습니다.

사실, 하스켈 사양은 지정하지 않는 어떤 특정 평가 전략을. 대부분의 Hakell 구현은 이름 별 호출과 필요에 따른 호출 (메모와 함께 호출 별 변형)을 사용하지만 표준에서는이를 요구하지 않습니다.

엄격한 언어의 경우에도 참조 언어를 변경하는 경우에만 기능 언어 간의 차이를 관찰 할 수 있으므로 기능 언어의 참조 별 전달 또는 값별 전달을 구분하는 것은 의미가 없습니다. 따라서 구현자는 언어의 의미를 어지럽히 지 않고 둘 사이에서 자유롭게 선택할 수 있습니다.


답변

언어의 호출 모델, 인수 유형 및 언어의 메모리 모델에 따라 다른 동작이 있습니다.

단순 기본 유형의 경우 값을 전달하면 레지스터에서 값을 전달할 수 있습니다. 메모리에서 값을로드하거나 다시 저장할 필요가 없으므로 매우 빠릅니다. 호출자가 오브젝트의 호출자 사본을 망칠 위험없이 인수가 완료되면 인수가 사용한 메모리를 재사용함으로써 유사한 최적화가 가능합니다. 인수가 임시 객체라면 아마도 전체 사본을 저장했을 것입니다 (C ++ 11은 새로운 오른쪽 참조 및 이동 의미론을 통해 이러한 종류의 최적화를보다 분명하게 만듭니다).

많은 OO 언어에서 (이 컨텍스트에서는 C ++이 더 예외 임) 개체를 값으로 전달할 수 없습니다. 참조로 전달해야합니다. 이것은 기본적으로 코드를 다형성으로 만들고 OO에 적합한 인스턴스 개념과 더 일치합니다. 또한 값을 기준으로 전달하려면 이러한 작업을 생성 한 성능 비용을 확인하여 직접 사본을 만들어야합니다. 이 경우 언어는 최상의 성능을 제공 할 수있는 접근 방식을 선택합니다.

기능적 언어의 경우, 값이나 참조를 전달하는 것이 단순히 최적화의 문제라고 생각합니다. 이러한 언어의 기능은 순수하고 부작용이 없으므로 속도를 제외하고 값을 복사 할 이유가 없습니다. 나는 그러한 언어가 종종 같은 값을 가진 동일한 객체의 사본을 공유한다는 것을 확신합니다. 이는 당신이 (const) 참조 의미론을 사용하는 경우에만 사용할 수 있습니다. 파이썬은 또한 정수와 문자열이 정수와 문자열이 파이썬에서 상수 객체 인 이유를 설명하는 정수 및 일반 문자열에이 트릭을 사용했습니다. 이는 또한 컨텐츠 비교 대신 포인터 비교를 허용하고 일부 내부 데이터의 지연 평가를 수행하여 코드를 다시 최적화하는 데 도움이됩니다.


답변

값으로 표현을 전달할 수 있습니다. 자연 스럽습니다. (임시) 참조로 표현을 전달하는 것은 … 이상합니다.


답변

참조로 전달하면 전역의 모든 문제 (즉, 범위 및 의도하지 않은 부작용)와 함께 항상 전역 값으로 효과적으로 작업하고 있습니다.

세계와 마찬가지로 참고 문헌은 유익하지만 때로는 첫 번째 선택이되어서는 안됩니다.