약한 유형의 언어와 관련하여 명백한 모순에 대해 설명하기 Perl이 명시 적으로 변환되지

필자는 강력한 타이핑을 이해한다고 생각 하지만 약한 타이핑에 대한 예제를 찾을 때마다 유형을 자동으로 강제 변환 / 변환하는 프로그래밍 언어의 예제를 찾습니다.

예를 들어, Typing : Strong vs. Weak 라는 기사 에서 Static vs. Dynamic 은 다음 과 같은 경우 예외가 발생하므로 Python이 강력하게 입력된다고 말합니다.

파이썬

1 + "1"
Traceback (most recent call last):
File "", line 1, in ? 
TypeError: unsupported operand type(s) for +: 'int' and 'str'

그러나 Java와 C #에서는 그러한 일이 가능하며 그 유형에 대해서만 약한 유형으로 간주하지는 않습니다.

자바

  int a = 10;
  String b = "b";
  String result = a + b;
  System.out.println(result);

씨#

int a = 10;
string b = "b";
string c = a + b;
Console.WriteLine(c);

Weakly Type Languages 라는 다른 기사 에서 저자는 Perl이 명시 적으로 변환되지 않고 문자열을 숫자로 또는 그 반대로 연결할 수 있기 때문에 약하게 유형이 지정되었다고 말합니다.

$a=10;
$b="a";
$c=$a.$b;
print $c; #10a

따라서 동일한 예제는 Perl을 약하게 입력했지만 Java 및 C #은 아닙니다.

이봐, 혼란스러워 여기에 이미지 설명을 입력하십시오

저자는 다른 유형의 값에 대한 특정 작업의 적용을 방해하는 언어가 강력하게 입력되고 반대로 의미가 약한 유형임을 암시하는 것으로 보입니다.

따라서 언젠가는 언어가 많은 자동 변환을 제공하거나 유형 사이의 강제 변환이 (약식으로) 약한 유형으로 간주 될 수 있지만, 약간의 변환 만 제공하는 다른 언어는 결국에는 강력하게 입력 된 것으로 간주됩니다.

그러나 나는이 해석에있어서 틀렸다는 것을 믿기를 원한다. 나는 왜 그것을 어떻게 설명해야하는지 모른다.

그래서 내 질문은 :

  • 언어가 실제로 약하게 입력되었다는 것은 실제로 무엇을 의미합니까?
  • 언어에 의한 자동 변환 / 자동 강제와 관련이없는 약한 타이핑의 좋은 예를 언급 할 수 있습니까?
  • 언어를 약하고 타이핑 할 수 있습니까?


답변

업데이트 : 이 질문은 2012 년 10 월 15 일에 제 블로그의 주제였습니다. 훌륭한 질문에 감사드립니다!


언어가 “약하게 입력 된”다는 것은 무엇을 의미합니까?

“이 언어는 내가 싫어하는 타입 시스템을 사용합니다”라는 의미입니다. 대조적으로 “강력한 유형의”언어는 유쾌한 유형 시스템을 갖춘 언어입니다.

용어는 본질적으로 의미가 없으므로 피해야합니다. Wikipedia 에는 “강력한 유형”에 대한 11 가지 다른 의미가 나열되어 있으며 그 중 일부는 모순됩니다. 이는 “강력한 유형”또는 “약한 유형”이라는 용어가 포함 된 대화에서 혼동이 발생할 가능성이 높다는 것을 나타냅니다.

실제로 확실하게 말할 수있는 것은 논의중인 “강력한 유형의”언어가 런타임 또는 컴파일 타임에 유형 시스템에 추가 제한이 있다는 점입니다. 추가 제한 없이는 그러한 제한을 결정할 수 없습니다.

“강력한 유형”및 “약한 유형”을 사용하는 대신 어떤 종류의 유형 안전을 의미하는지 자세히 설명해야합니다. 예를 들어 C #은 대부분 정적으로 형식이 지정된 언어이며 형식이 안전한 언어이며 메모리가 안전한 언어 입니다.. C #을 사용하면 이러한 세 가지 “강력한”타이핑 형식을 모두 위반할 수 있습니다. 캐스트 연산자는 정적 입력을 위반합니다. 컴파일러에게 “이 표현식의 런타임 유형에 대해 더 많이 알고 있습니다”라고 말합니다. 개발자가 잘못된 경우 형식 안전성을 보호하기 위해 런타임에서 예외가 발생합니다. 개발자가 유형 안전 또는 메모리 안전을 중단하려면 “안전하지 않은”블록을 만들어 유형 안전 시스템을 끄면됩니다. 안전하지 않은 블록에서는 포인터 매직을 사용하여 int를 float (유형 안전 위반)로 취급하거나 소유하지 않은 메모리에 쓸 수 있습니다. (메모리 안전 위반)

C #에서는 컴파일 타임과 런타임에 모두 확인되는 형식 제한을 적용하여 컴파일 타임 확인이 적거나 런타임 확인이 적은 언어와 비교하여 “강력한 형식의”언어로 만듭니다. 또한 C #을 사용하면 특수한 상황에서 이러한 제한 사항에 대한 최종 실행을 수행 할 수 있으므로 이러한 최종 실행을 수행 할 수없는 언어와 비교하여 “약한 형식의”언어가됩니다.

어느 것이 진짜입니까? 말하는 것은 불가능합니다. 그것은 화자의 관점과 다양한 언어 기능에 대한 그들의 태도에 달려 있습니다.


답변

다른 사람들이 지적했듯이, “강력한 유형”과 “약한 유형”이라는 용어는 매우 다양한 의미를 지니므로 귀하의 질문에 대한 단일 답변이 없습니다. 그러나 질문에 Perl을 구체적으로 언급했기 때문에 Perl이 약하게 입력 된 의미를 설명하려고합니다.

요점은 Perl에는 “정수 변수”, “부동 변수”, “문자열 변수”또는 “부울 변수”와 같은 것이 없다는 것입니다. 사실, 사용자가 (보통) 말할 수있는 한, 정수, 부동 소수점, 문자열 또는 부울 값도 없습니다 . “스칼라”만 있으면됩니다. 예를 들어 다음과 같이 쓸 수 있습니다.

$foo = "123" + "456";           # $foo = 579
$bar = substr($foo, 2, 1);      # $bar = 9
$bar .= " lives";               # $bar = "9 lives"
$foo -= $bar;                   # $foo = 579 - 9 = 570

물론, 당신이 올바르게 지적했듯이,이 모든 것은 단지 유형 강제라고 볼 수 있습니다. 그러나 요점은 Perl에서 유형은 항상 강제 된다는 것 입니다. 사실, 사용자는 변수의 내부 “유형”이 무엇인지 말하기가 매우 어렵습니다. 위의 예제에서 2 행에서 값이 $bar문자열 "9"인지 또는 숫자 9인지는 거의 의미가 없습니다. Perl에 관한 한, 그것들은 같습니다 . 실제로, 내부적으로이에 펄 스칼라에 대해서도 가능 모두 로의 경우를 예입니다, 문자열과 같은 시간에 숫자 값을 $foo줄이 후 위.

이것의 단점은 Perl 변수가 형식화되지 않았기 때문에 (또는 내부 유형을 사용자에게 노출시키지 않기 때문에) 연산자가 다른 유형의 인수에 대해 다른 작업을 수행하도록 오버로드 될 수 없다는 것입니다. “이 연산자는 숫자에 대해 X를, 문자열에 대해 Y를 수행 할 것”이라고 말할 수는 없습니다. 연산자는 인수가 어떤 종류의 값인지 알 수 없기 때문입니다.

예를 들어, Perl에는 숫자 덧셈 연산자 ( +)와 문자열 연결 연산자 ( .) 가 모두 필요합니다. 위에서 보았 듯이 문자열 ( "1" + "2" == "3") 을 추가 하거나 숫자 ( 1 . 2 == 12) 를 연결하는 것이 좋습니다. 마찬가지로, 수치 비교 연산자 ==, !=, <, >, <=, >=그리고 <=>그들의 인수의 숫자 값을 비교, 문자열 비교 연산자는 동안 eq, ne, lt, gt, le, gecmp문자열로 사전 식을 비교합니다. 그래서 2 < 10, 그러나 2 gt 10(그러나 "02" lt 10, "02" == 2). ( 자바 스크립트와 같은 다른 언어는 Perl과 같은 약한 입력을 수용하려고합니다.또한 연산자 오버로드를 수행합니다. 이것은 종종 연관성을 잃는 것과 같이 추함을 초래합니다 +.)

(여기서 연고의 비행은 역사적 이유로 Perl 5에는 비트 논리 연산자와 같이 몇 가지 모퉁이가 있으며, 그 논리적 인 동작은 인수의 내부 표현에 따라 달라집니다. 내부 표현은 놀라운 이유로 변경 될 수 있으므로 주어진 상황에서 해당 운영자가 수행하는 작업을 예측하는 것은 까다로울 수 있습니다.)

모든 사람이 펄이 주장 할 수, 말했다 않는 강한 유형이있다; 그들은 당신이 기대할 수있는 종류의 유형이 아닙니다. 특히, 위에서 설명한 “scalar”유형 외에도 Perl에는 “array”및 “hash”라는 두 가지 구조화 된 유형이 있습니다. 스칼라와 는 매우 다르며, Perl 변수 의 유형 ( 스칼라, 배열, 해시) 1을 나타내는 서로 다른 시길이 있습니다. 이 있습니다 당신은 그래서 이러한 유형의 사이에 강제 변환 규칙은 할 수 예를 들어, 쓰기 ,하지만 그들 중 많은 사람들이 매우 손실이 있습니다 : 예를 들어, 할당 길이 배열 로를$@%%foo = @bar$foo = @bar@bar$foo내용이 아닙니다. (또한 typeglobs 및 I / O 핸들과 같이 자주 노출되지 않는 몇 가지 다른 이상한 유형이 있습니다.)

또한이 멋진 디자인의 약간의 단점은 특수 유형의 스칼라 (및 연산자를 사용하여 일반 스칼라와 구별 할 수 있는) 참조 유형의 존재입니다 ref. 참조를 일반 스칼라로 사용할 수 있지만 문자열 / 숫자 값은 특히 유용하지 않으며 일반 스칼라 연산을 사용하여 수정하면 특수 참조가 손실되는 경향이 있습니다. 또한 모든 Perl 변수 2bless클래스에 연결되어 해당 클래스의 객체로 바뀔 수 있습니다 . Perl의 OO 클래스 시스템은 위에서 설명한 기본 유형 (또는 유형이없는) 시스템과 다소 직교하지만 오리 입력 을 따르는 의미에서 “약한”어형 변화표. 일반적인 의견은 Perl에서 객체의 클래스를 확인하면 무언가 잘못하고 있다는 것입니다.


1 실제로, sigil은 액세스되는 값의 유형을 @foo나타내 므로 배열의 첫 번째 스칼라 가 표시 $foo[0]됩니다. 자세한 내용은 perlfaq4 를 참조하십시오.

2 Perl의 객체는 일반적으로 객체에 대한 참조를 통해 액세스되지만 실제로 얻는 bless것은 참조가 가리키는 (익명) 변수입니다. 그러나 축복은 실제로 그 가치가 아니라 변수의 속성입니다. 예를 들어, 실제 축복 변수를 다른 변수에 할당하면 변수의 얕고 축복 되지 않은 사본 만 얻게됩니다. 자세한 내용은 perlobj 를 참조하십시오.


답변

Eric이 말한 것 외에도 다음 C 코드를 고려하십시오.

void f(void* x);

f(42);
f("hello");

Python, C #, Java 등과 같은 언어와 달리 위의 내용 유형 정보 가 손실 되기 때문에 약하게 입력 됩니다 . Eric은 C #에서“캐스팅을 통해 컴파일러를 우회하여“이 변수의 유형에 대해 더 많이 알고 있습니다”라고 효과적으로 지적했습니다.

그러나 그럼에도 불구하고 런타임은 여전히 ​​유형을 검사합니다! 캐스트가 유효하지 않으면 런타임 시스템이 캐스트를 포착하여 예외를 처리합니다.

유형 삭제를 사용하면 이런 일이 발생하지 않습니다. 유형 정보가 삭제됩니다. void*C 로의 캐스트 는 정확히 그렇게합니다. 이와 관련하여 위의 내용은와 같은 C # 메서드 선언과 근본적으로 다릅니다 void f(Object x).

기술적으로 C #에서는 안전하지 않은 코드 나 마샬링을 통해 형식을 지울 수도 있습니다.

이것은 약한 유형입니다. 다른 모든 정적 대의 동적 유형 검사, 즉 시간의 문제이다 타입이 선택된다.


답변

강력한 타이핑 위키피디아 기사 에서 완벽한 예를 들어 보자 .

일반적으로 강력한 타이핑은 프로그래밍 언어가 허용되는 혼합에 심각한 제한을가한다는 것을 의미합니다.

약한 타이핑

a = 2
b = "2"

concatenate(a, b) # returns "22"
add(a, b) # returns 4

강력한 타이핑

a = 2
b = "2"

concatenate(a, b) # Type Error
add(a, b) # Type Error
concatenate(str(a), b) #Returns "22"
add(a, int(b)) # Returns 4

타이핑 언어가 약하면 오류없이 여러 유형을 혼합 할 수 있습니다. 강력한 형식 언어를 사용하려면 입력 형식이 예상 형식이어야합니다. 강력한 유형의 언어에서 유형을 변환 ( str(a)정수를 문자열로 변환)하거나 캐스트 ( int(b)) 할 수 있습니다.

이것은 모두 타이핑 해석에 달려 있습니다.


답변

다른 사람들이 의견을 밝히고 의견을 밝히면서 주제에 대한 저 자신의 연구와의 토론에 기여하고 싶습니다. 나는 그들의 답변을 읽고 그들의 참조를 따르고 흥미로운 정보를 찾았습니다. 제안 된 바와 같이,이 중 대부분은 실제적인 것보다 이론적 인 것으로 보이므로 프로그래머 포럼에서 더 잘 논의 될 가능성이 높습니다.

이론적 인 관점에서 Luca Cardelli와 Peter Wegner의 기사에서 유형 이해, 데이터 추상화 및 다형성에 관한 기사 는 내가 읽은 최고의 주장 중 하나라고 생각합니다.

유형은 기본 유형화되지 않은 표현을 임의적이거나 의도하지 않은 사용으로부터 보호하는 옷 세트 (또는 갑옷)로 볼 수 있습니다 . 기본 표현을 숨기고 객체가 다른 객체와 상호 작용하는 방식을 제한하는 보호 덮개를 제공합니다. 형식화되지 않은 시스템에서 지정되지 않은 객체는 알몸
모두가 볼 수 있도록 기본 표현이 노출되도록한다. 유형 시스템을 위반하는 것은 보호 복 세트를 제거하고 알몸으로 직접 작업하는 것을 포함합니다.

이 문장은 약한 타이핑으로 유형의 내부 구조에 액세스하여 다른 유형 (다른 유형) 인 것처럼 조작 할 수 있다고 제안합니다. 안전하지 않은 코드 (Eric에서 언급 한) 또는 Konrad에서 언급 한 c 유형의 지워진 포인터로 수행 할 수있는 작업 일 수 있습니다.

기사는 계속됩니다 …

모든식이 형식이 일치 하는 언어를 강력한 형식의 언어라고합니다. 언어가 강력하게 형식화 된 경우 컴파일러는 허용되는 프로그램이 형식 오류없이 실행되도록 보장 할 수 있습니다. 일반적으로 강력한 타이핑을 위해 노력하고 가능할 때마다 정적 타이핑을 채택해야합니다. 정적으로 유형이 지정된 모든 언어는 강력하게 유형이 지정되지만 그 반대의 경우는 아닙니다.

따라서 강력한 타이핑은 유형 오류가 없음을 의미하며, 약한 타이핑은 반대로 유형 오류가 있음을 의미한다고 가정 할 수 있습니다. 런타임 또는 컴파일 타임? 여기에 관련이없는 것 같습니다.

이 정의에 따르면 Perl과 같은 강력한 유형 강제 변환을 사용하는 언어는 시스템이 실패하지 않기 때문에 강력하게 유형화 된 것으로 간주되지만 유형을 적절하고 잘 정의 된 동등성으로 강제 처리하여 유형을 처리합니다.

반면에, 나는의 수당보다 말할 수 ClassCastExceptionArrayStoreException와 (자바) InvalidCastException,ArrayTypeMismatchException 컴파일시에 적어도 약하게 입력의 수준을 나타냅니다 (C #에서)? 에릭의 대답은 이것에 동의하는 것 같습니다.

Luca Cardelli는이 질문에 대한 답변 중 하나에 제공된 참고 문헌 중 하나에서 제공되는 Typeful Programming 이라는 두 번째 기사 에서 유형 위반의 개념을 탐구합니다.

대부분의 시스템 프로그래밍 언어는 임의의 유형 위반을 허용하며, 일부는 무차별 적으로, 일부는 프로그램의 제한된 부분에서만 허용됩니다. 형식 위반과 관련된 작업을 소리가 나지 않습니다. 유형 위반은 몇 가지 클래스로 나뉩니다.

기본 값 강제 : 여기에는 정수, 부울, 문자, 집합 등의 변환이 포함됩니다. 여기에서는 유형 사운드 방식으로 강제를 수행하기 위해 내장 인터페이스를 제공 할 수 있기 때문에 유형 위반이 필요하지 않습니다.

따라서 운영자가 제공하는 것과 같은 유형 강제는 유형 위반으로 간주 될 수 있지만 유형 시스템의 일관성을 위반하지 않으면 유형이 약한 시스템으로 이어지지 않는다고 말할 수 있습니다.

이를 기반으로 Python, Perl, Java 또는 C #은 약하게 입력되지 않습니다.

Cardelli는 실제로 타이핑이 약한 두 가지 유형의 위반을 언급합니다.

주소 산술. 필요한 경우, 내장 된 (소리가 들리지 않는) 인터페이스가 있어야 주소 및 유형 변환에 대한 적절한 작업을 제공 할 수 있습니다. 다양한 상황에는 힙에 대한 포인터 (콜렉터 재배치에 매우 위험), 스택에 대한 포인터, 정적 영역에 대한 포인터 및 다른 주소 공간에 대한 포인터가 포함됩니다. 때때로 배열 인덱싱이 주소 산술을 대체 할 수 있습니다.
메모리 매핑. 여기에는 구조화 된 데이터가 포함되어 있지만 메모리 영역을 구조화되지 않은 배열로 보는 것이 포함됩니다. 이것은 일반적인 메모리 할당 자 및 수집기입니다.

C (Konrad에 의해 언급 된)와 같은 언어 나 .Net (에릭에 의해 언급 된)의 안전하지 않은 코드를 통해 가능한 이런 종류의 것들은 실제로 타이핑이 약하다는 것을 의미합니다.

나는이 개념의 정의가 매우 이론적이며 특정 언어에 관해서는 이러한 모든 개념의 해석이 다른 논쟁의 여지가있는 결론으로 ​​이어질 수 있기 때문에 지금까지 가장 좋은 대답은 Eric의 것이라고 믿는다.


답변

타이핑이 약하다는 것은 실제로 높은 비율의 유형이 암묵적으로 강제되어 코더의 의도를 추측하려고 시도한다는 것을 의미합니다.

강력한 타이핑은 유형이 강요되지 않거나 최소한 강요되지 않음을 의미합니다.

정적 타이핑은 컴파일시 변수 유형이 결정됨을 의미합니다.

많은 사람들이 최근에 “매니 컬 타이핑”과 “강력 타이핑”을 혼동하고 있습니다. “매니페스트 유형”은 변수 유형을 명시 적으로 선언 함을 의미합니다.

부울 컨텍스트에서 거의 모든 것을 사용할 수 있지만 부울은 정수 컨텍스트에서 사용할 수 있으며 부동 컨텍스트에서 정수를 사용할 수 있지만 파이썬은 대부분 강력하게 유형이 지정됩니다. 타입을 선언 할 필요가 없기 때문에 명시 적으로 타이핑되지는 않습니다 (전적으로 파이썬은 아니지만 Cython은 제외). 또한 정적으로 입력되지 않습니다.

C 및 C ++는 명시 적으로 형식화되고 정적으로 형식화되고 다소 강력하게 형식화됩니다. 유형을 선언하고 컴파일 타임에 형식이 결정되며 정수와 포인터 또는 정수와 복식을 혼합하거나 한 유형에 대한 포인터를 캐스트 할 수 있기 때문에 다른 유형에 대한 포인터

Haskell은 명백하게 입력되지 않았지만 정적으로 강력하게 입력되기 때문에 흥미로운 예입니다.


답변

강한 <=> 약한 타이핑은 한 데이터 유형의 언어가 다른 데이터 유형에 대한 언어에 의해 자동으로 강요되는 양 또는 양에 대한 연속성뿐만 아니라 실제 이 얼마나 강하거나 약하게 입력 되는지에 관한 것 입니다. Python과 Java 및 대부분 C #에서 값의 유형은 스톤으로 설정됩니다. Perl에서는 그다지 많지 않습니다. 변수에 저장할 소수의 다른 값 유형이 실제로 있습니다.

사례를 하나씩 열어 봅시다.


파이썬

파이썬 예제 1 + "1"에서+ 연산자는 __add__for 유형 int을 호출하여 문자열 "1"을 인수로 제공 하지만 NotImplemented가됩니다.

>>> (1).__add__('1')
NotImplemented

다음으로 통역사는 __radd__str을 시도합니다 .

>>> '1'.__radd__(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute '__radd__'

실패하면 + 연산자는 결과와 함께 실패합니다 TypeError: unsupported operand type(s) for +: 'int' and 'str'. 따라서 예외는 강력한 타이핑에 대해 많이 말하지 않지만 연산자 가 강제하지 않는다는 사실+ 인수를 동일한 유형으로 자동으로 사실은 파이썬이 연속체에서 가장 약한 유형의 언어가 아니라는 사실에 대한 포인터입니다.

반면에 파이썬에서는 'a' * 5 구현됩니다.

>>> 'a' * 5
'aaaaa'

그건,

>>> 'a'.__mul__(5)
'aaaaa'

작업이 다르다는 사실은 약간의 타이핑이 필요합니다. * 곱하기 전에 값을 숫자 강제 변환하는 값을 약하게 입력 할 필요는 없습니다.


자바

Java 예제 String result = "1" + 1;는 편의상 연산자 +가 문자열에 과부하되어 있기 때문에 작동합니다 . 자바 +연산자는을 만드는 순서를 대체 StringBuilder합니다 ( )

String result = a + b;
// becomes something like
String result = new StringBuilder().append(a).append(b).toString()

이것은 실제 강제 StringBuilder가 없는 매우 정적 인 타이핑의 예입니다- append(Object)여기에 특별히 사용되는 방법 이 있습니다. 설명서는 다음과 같이 말합니다.

Object인수 의 문자열 표현을 추가합니다 .

전체적인 효과는 마치 인수가 메소드에 의해 문자열로 변환 된 것과 똑같이 String.valueOf(Object)해당 문자열의 문자가이 문자 시퀀스에 추가 된 것과 같습니다.

어디 String.valueOf다음

Object 인수의 문자열 표현을 리턴합니다. 인수가이면 null문자열이 "null"; 그렇지 않으면의 값 obj.toString()이 반환됩니다.

따라서 이것은 언어에 의한 강요가 전혀없는 경우입니다-모든 관심사를 객체 자체에 위임하십시오.


씨#

Jon Skeet의 답변 에 따르면 연산자 +string클래스와 Java와 비슷하게 오버로드되지 않으며 정적 및 강력한 타이핑 덕분에 컴파일러가 생성하는 편의성입니다.


perldata가 설명 하듯이

Perl에는 세 개의 기본 제공 데이터 유형 (스칼라, 스칼라 배열 및 “해시”라고하는 스칼라 배열)이 있습니다. 스칼라는 단일 문자열 (사용 가능한 메모리로만 제한되는 모든 크기), 숫자 또는 무언가에 대한 참조 (perlref에서 설명)입니다. 일반 배열은 0부터 시작하여 숫자로 색인화 된 스칼라 목록입니다. 해시는 연관된 문자열 키로 색인화 된 스칼라 값의 정렬되지 않은 콜렉션입니다.

그러나 Perl은 숫자, 부울, 문자열, null, undefineds, 다른 객체에 대한 참조 등에 대한 별도의 데이터 유형을 가지고 있지 않습니다 . 0은 “0”만큼의 스칼라 값입니다. 문자열로 설정된 스칼라 변수 는 실제로 숫자로 변경 될 수 있으며 숫자 컨텍스트에서 액세스하는 경우 “문자열”과 다르게 동작합니다.. 스칼라는 Perl에서 무엇이든 가질 수 있으며 시스템에 존재하는만큼의 오브젝트입니다. 파이썬에서 이름은 단지 객체를 참조하고, Perl에서 이름의 스칼라 값은 변경 가능한 객체입니다. 또한 객체 지향 유형 시스템은이 위에 붙어 있습니다. 스칼라, 목록 및 해시에는 3 가지 데이터 유형이 있습니다. Perl의 사용자 정의 객체 대한 참조 (이전 3 개 중 하나에 대한 포인터)입니다.bless패키지에 연결된 -이러한 값을 가져 와서 원하는 순간에 모든 클래스에 축복 할 수 있습니다.

펄은 심지어 값의 클래스를 변덕스럽게 바꿀 수 있습니다-파이썬에서 일부 클래스의 값을 생성하는 곳에서는 불가능합니다 object.__new__. 파이썬에서는 생성 후 객체의 본질을 실제로 바꿀 수 없으며, Perl에서는 많은 것을 할 수 있습니다.

package Foo;
package Bar;

my $val = 42;
# $val is now a scalar value set from double
bless \$val, Foo;
# all references to $val now belong to class Foo
my $obj = \$val;
# now $obj refers to the SV stored in $val
# thus this prints: Foo=SCALAR(0x1c7d8c8)
print \$val, "\n";
# all references to $val now belong to class Bar
bless \$val, Bar;
# thus this prints Bar=SCALAR(0x1c7d8c8)
print \$val, "\n";
# we change the value stored in $val from number to a string
$val = 'abc';
# yet still the SV is blessed: Bar=SCALAR(0x1c7d8c8)
print \$val, "\n";
# and on the course, the $obj now refers to a "Bar" even though
# at the time of copying it did refer to a "Foo".
print $obj, "\n";

따라서 타입 아이덴티티는 변수에 약하게 묶여 있으며, 어떤 참조를 통해서든 변경 될 수 있습니다. 사실, 당신이 할 경우

my $another = $val;

\$another\$val여전히 축복받은 참조를 줄 지라도, 학급 정체성이 없습니다 .


TL; DR

자동 강제보다는 Perl에 대한 약한 타이핑에 대해 훨씬 더 많은 것이 있으며, 동적이지만 매우 강력한 유형의 언어 인 Python과 달리 값 자체의 유형은 돌로 설정되지 않습니다. 파이썬이 제공 TypeError하는 1 + "1"것은 Java 또는 C #에서 강력하게 유형이 지정되는 언어를 배제하지 않는 것처럼 유용한 무언가를 수행하는 것과 반대로 언어가 강력하게 유형화되었음을 나타냅니다.