태그 보관물: programming-languages

programming-languages

암시 적 변환이없는 이유는 무엇입니까? 내가 알기로 암시

내가 알기로 암시 적 변환은 오류를 일으킬 수 있습니다.

그러나 그것은 의미가 없습니다. 정상적인 변환도 오류를 일으키지 않아야합니까?

왜 없어

len(100)

다음과 같이 해석하거나 컴파일하는 언어로 작업

len(str(100))

특히 그것이 그것이 작동 하는 유일한 방법 이기 때문에 . 언어는 오류가 무엇인지 알고 왜 수정하지 않습니까?

이 예제에서는 파이썬을 사용했지만이 작은 것에는 기본적으로 보편적이라고 생각합니다.



답변

무엇의 가치를 들면 len(str(100)), len(chr(100))그리고 len(hex(100))모든 다른입니다. 파이썬에서 정수에서 문자열로 하나 이상의 다른 변환이 있기 때문에 이것이 작동하는 유일한 방법 str아닙니다 . 물론 그중 하나가 가장 일반적이지만, 그것이 당신이 의미 한 것은 말할 필요도 없습니다. 암묵적인 변환은 문자 그대로 “말하지 않고 간다”를 의미합니다.

암시 적 변환의 실제 문제점 중 하나 는 몇 가지 가능성이있는 경우 어떤 변환이 적용되는지 항상 명확 하지 않다는 것입니다. 따라서 독자는 올바른 암시 적 변환을 파악하지 못하기 때문에 코드를 해석 할 때 오류가 발생합니다. 모든 사람들은 항상 그들이 의도 한 것은 “분명한 해석”이라고 말합니다. 그들이 의미하는 바이기 때문에 그들에게는 분명합니다. 다른 사람에게는 분명하지 않을 수 있습니다.

그렇기 때문에 (대부분의 경우) 파이썬은 암시적인 것보다 명시적인 것을 선호하고 위험을 감수하지 않는 것을 선호합니다. 파이썬이 강제 변환을 수행하는 주된 경우는 산술입니다. 그것은 수 있습니다 1 + 1.0대안이 살 너무 짜증나는 일 것이기 때문에,하지만 허용하지 않습니다 1 + "1"당신이 무슨 뜻인지 지정해야한다고 생각하기 때문에 int("1"), float("1"), ord("1"), str(1) + "1"다른, 또는 무언가를. 또한 결과 유형을 선택하기위한 규칙을 정의하는 (1,2,3) + [4,5,6]것처럼 결과 유형을 선택하기위한 규칙을 정의 할 있지만을 허용하지 않습니다 1 + 1.0.

다른 언어는 동의하지 않으며 많은 암시 적 변환이 있습니다. 더 많이 포함할수록 덜 명확 해집니다. 아침 식사 전에 “정수 프로모션”및 “일반적인 산술 변환”에 대한 C 표준 규칙을 기억해보십시오!


답변

내가 알기로 암시 적 변환은 오류를 일으킬 수 있습니다.

단어가 누락되었습니다. 암시 적 변환으로 인해 런타임 오류 가 발생할 수 있습니다 .

당신이 보여주는 것과 같은 간단한 경우에, 당신이 의미하는 것이 분명합니다. 그러나 언어는 사례에서 작동하지 않습니다. 규칙을 다루어야합니다. 다른 많은 상황에서는 프로그래머가 잘못된 유형을 사용하여 오류가 발생했는지 또는 프로그래머가 코드에서 의도 한대로 수행하려고했는지 명확하지 않습니다.

코드가 잘못되었다고 가정하면 런타임 오류가 발생합니다. 추적하기가 지루하기 때문에 많은 언어가 엉망이고 컴퓨터가 실제로 무엇을 의미하는지 (버그 수정 또는 명시 적으로 변환) 컴퓨터에 알려주는 측면으로 잘못되었습니다. 다른 언어는 그 스타일이 디버그하기 쉬운 빠르고 쉬운 코드에 적합하기 때문에 추측을합니다.

한 가지 주목할 점은 암시 적 변환으로 인해 컴파일러가 좀 더 복잡해집니다. 당신은 사이클에 대한 자세한 조심해야 (의는 A로부터 B에이 변환을 시도하자;! 작업 그렇지 않은 죄송하지만,이 변환은 B에서 A의 와 C와 D가 너무주기를 크기에 대해 다음 걱정할 필요 ), 어떤 암묵적인 전환을 피하려는 작은 동기입니다.


답변

암시 적 변환이 가능합니다. 문제가 발생하는 상황은 어떤 방식으로 작동해야하는지 모르는 경우입니다.

이 예제는 +운영자가 다른 시간에 다른 방식으로 작업 하는 Javascript에서 볼 수 있습니다 .

>>> 4 + 3
7
>>> "4" + 3
43
>>> 4 + "3"
43

인수 중 하나가 문자열 인 경우 +연산자는 문자열 연결이며 그렇지 않은 경우 추가입니다.

인수가 주어졌고 그것이 문자열인지 정수인지 모르고 그것을 추가하고 싶다면 약간 혼란 스러울 수 있습니다.

이것을 다루는 또 다른 방법은 기본 유산에서 온 것입니다 (펄은 다음과 같습니다- 프로그래밍은 어렵다, 스크립팅은 가십시오 … ).

Basic에서는 len함수가 String에서 호출되는 것이 의미가 있습니다 ( Visual Basic의 경우 문서 : “모든 유효한 문자열 표현식 또는 변수 이름. Expression이 Object 유형 인 경우 Len 함수는 파일에 기록 될 크기를 반환합니다. FilePut 기능. “).

Perl은 이러한 맥락 개념을 따릅니다. 에 대한 유형의 암시 적 변환과 자바 스크립트에 존재하는 혼란 +운영자가 때때로 추가되고, 때로는 연결이 펄에서 발생하지 않습니다이 있기 때문 +입니다 항상 추가 및 .입니다 항상 연결.

스칼라 컨텍스트에서 스칼라로 사용되는 항목 (예 : 목록을 스칼라로 사용하는 경우 목록은 해당 길이에 해당하는 숫자 인 것처럼 동작 함) 문자열 연산자 ( eq등식 테스트, cmp문자열 비교)를 사용하는 경우 스칼라는 문자열 인 것처럼 사용됩니다. 마찬가지로, 수학 문맥에서 어떤 것이 ( ==등식 테스트 및 <=>숫자 비교를 위해) 사용 된 경우 스칼라는 숫자 인 것처럼 사용됩니다.

모든 프로그래밍의 기본 규칙은 “사람을 가장 놀라게하는 것”입니다. 그렇다고해서 놀라움이 없다는 것을 의미하는 것은 아니지만 그 노력은 사람을 가장 놀라게하는 것입니다.

perl-php의 가까운 사촌으로 가면 연산자가 문자열이나 숫자 컨텍스트에서 무언가에 대해 행동 할 수 있고 사람들에게 그 행동이 놀라운 상황이 있습니다. ++작업자는 하나의 이러한 예이다. 숫자에서는 예상대로 정확하게 동작합니다. 과 같은 문자열에 작용할 때 문자열 "aa"을 증가시킵니다 ( $foo = "aa"; $foo++; echo $foo;prints ab). 또한 az증분 될 때가 되도록 롤오버 됩니다 ba. 이것은 아직 놀라운 일이 아닙니다.

$foo = "3d8";
echo "$foo\n";
$foo++;
echo "$foo\n";
$foo++;
echo "$foo\n";
$foo++;
echo "$foo\n";

( 아이디어 )

인쇄됩니다 :

3d8
3d9
3e0
4

암시 적 변환 및 연산자가 동일한 문자열에서 다르게 작동하는 위험에 오신 것을 환영합니다. (Perl은 코드 블록을 조금 다르게 처리합니다.- 연산자가 적용될 "3d8"++시작부터 숫자 값으로 결정하고 4바로 가기 ( ideone )-이 동작은 perlop에 잘 설명되어 있습니다 : 자동 증가 및 자동 감소 )

이제 왜 한 언어가 어떤 방식으로 무언가를하고 다른 언어가 다른 방식으로 디자이너의 디자인 사고에 도달 하는가? Perl의 철학은 하나 이상의 방법이 있다는 것입니다. 저는 이러한 작업을 수행하는 여러 가지 방법을 생각할 수 있습니다. 다른 한편으로, 파이썬은 PEP 20-파이썬의 선 (Phen of Zen of Python)에 기술 된 철학을 가지고 있습니다. “그것을하는 명백한 방법이 있어야합니다.

이러한 디자인 차이로 인해 다른 언어가 사용되었습니다. 파이썬에서 숫자의 길이를 얻는 한 가지 방법이 있습니다. 암묵적인 전환은이 철학에 위배됩니다.

관련 자료 : Ruby에서 Fixnum을 문자열로 암시 적으로 변환하지 않는 이유는 무엇입니까?


답변

ColdFusion이이 대부분을 수행했습니다. 암시 적 변환을 처리하기위한 일련의 규칙을 정의하고 단일 변수 유형을 가지고 있습니다.

결과는 총 무정부 상태이며, “4a”를 6에 더하면 6.16667입니다.

왜? 두 변수 중 첫 번째 변수는 숫자이므로 결과는 숫자입니다. “4a”는 날짜로 구문 분석되며 “4 AM”으로 표시됩니다. 오전 4시는 4 : 00/24 ​​: 00 또는 하루의 1/6입니다 (0.16667). 6에 더하면 6.16667이됩니다.

목록에는 쉼표의 기본 구분 문자가 있으므로 쉼표가 포함 된 목록에 항목을 추가 한 경우 두 항목 만 추가했습니다. 또한 목록은 비밀리에 문자열이므로 하나의 항목 만 포함하면 날짜로 구문 분석 할 수 있습니다.

문자열 비교는 두 문자열을 날짜로 먼저 구문 분석 할 수 있는지 확인합니다. 날짜 유형이 없으므로 그렇게합니다. 숫자, 8 진 표기법 및 부울 ( “true”및 “yes”등)을 포함하는 숫자 및 문자열에 대해서도 동일합니다.

ColdFusion은 빠른 실패와 오류보고 대신 데이터 유형 변환을 처리합니다. 그리고 좋은 방법은 아닙니다.

물론 DateCompare와 같은 명시 적 함수를 호출하여 암시 적 변환을 수정할 수 있지만 암시 적 변환의 “혜택”을 잃어 버렸습니다.


ColdFusion의 경우 개발자에게 권한을 부여하는 데 도움이됩니다. 특히 모든 개발자가 HTML에 익숙한 경우 (ColdFusion은 태그와 함께 작동하며 CFML이라고하며 나중에 <cfscript>모든 것을 위해 태그를 추가 할 필요가없는 스크립팅 을 추가했습니다). 그리고 무언가를 원할 때 잘 작동합니다. 그러나 좀 더 정확한 방식으로 일을해야하는 경우 실수 였을 가능성이있는 것처럼 보이는 것을 암시 적으로 변환하지 않는 언어가 필요합니다.


답변

당신은 암시 적 변환이 같은 모호 작업에 대한 좋은 생각이 될 수 있다는 말을하는지 int a = 100; len(a)당신은 분명히 평균 호출하기 전에 문자열로 INT 변환.

하지만 이러한 호출 될 수 있다는 것을 잊고있는 구문 모호하지만, 그들은 전달하는 의미 프로그래머에 의해 만들어진 오타 나타낼 수 a1있는 것입니다 문자열을. 이것은 고안된 예이지만 변수 이름에 자동 완성 기능을 제공하는 IDE를 사용하면 이러한 실수가 발생합니다.

유형 시스템은 오류를 피하는 데 도움이되고보다 엄격한 유형 검사를 선택하는 언어의 경우 암시 적 변환이이를 손상시킵니다.

==에 의해 수행되는 모든 암시 적 변환으로 Javascript의 문제를 확인하여 많은 사람들이 no-implicit-conversion === 연산자를 고수하는 것이 좋습니다.


답변

당신의 진술의 맥락을 잠시 고려하십시오. 이것이 “유일한 방법”이라고 말하지만 실제로 그렇게 작동 할 것이라고 확신하십니까? 이건 어때?

def approx_log_10(s):
    return len(s)
print approx_log_10(3.5)  # "3" is probably not what I'm expecting here...

다른 사람들이 언급했듯이, 매우 구체적인 예에서 컴파일러가 의미를 직관적으로 표현하는 것이 간단 해 보입니다. 그러나 더 복잡한 프로그램의 더 큰 맥락에서 문자열을 입력하거나 다른 변수 이름을 입력하거나 잘못된 함수 또는 수십 가지 다른 잠재적 논리 오류를 입력할지 여부는 종종 분명하지 않습니다. .

인터프리터 / 컴파일러가 의미하는 바를 추측하는 경우 때로는 마술처럼 작동하며, 다른 경우에는 별다른 이유없이 신비하게 작동하지 않는 무언가를 디버깅하는 데 몇 시간을 소비합니다. 평균적으로, 진술이 이해가되지 않는다는 말을 듣는 것이 훨씬 안전하며, 실제로 의도 한 바에 맞게 수정하는 데 몇 초가 소요됩니다.


답변

암시 적 변환은 작업하기가 매우 어려울 수 있습니다. PowerShell에서 :

$a = $(dir *.xml) # typeof a is a list, because there are two XML files in the folder.
$a = $(dir *.xml) # typeof a is a string, because there is one XML file in the folder.

암시 적 변환이없는 것보다 두 배나 많은 테스트가 필요하고 두 배나 많은 버그가 있습니다.