프로그래밍 언어를 아무리 좋아하더라도 항상 그다지 좋지 않은 세부 사항이 몇 가지 있습니다.
이 질문에서는 구문 요소 에 특별히 초점을 맞추고 싶습니다 . 자주 사용하는 프로그래밍 언어 (아마도 가장 좋아하는 프로그래밍 언어 또는 직장에서 사용해야하는 언어)에서 가장 읽을 수 없거나, 명확하지 않거나, 불편하거나 불쾌한 구문 요소는 무엇입니까?
프로그래밍 언어를 아무리 좋아하더라도 항상 그다지 좋지 않은 세부 사항이 몇 가지 있습니다.
이 질문에서는 구문 요소 에 특별히 초점을 맞추고 싶습니다 . 자주 사용하는 프로그래밍 언어 (아마도 가장 좋아하는 프로그래밍 언어 또는 직장에서 사용해야하는 언어)에서 가장 읽을 수 없거나, 명확하지 않거나, 불편하거나 불쾌한 구문 요소는 무엇입니까?
답변:
나는 종종 그것을 자주 물지 않았지만 그것은 단지 머리가 돌게 만드는 엄청나게 나쁜 생각입니다.
규칙은 다음과 같습니다 (ECMA-262 섹션 7.9 참조).
예:
return 1; // returns 1
return
1; // returns undefined
/**
* Name of user
*/
private String name;
/**
* Gets name of user
* @return Name of user
*/
public String getName() {
return this.name;
}
/**
* Sets name of user.
* @param name
*/
public void setName(final String name) {
this.name = name;
}
GAH !!!
내가 가진 문제
getX
, getY
, getZ
, getAnotherAnnoyingField
, getWhyIHateJavaBeans
, getThisIsVerbose
, getGAH
, ... 아, 거기입니다 hashCode
.public
. 멤버는 비공개이어야하며 클라이언트 코드의 getter 및 setter가 아닌 상위 수준의 논리를 사용하여 클래스에서 현명하게 조작해야합니다 .
파이썬은 이런 점에서 나를 귀찮게합니다. 어쨌든 제대로 들여 쓰기가 필요하지만 버그가 있습니다 . 구문의 표현 부분을 만드는 것은 저를 자극합니다.
switch
문 (C, C에서 + +, C #을, 자바, 등)다음은 내가 매우 불편한 이유의 예입니다.
switch (someVariable)
{
case 1:
int i = something();
doSomething(i);
break;
case 2:
int i = somethingElse();
doSomethingElse(i);
break;
}
변수 i
가 동일한 범위에서 다시 선언 되기 때문에 컴파일되지 않습니다 . 이것은 사소한 세부 사항처럼 보이지만 정말 자주 물립니다. 중괄호를 추가하여 완화시킬 수 있지만 중괄호가 구문의 필수 부분이었고 여분의 들여 쓰기 수준이 없으면 좋을 것입니다. 나는 또한 여분을 작성하는 것이 정말 싫어 break
. 이것은 훨씬 좋을 것입니다 :
switch (someVariable)
case 1
{
int i = something();
doSomething(i);
}
case 2
{
int i = somethingElse();
doSomethingElse(i);
}
default
{
...
}
이것은 if
/ else
chain 처럼 보이게 합니다. 시맨틱 적으로 비슷하기 때문에 좋은 것입니다. 적어도 C #에서는 여전히 똑같은 것은 아니지만 switch
명령문에서 케이스 레이블의 순서는 중요하지 않지만 if
/ else
에서는 중요합니다.
goto
이미 C #에서와 같이 더 명확하게 ( 또는 유사한 것을 사용하여 ) 만들면됩니다.
case Foo of 1,3: Result := 'odd'; 2,4: Result := 'even' end;
.
break
기본값이었고 상상할 필요 가 있다고 상상해보십시오 . 더 이상 언급 할 필요가 없습니다! :)
VB.NET에서 고정 배열을 초기화 할 때 C / C ++, PHP 또는 Java와 같은 요소 수가 아닌 배열의 상한을 지정한다는 것을 항상 잊어 버립니다 . VB6 외에도 (우리는 거기에 가지 않을 것입니다 ...), 나는 이런 식으로하는 다른 언어를 생각할 수 없습니다.
Dim myArray(20) as Integer '# Creates an array with 21 elements,
'# indexed from 0 to 20
대부분의 언어에서는 변수를 선언하고 한 줄의 코드로 변수를 할당 할 수 있습니다. 반면에 VB6은 두 가지를 사용하도록합니다.
Dim i as Integer
i = 0
Dim derpderp as Collection
Set derpderp = new Collection
콜론을 사용하여 두 개의 명령을 한 줄에 넣을 수 있지만 실제 코드에서는 빠르게 혼란스러워집니다.
Dim i as Integer: i = 0
Dim derpderp as Collection: Set derpderp = new Collection
Dim Hurp As New Collection
, Hurp
참조 할 때 액세스하면 액세스 Nothing
하기 전에 마술처럼 초기화됩니다. 명시 적으로 설정하고 Nothing
다시 터치하면 부활됩니다 ...
//
PHP 및 Javascript와 같은 다른 많은 언어에서와 같이 코드 줄을 주석 처리하지 않습니다. /* this is commented out */
작동 하지만 을 사용하는 것을 선호합니다 //
.
절반의 시간이 CSS를 편집하는 것을 잊고 돌아가서 오류를 수정해야하기 때문에 귀찮습니다.
PHP는 배열이나 문자열에서 생각할 수있는 거의 모든 작업을 수행하기위한 많은 편리한 기능을 가지고 있습니다. 이러한 많은 작업은 a $needle
와 a 를 모두 사용해야 $haystack
하지만 서로 다른 함수는 순서가 다릅니다. 어느 함수가 어떤 인수를 요구하는지는 내가 얼마나 자주 그것들을 만나더라도 내 두뇌가 흡수하지 않는 사실 중 하나입니다!
기능을 가지고 와 in_array 및 않는 strstr :
// Check whether $needle occurs in array $haystack
bool in_array (mixed $needle, array $haystack [, bool $strict])
// Check whether $needle is a substring of $haystack
string strstr (string $haystack, mixed $needle [, bool $before_needle=false])
재미있게도, PHP는 $haystack, $needle
배열 함수가 다른 방식으로 사용 되는 반면 모든 문자열 함수가 사용 되는 것처럼 보이기 때문에 이러한 순서와 내부적으로 일관성이있는 것처럼 보이지만 PHP를 처음 접하는 사람에게는 익숙해 질 수 있습니다. ExpressionEngine 에는 이 특정 기능에 대해 자세히 설명 하고 PHP 팀의 응답이 짧은 PHP 버그 목록에 대한 토론 이 있습니다.
helly@php.net
괜찮은 IDE를 사용하십시오.
$needle
, $haystack
이 말의 길을 생각 나게로 건초 더미에서 바늘 찾기 .
strstr
. 너무 아름답게 의미가 없습니다.
self
인스턴스 메소드 정의의 매개 변수
self
것은 쉽게 일어나고 시간이 걸립니다.
기간. 마침표. 이야기의 끝.
어디서 시작하나요? 오, 나는 어디서부터 시작해야하는지 안다 : 자바는 엄청나게 복잡하고 못 생기고 어리 석고 본질적으로 깨진 제네릭이다. 더 말할 필요가 있습니까? :( 좋아요, 다음 : type erasure .
그리고 비 결정적 리소스 관리가 있습니다. 켈프 풋처!
다음은 무엇입니까? 오 예 : Java의 어리석은 정규식 은 가장 짜증나고 소고기입니다. 백 슬래쉬가 충분하지 않아서 몇 번이나 호스를 쳤는지 셀 수 없습니다. 이것은이 밀레니엄에서 유니 코드 속성에 액세스 할 수없는 것보다 훨씬 나쁩니다. 구식 10 년이 지났습니다 !!! 완전히 쓸모없는. 휴지통
그런 다음 문자 클래스 바로 가기가 비 ASCII에서 작동하지 않는 버그가 있습니다. 왕의 고통! 그리고 사용하는 것도 고려하지 마십시오 \p{javaWhiteSpace}
. 몇 가지 매우 일반적인 유니 코드 공백 코드 포인트로 올바른 작업을 수행하지 않습니다.
당신은 \p{javaJavaIdentifierStart}
재산 이 있다는 것을 알고 있습니까? 그들은 무엇을 생각하고 있었습니까? 너무 똑똑해서 엿보는 똑똑한 엿보는 사람을 얻었습니다.
CANON_EQ 플래그를 사용해 보셨습니까? 당신은 그것이 실제로 무엇을 하지 않는지 알고 있습니까? 소위 "유니 코드 케이스"는 어떻습니까? 정상적인 케이스는 많이 작동하지 않습니다.
그런 다음 유지 관리 가능한 정규식을 작성하기가 어렵습니다. Java는 여전히 여러 줄 문자열을 작성하는 방법을 알지 못했기 때문에 다음과 같이 미친 것들을 작성하게됩니다.
"(?= ^ [A-Z] [A-Za-z0-9\\-] + $) \n"
+ "(?! ^ .* \n"
+ " (?: ^ \\d+ $ \n"
+ " | ^ [A-Z] - [A-Z] $ \n"
+ " | Invitrogen \n"
+ " | Clontech \n"
+ " | L-L-X-X \n"
+ " | Sarstedt \n"
+ " | Roche \n"
+ " | Beckman \n"
+ " | Bayer \n"
+ " ) # end alternatives \n"
+ ") # end negated lookahead \n"
그 줄 바꿈은 무엇입니까? 아, 그냥 자바 바보 야. 그들은 줄 끝까지가는 Java 주석 ( 바보! )이 아닌 Perl 주석을 사용했습니다 . 그래서 \n
거기에 넣지 않으면 나머지 패턴을 잘라냅니다. Duh and double duh!
자바에서 정규 표현식을 사용하지 마십시오 : 당신은 물건을 부수기를 원할 것입니다. 나는 사람들이 이것을 참는 것을 믿을 수 없다. 일부는 그렇지 않습니다 .
그런 다음 인코딩으로 Java의 바보 말도 안되는 이야기를 시작할 수 있습니다. 첫째, Java의 charchars가 Unicode 인 경우에도 기본 플랫폼 인코딩은 항상 약간의 8 비트 인코딩이라는 사실이 있습니다. 그런 다음 인코딩 오류에 대해 예외를 발생시키지 않는 방법이 있습니다. 당신은 쓰레기가 보장됩니다. 아니면 어떻습니까?
OutputStreamWriter(OutputStream out)
Creates an OutputStreamWriter that uses the default character encoding.
OutputStreamWriter(OutputStream out, Charset cs)
Creates an OutputStreamWriter that uses the given charset.
OutputStreamWriter(OutputStream out, CharsetEncoder enc)
Creates an OutputStreamWriter that uses the given charset encoder.
OutputStreamWriter(OutputStream out, String charsetName)
Creates an OutputStreamWriter that uses the named charset.
차이점이 뭐야? 인코딩 오류가있는 경우 그 중 하나만 예외가 발생 한다는 것을 알고 있습니까? 나머지는 그냥 총구입니다.
그런 다음 캐릭터를 보유하기에 충분하지 않은 Java 문자의 관용구가 있습니다! 그들은 무엇을 생각하고 있습니까? 그래서 나는 그들을 charchars라고 부릅니다. 제대로 작동하려면 다음과 같은 코드를 작성해야합니다.
private static void say_physical(String s) {
System.out.print("U+");
for (int i = 0; i < s.length(); i++) {
System.out.printf("%X", s.codePointAt(i));
if (s.codePointAt(i) > Character.MAX_VALUE) { i++; } // UG!
if (i+1 < s.length()) { System.out.printf("."); }
}
}
누가 그런 생각을합니까? 아무도 옆에.
몇 문자가 "\uD83D\uDCA9"
있습니까? 하나 또는 둘? 계산 방법에 따라 다릅니다. 정규식 엔진은 물론 논리 문자를 처리하므로 패턴 ^.$
이 성공하고 패턴 ^..$
이 실패합니다. 이 광기가 여기에 설명되어 있습니다.
String { U+61, "\u0061", "a" } =~ /^.$/ => matched.
String { U+61, "\u0061", "a" } =~ /^..$/ => failed.
String { U+61.61, "\u0061\u0061", "aa" } =~ /^.$/ => failed.
String { U+61.61, "\u0061\u0061", "aa" } =~ /^..$/ => matched.
String { U+DF, "\u00DF", "ß" } =~ /^.$/ => matched.
String { U+DF, "\u00DF", "ß" } =~ /^..$/ => failed.
String { U+DF.DF, "\u00DF\u00DF", "ßß" } =~ /^.$/ => failed.
String { U+DF.DF, "\u00DF\u00DF", "ßß" } =~ /^..$/ => matched.
String { U+3C3, "\u03C3", "σ" } =~ /^.$/ => matched.
String { U+3C3, "\u03C3", "σ" } =~ /^..$/ => failed.
String { U+3C3.3C3, "\u03C3\u03C3", "σσ" } =~ /^.$/ => failed.
String { U+3C3.3C3, "\u03C3\u03C3", "σσ" } =~ /^..$/ => matched.
String { U+1F4A9, "\uD83D\uDCA9", "💩" } =~ /^.$/ => matched.
String { U+1F4A9, "\uD83D\uDCA9", "💩" } =~ /^..$/ => failed.
String { U+1F4A9.1F4A9, "\uD83D\uDCA9\uD83D\uDCA9", "💩💩" } =~ /^.$/ => failed.
String { U+1F4A9.1F4A9, "\uD83D\uDCA9\uD83D\uDCA9", "💩💩" } =~ /^..$/ => matched.
그 관용구는 당신이 완벽하게 합리적으로 글을 쓸 수 \u1F4A9
없고, 물론 그렇게 할 수 없다는 경고를받지 않기 때문입니다. 그것은 단지 잘못된 일을합니다.
Stoooopid.
우리가 그 동안, 전체 \uXXXX
표기법은 선천적으로 뇌사입니다. Java 전 처리기 ( 예, 당신은 저를 들었습니다 )는 Java보다 먼저 그것을 얻습니다. 따라서 Java가 그것을 "\u0022"
보았을 때, 전처리 기가로 바뀌 었 """
으므로 잃어 버릴 것입니다. 아, 잠깐 되지 는 정규식에 있다면! 그래서 당신은 "\\u0022"
잘 사용할 수 있습니다 .
Riiiiiiiight!
Java에서 isatty(0)
전화를 걸 방법이 없다는 것을 알고 있습니까? 당신은 그런 생각을 할 수 없습니다. 그것은 당신에게 좋지 않을 것입니다.
그리고 클래스 클래스 가증 전체가 있습니다.
또는 동일한 소스 파일에서 Java 소스 파일의 인코딩을 지정할 수있는 방법 이 없어서 손실되지 않습니까? 다시 한 번 나는 알고 싶어한다 : 그들이 무엇을 생각 했는지
광기를 멈춰라! 사람들이이 쓰레기를 참는 것을 믿을 수 없습니다. 완전한 농담입니다. 나는 터무니없는 자바 광기의 슬링과 화살을 겪는 것보다 월마트 인사를 원합니다. 그것은 모든 생겼습니다, 그들은뿐만 아니라 문제를 해결할 수 없습니다, 그들은 하지 않습니다 그것을 해결.
이것은 printf()
기능 을 갖는 것이 불법이 된 언어에 자부심을 느낀 같은 포도 같은 사람들에 의해 . 저런, 그게 있는지, 실제 잘 작동하지만 그것을하지 않았다!?
깎아 지른듯한 감각. 암캐를 때리는 것은 너무 친절합니다. 어셈블러로 프로그래밍하고 싶다면 그렇게 할 것입니다. 이것은 구할 수있는 언어가 아닙니다. 황제는 옷이 없습니다.
우리는 그것을 싫어합니다. 우리는 그것을 영원히 싫어합니다 . 이 다이 죽게 다이를 !
^H
)가 포함됩니다.
C 및 C ++의 함수 포인터 선언 구문 :
(int)(*f)(int, int);
이것은 f
pointee가 두 개의을 가지고을 int
반환 할 수 있는 함수 포인터를 선언 합니다 int
.
다음과 같은 구문을 선호합니다.
f: (int, int) => int
당신은 함수 포인터를 선언하고 싶은 말은 g
그의 pointee이 개 걸릴 수 int
들과에서 함수 int
와 int
에 int
, 그리고를 반환을 int
.
C 또는 C ++ 표기법을 사용하면 다음과 같이 선언합니다.
(int)(*g)(int, int, int(int, int));
위에서 제안한 표기법으로 동일한 것을 다음과 같이 선언 할 수 있습니다.
g: (int, int, (int, int) => int) => int
후자는 훨씬 직관적 인 IMO입니다.
따로 : OOC라는 프로그래밍 언어는이 구문과 C 및 C ++의 다양한 구문 문제를 해결합니다. 홈페이지를 확인 하십시오 .
자바의 장황.
즉 :
public static final int
const int
예를 들면 다음과 같습니다 .
a+(b*c)/d*e+f/g^20
사용하여 BigInteger
자바. 이 언어는 왜 연산자 오버로딩을 허용하지 않습니까?
이 구문은 추악 할뿐만 아니라 새로운 개발자가 문자열의 네임 스페이스에 대해 생각해야 할 때 혼란을 야기합니다. PHP는 큰 따옴표로 묶인 문자열에서 백 슬래시를 이스케이프 시퀀스로 보간합니다. 작은 따옴표 \you\should\never\do\that
로 묶은 문자열 대신 큰 따옴표로 묶은 문자열 과 같은 네임 스페이스를 나타내려고하면 줄 바꿈, 탭 및 재해가 발생합니다.
나는 중괄호가 if / while / for 문 다음에 선택 사항이 될 수 있다는 사실을 무시합니다.
특히 내가 같은 코드를 볼 때
if (...)
for(...)
... One line of stuff ...
괄호를 넣고 끝내십시오.
for (...) while (...) if (...) { x(); y(); }
더 잘 작성됩니다 for (...) { while (...) { if (...) { x(); y(); } } }
.
거의 모든 현명한 언어와 달리 VBScript는 논리 연산자 대신 비트 연산자를 사용합니다. 이것이 실제로 무엇을 의미합니까? 음, 같은 에릭 Lippert의 지적 :
If Blah = True Then Print "True!" Else Print "False!"
과
If Blah Then Print "True!" Else Print "False!"
VBScript에서 동일하지 않습니다!
더 나쁜,하지만, 다음과 같은 문장이 때문에 이렇게 VBScript를에는 단락 회로 평가이 수단이 없음을 충돌 프로그램을하면 Blah
됩니다Nothing
If (Not Blah Is Nothing) And (Blah.Frob = 123) Then
...
맞습니다. VBScript는 첫 번째 것이 거짓 인 경우에도 AND 비교의 두 부분을 모두 평가 합니다 ! 그 싱크대에 들어가게 해
If x Then ... If Not x Then ... End If ... End If
x가 2라는 것을 알기 전까지는 실제로 VB / VBScript로 프로그래밍되지 않았습니다.
편집 : 의견의 토론에 이어 나는 더 나은 설명을 위해이 답변을 업데이트하기로 결정했습니다.
함수 포인터가 C에서 보이는 방식이 정말 싫습니다. 일반적으로 모든 변수 선언은 튜플처럼 보입니다. type varname;
반면에 함수 포인터 선언은 함수 이름 앞에 *를 사용하여 함수를 선언하는 것처럼 보입니다. 이것을 포인터 유형의 설명으로 받아 들일 수는 있지만 C에서는 해당 유형의 변수의 유형과 이름을 모두 선언합니다. 유형 선언이 변수 선언과 다르기 때문에 이것은 나에게 일관성이 없습니다. struct myStruct{int X; int Y;}
유형 만 정의하고라는 변수를 정의하지 않습니다 myStruct
. 마찬가지로 유형 선언과 변수 선언이 함수 포인터에서 하나의 원자 명령문 으로 그룹화 될 이유가 없습니다 .type varname;
구조와 .
누군가는 그것이 어떤 나선 규칙과 일치한다고 지적했으며, 그럴 수도 있지만 좋은 구문의 표시는 자기 설명이 필요하고 내부 논리가 분명하다는 것입니다. 어떤 나선 규칙도 분명하지 않습니다.
typedef
있습니다.
인 / 아웃 인수. 나는 논쟁에서 모두를 위해 (내가 좋은 일이다), 논쟁도 괜찮지 만,이 두 가지 상태를 전달 해야하는 논쟁은 나를 화나게한다.
여기서 내가 목표로하는 것은 매개 변수에서 입력을 가져온 다음 해당 입력을 일부 출력으로 덮어 쓰는 함수입니다. 객체를 참조로 전달하여 업데이트해도됩니다. 그러나 대부분 기본 유형의 경우 객체를 가져 와서 사용하고 완전히 변경하면 나에게 맞지 않습니다. 인아웃을 통해 인수 의 의미 를 변경해서는 안됩니다 .
in
대해 말해야 할 언어를 본 적이 없다 in
. 나는 단지 그들에 대해 이야기하고있다. 또한 내 의견 으로는 입 / 출력 논쟁을 변명 할 수 없으며 그것을 명시 적으로 만드는 것이 고통을 완화 시키지는 않습니다. 함수에 도움이되는 값으로 로컬 변수를 초기화 할 이유가 없어야하며, 동일한 변수를 가지면 함수가 거기에 놓기로 결정한 모든 것을 갑자기 포함 할 수 있습니다. 이 두 가지가 분명해야합니다. 항상.
struct
새 값이 값에 의존 하는 위치 업데이트). 같은 분야의 다른 분야 struct
.)
class
함수에 의해 수정 된 참조로 전달 된 객체 (예 : C # 의 객체 인스턴스 )는 괜찮습니다. 상수가 아닌 구조체를 싫어한다는 것 외에도 키워드 struct
와 함께 ref
키워드를 전달 하여 업데이트하는 것도 좋습니다. 내가 정말로 싫어하는 것은 입력이 출력 으로 덮어 쓰여질 때 입니다. 제가 생각할 수있는 가장 좋은 예는 버클리 소켓의 accept
기능입니다. socklen_t*
입력시 struct sockaddr*
전달한 크기를 포함해야하는 인수가 필요합니다 . 출력시, 작성된 바이트 수를 포함합니다. 이건 범죄 야
일반적으로 변수 선언은 형식 type variable_name
입니다. 이러한 선언을 왼쪽에서 오른쪽으로 쉽게 읽을 수 있습니다. 그러나 int foo[size]
처음 foo
에는 int로 선언하는 것처럼 보입니다. 그런 다음 더 자세히 읽고 foo의 "정수 배열"유형을 봅니다. int[size] foo
훨씬 더 잘 읽습니다.
그리고 프로그래머가 비슷한 이유로 포인터를 선언하면 싫어요 int *foo
. 내가 알지 못했던 어떤 이유로, 그것이 작성 되는 일반적인 방법입니다.
int* a, b;
되므로 그렇게 작성 됩니다. 그래서 *하지 않습니다 선언 a
과 b
포인터로; 단지 a
입니다. 따라서 그것을 작성하는 것이 좋습니다 int *a, b;
(또는 두 개의 선언으로 작성하는 것이 좋습니다).
*
유형에 바인딩되지 않습니다.
void(int) *f;
? Nope :void (*f)(int);
int* a, b;
언급 한 문제가 훨씬 더 심각 하다고 생각합니다 .
Java에서 중복 매개 변수화 :
HashMap<String,HashMap<String,String>> foo = new HashMap<String, HashMap<String, String>>();
컴파일러가 생각할 foo
수있는 다른 유형 매개 변수는 무엇입니까 ?
HashMap<String,HashMap<String,String>> foo = Maps.newHashMap();
HashMap<String,HashMap<String,String>> foo = new HashMap<>();
What other type parameterization does the compiler think foo could have?
-어떤 이유로 든 마치 제정신 유형과 매개 변수화 된 유형을 혼합 한 것처럼 원시 유형입니다.
사람들이 이미 =
vs ==
에 대해 불평 했으므로 훨씬 더 나쁜 대안을 지적하겠습니다. PL / I는 모두를 가지고 :=
와 =
, 하지만 뭔가 "분명히"할당이 때, 당신이 사용하여 도망 할 것이다 =
그것을 할 수 있습니다. 사용:=
하면 컴파일러가이를 비교로 해석하는 상황에서 무언가를 강제로 할당 할 수 있습니다.
불행하게도, 컴파일러는 항상 예상했던대로 일을 결정하지는 않았습니다. 하나의 명백한 예를 고려하십시오.
A = B = 0;
이제 대부분의 "일반적인"언어에 익숙한 대부분의 사람들에게이 의미는 매우 분명합니다. A와 B 모두에 0을 할당하십시오. PL / I는 조금 다릅니다. 언어의 (미친) 디자이너에게만 알려진 이유로, 첫 번째 =
는 과제로 해석되지만 두 번째는 과제로 해석됩니다.=
는 비교로 해석됩니다. 따라서 이것은 B를 0과 비교 한 다음 그 비교 결과를 A에 할당합니다 ( "거짓"은 1이고 "참"인 C 스타일 규칙을 따릅니다).
따라서 B가 0이면 A가 1이됩니다. 그렇지 않으면 A가 0이됩니다. 즉, A와 B에 같은 값을 할당하지 않고 실제로 A 가 가질 .
결론 : C / C ++ / PHP 스타일이 처음에는 고통 스러운 것처럼 보이지만 대안은 훨씬 더 나쁩니다 1 .
1 기술적으로는 또 다른 대안이 있습니다. 파스칼 스타일 (Pascal style). =
항상 비교와 할당은 항상 필요합니다 :=
. 그것을 잠시 사용한 후에, 할당이 두 가지를 명확하게하기 위해 여분의 "물건"을 필요로 할 경우, 할당을 깨끗하고 간단하게 유지해야한다는 점보다 할당이 훨씬 일반적이라는 것이 분명합니다 (적어도 나에게). 비교에 대한 추가 "그런 지"가 필요하며 그 반대도 마찬가지입니다.
==
평등과 :=
과제 를 위해 사용할 것을 제안했다 . 이렇게하면 타이핑을 더 많이 할 수 있지만 외로움 =
을 피하면 버그를 피할 수 있습니다.
if($x < 10) do_something();
. 현재로서는 do_something() if($x < 10);
또는로 작성해야합니다 if($x < 10) { do_something(); }
.do_something() if ($x < 10);
그렇게 나쁘지 않습니다.
if(..) ...
모든 표현식을 오른쪽에 표시 할 수 있기 때문에 부팅하는 것보다 훨씬 깨끗하지 않으며 대부분의 경우 부팅 보다 훨씬 깨끗 합니다. 그러나 정말로 말하고 싶은 시간 if($x < 10) do_something();
이 있으며 펄이 나를 허락하지 않는 것은 불행합니다.
if ($x<10) do_something(); and_call_me();
왜 전화를받지 않는지 궁금 할 때까지는 불행 합니다. C와 가족이 이러한 유형의 오류를 방지하기 위해 중괄호를 요구하기를 바랍니다.
else
s 제외 . ( EXPR1 if COND else EXPR2
파이썬이 갖고있는 것처럼 바란다 )
reinterpret_cast<unsigned long>
C ++에서. 이 작업은 외부 API를 처리하고 숫자의 정확성을 보장하는 데 유용합니다. 왜 입력하기가 너무 어려워 보입니까?
reinterpret_cast
C ++에서 a 를 사용하는 것은 매우 강력한 코드 냄새입니다. 99 %의 시간, 당신이 그것을 사용하려고 할 때, 당신은 할 필요가 없습니다-당신은 아마 뭔가 잘못했을 것입니다. 시간의 다른 1 %는 C와 인터페이스하고 reinterpret_cast
있습니다. 그렇지 않으면 불가능한 일을하기 위해 형식 시스템이 작동하지 않습니다. 그것은 일반적으로 나쁜 것입니다.
배열을 반복 할 때 JavaScript 의 for ... in 구문과 PHP 의 foreach 구문입니다. 둘 다 올바른 코드보다 버그를 작성하기가 더 쉽습니다.
C / C ++에서 배열의 포인터 또는 포인터의 포인터 나는 아직도 이것에 대해 혼란스러워합니다.
int[]*
정수 int*[]
배열에 대한 포인터이고 정수에 대한 포인터의 배열입니다. const
s 와도 잘 작동합니다 : int* const
정수에 대한 상수 포인터입니다.const int*
와 int const*
상수 정수에 대한 포인터 (또는 정수 상수로).
int (*p)[10];
임을 선언 p
합니다. 경우 sizeof (int) == 4
다음 p++
진출하게됩니다 p
(40)에 의해
Javascript / Java 등, 비교와 동일합니다. 예 : if (a == 1)
if (a = 1)을 몇 번이나 쓰나요?
인간으로서 나는 그것을 완벽하게 읽습니다. 그러나 대담한 통역사 / 컴파일러는 "이봐, 나는 1을 a에 할당하고 a가 1과 같은지 확인하고, 그렇다고 믿는가?"
나를 벽으로 몰아 넣는다.
if (a == 1) 가독성이 떨어지고 인터프리터 / 컴파일러는 내가 무슨 뜻인지 알아야합니다. 다른 많은 언어 (VB)는 수백 년 동안이 언어를 성공적으로 개발해 왔습니다.
if (a = true)
뜻입니까?
if (a == true)
, 그냥 작성하십시오 if (a)
. 을 의미 a = true
하면 if
명령문이 중복됩니다.
structPointer->member
C / C ++에서. 다른 사람의 코드를 읽는 데 도움이 될 수 있지만 마음에 들지 않습니다. 하나 대신 두 문자 ... 공간 낭비!
.
포인터가 아닌 객체의 멤버에 적용 되는와 구별되어야 합니다. 모호한 구문이 잘못되었습니다.
shared_ptr
, 어디에 ->
포함 된 유형에 액세스하고 .
의 속성에 접근 shared_ptr
자체를? 죄송하지만 여기에 완전히 동의하지 않습니다.
->
의 액세스 회원에게 아무것도 .
대괄호 안에있는 스칼라 멀티 라인 코드
예를 들어 :
class Foo(
val bar: String,
val baz: Int,
val bing: String,
val bong: Boolean
) extends Model {
// body here
}
당신이 실제로 얻는 것은 훌륭합니다. 생성자와 getter 및 setter를 생성합니다. 그러나 그것은 추악하고 코드를 들여 쓰는 방법에 대한 모든 정신적 모델을 깨뜨리고 기본적으로 한쪽에는 Java가 있고 다른쪽에는 Lisp가있는 기괴한 샌드위치에있는 것처럼 느끼게합니다. (오, 잠깐만 ... 스칼라의 요점입니다.)
val bar
부분 또는 중괄호 안의 부분 (다음 부분 extends Model
)을 의미합니까? (해당 코드에는 대괄호가 없습니다)