PHP에서 언어 구조와 "내장"함수의 차이점은 무엇입니까?


92

나는 알고있다 include, isset, require, print, echo, 일부 다른 기능을하지만, 언어 구조되지 않습니다.

이러한 언어 구조 중 일부는 괄호가 필요하고 다른 일부는 괄호가 필요하지 않습니다.

require 'file.php';
isset($x);

일부는 반환 값이 있고 다른 일부는 그렇지 않습니다.

print 'foo'; //1
echo  'foo'; //no return value

그렇다면 언어 구조와 내장 함수 의 내부 차이점 은 무엇 입니까?

답변:


131

(이는 내가 의도 한 것보다 더 깁니다. 참아주세요.)

대부분의 언어는 "구문"이라고하는 것으로 구성됩니다. 언어는 잘 정의 된 여러 키워드로 구성되며 해당 언어로 구성 할 수있는 전체 범위의 표현식은 해당 구문에서 구성됩니다.

예를 들어, 한 자리 정수만 입력하고 연산 순서를 완전히 무시하는 간단한 4 기능 산술 "언어"가 있다고 가정 해 보겠습니다 (단순한 언어라고 말씀 드렸습니다). 해당 언어는 다음 구문으로 정의 할 수 있습니다.

// The | means "or" and the := represents definition
$expression := $number | $expression $operator $expression
$number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
$operator := + | - | * | /

이 세 가지 규칙에서 원하는 수의 단일 숫자 입력 산술 표현식을 작성할 수 있습니다. 그런 다음이 구문 파서를 작성할 수 유효한 그 구성 유형에 입력 (고장 $expression, $number또는 $operator결과에)와 거래. 예를 들어, 표현식 3 + 4 * 5은 다음과 같이 분류 할 수 있습니다.

// Parentheses used for ease of explanation; they have no true syntactical meaning
$expression = 3 + 4 * 5
            = $expression $operator (4 * 5) // Expand into $exp $op $exp
            = $number $operator $expression // Rewrite: $exp -> $num
            = $number $operator $expression $operator $expression // Expand again
            = $number $operator $number $operator $number // Rewrite again

이제 원래 표현식에 대해 정의 된 언어로 완전히 구문 분석 된 구문이 있습니다. 이 정보가 있으면 모든 조합의 결과를 찾기 위해 구문 분석기를 작성하고 $number $operator $number하나만 $number남았을 때 결과를 뱉어 낼 수 있습니다 .

$expression원래 표현식의 최종 구문 분석 버전에는 구문이 남아 있지 않습니다 . 그것은 $expression항상 우리 언어로 다른 것들의 조합으로 축소 될 수 있기 때문 입니다.

PHP는 거의 동일합니다. 언어 구조는 우리의 $number또는 $operator. 그것들 은 다른 언어 구조로 축소 될 수 없습니다 . 대신 그들은 언어가 구축되는 기본 단위입니다. 함수와 언어 구조의 주요 차이점은 다음과 같습니다. 파서는 언어 구조를 직접 처리합니다. 기능을 언어 구조로 단순화합니다.

언어 구조가 괄호를 필요로 할 수도 있고 필요하지 않을 수도있는 이유와 일부는 반환 값을 갖는 이유와 나머지는 PHP 파서 구현의 특정 기술 세부 사항에 전적으로 의존하지 않습니다. 나는 파서가 어떻게 작동하는지에 대해 잘 모르기 때문에 이러한 질문을 구체적으로 다룰 수는 없지만 다음으로 시작하는 언어를 잠시 상상해보십시오.

$expression := ($expression) | ...

효과적으로,이 언어는 찾은 모든 표현을 자유롭게 사용하고 둘러싼 괄호를 제거합니다. PHP (그리고 여기에서는 순수한 추측을 사용하고 있습니다)는 언어 구조에 대해 비슷한 것을 사용할 print("Hello")수 있습니다 . print "Hello"파싱되기 전으로 축소 되거나 그 반대 일 수 있습니다 (언어 정의는 괄호를 추가하고 제거 할 수 있음).

이것이 echo또는 같은 언어 구조를 재정의 할 수없는 이유의 근원입니다 print. 이들은 파서에 효과적으로 하드 코딩되는 반면, 함수는 언어 구조 집합에 매핑되고 파서는 컴파일 또는 런타임에 해당 매핑을 다음과 같이 변경할 수 있습니다. 자신의 언어 구성 또는 표현 세트를 대체하십시오.

결국 구문과 표현식의 내부 차이점은 다음과 같습니다. 언어 구문은 파서가 이해하고 처리합니다. 내장 함수는 언어에 의해 제공되지만 구문 분석 전에 언어 구성 세트에 매핑되고 단순화됩니다.

더 많은 정보:

  • Backus-Naur 형식 , 형식 언어를 정의하는 데 사용되는 구문 (yacc는이 형식을 사용함)

편집 : 다른 답변 중 일부를 읽으면 사람들이 좋은 점을 만듭니다. 그중 :

  • 내장 된 언어는 함수보다 호출이 더 빠릅니다. 이것은 PHP 인터프리터가 파싱하기 전에 해당 함수를 해당 언어 내장 등가물에 매핑 할 필요가 없기 때문에 미미하지만 사실입니다. 그러나 현대 컴퓨터에서는 그 차이가 상당히 미미합니다.
  • 내장 된 언어는 오류 검사를 우회합니다. 이것은 각 내장의 PHP 내부 구현에 따라 사실 일 수도 있고 그렇지 않을 수도 있습니다. 함수가 더 많은 고급 오류 검사 및 내장 기능이 제공하지 않는 기타 기능을 갖는 경우가 많을 것입니다.
  • 언어 구조는 함수 콜백으로 사용할 수 없습니다. 구조가 함수아니기 때문에 이것은 사실 입니다. 그들은 별개의 개체입니다. 내장을 코딩 할 때 인수를받는 함수를 코딩하는 것이 아닙니다. 내장 구문은 파서가 직접 처리하며 함수가 아닌 내장으로 인식됩니다. (일급 함수를 사용하는 언어를 고려하면 이해하기 더 쉬울 수 있습니다. 효과적으로 함수를 객체로 전달할 수 있습니다. 내장 기능으로는 수행 할 수 없습니다.)

2
PHP뿐만 아니라 많은 언어에 적용 할 수있을만큼 개방적인 훌륭한 답변입니다. 감사합니다!
Levi Botelho

15

언어 구조는 언어 자체에서 제공합니다 (예 : "if", "while", ...). 따라서 그들의 이름.

그 결과 미리 정의되거나 사용자 정의 된 함수보다 호출이 더 빠르다는 것입니다 (또는 여러 번 듣거나 읽었습니다).

어떻게되었는지는 모르겠지만 그들이 할 수있는 한 가지는 (언어에 직접 통합되기 때문에) 일종의 오류 처리 메커니즘을 "우회"하는 것입니다. 예를 들어, isset ()은 통지, 경고 또는 오류를 일으키지 않고 존재하지 않는 변수와 함께 사용할 수 있습니다.

function test($param) {}
if (test($a)) {
    // Notice: Undefined variable: a
}

if (isset($b)) {
    // No notice
}

* 모든 언어의 구조에 해당하는 것은 아닙니다.

함수와 언어 구조의 또 다른 차이점은 일부는 키워드처럼 괄호없이 호출 할 수 있다는 것입니다.

예 :

echo 'test'; // language construct => OK

function my_function($param) {}
my_function 'test'; // function => Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING

여기에서도 모든 언어 구조에 해당하는 것은 아닙니다.

언어 자체의 일부이기 때문에 언어 구조를 "비활성화"할 수있는 방법이 전혀 없다고 생각합니다. 반면에, 많은 "내장"PHP 함수는 확장에 의해 제공되므로 항상 활성화되어 있기 때문에 실제로 내장되어 있지 않습니다 (모두는 아님).

또 다른 차이점은 언어 구조가 "함수 포인터"(예 : 콜백)로 사용될 수 없다는 것입니다.

$a = array(10, 20);

function test($param) {echo $param . '<br />';}
array_map('test', $a);  // OK (function)

array_map('echo', $a);  // Warning: array_map() expects parameter 1 to be a valid callback, function 'echo' not found or invalid function name

지금은 다른 생각이 떠오르지 않습니다 ... 그리고 PHP의 내부에 대해 잘 모릅니다 ... 그래서 지금 당장 ^^

여기에서 많은 답변을 얻지 못했다면 PHP 코어 개발자가 많은 메일 링리스트 내부 ( http://www.php.net/mailing-lists.php 참조 )에 문의 할 수 있습니다 . 아마 그거 아실 거예요 ^^

(그리고 저는 다른 답변에 정말 관심이 있습니다, btw ^^)

참고로 : PHP의 키워드 및 언어 구성 목록


참고로 변수를 취함으로써 통지를 생성하지 않고 설정되지 않은 변수를 받아들이는 함수를 가질 수 있습니다. 이것은 isset ()과 같은 언어 구조로 제한되지 않습니다.
Tom Haigh 2009-08-01

오, 그것에 대해 생각하지 않았습니다 :-( 감사합니다!
Pascal MARTIN

4

코드를 살펴본 후 php가 yacc 파일의 일부 명령문을 구문 분석하는 것을 발견했습니다. 그래서 그들은 특별한 경우입니다.

(Zend / zend_language_parser.y 참조)

그 외에는 다른 차이점이 있다고 생각하지 않습니다.


1

내장 함수를 재정의 할 수 있습니다 . 키워드는 영원합니다.


그것은 내장 함수가 아닙니다. APD (Advanced PHP Debugger) 확장에 정의되어 있습니다.
Ionuț G. Stan

함수를 재정의하는 것에 대해 런킷 확장에서 전리품을 가질 수 있습니다 (핵심도 아니며 확장이므로 OP에 대한 답변이 아니라이 답변에만 해당됩니다); 정말 강력하고 APD보다 더 최근의 (그리고 나는 그것이 pecl.php.net에 표시 아니더라도, 나는 어떤 사람들은 여전히 작업 한 것을 얼마 전에 들었 생각)
파스칼 MARTIN
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.