2011-08-10 59 views
5

Tại sao phương pháp này kiểm tra nếu một tồn tại liên tục trước khi xác định nó:Tại sao 'được xác định() || xác định 'cú pháp trong việc xác định một hằng số

defined('CONSTANT') || define('CONSTANT', somedefinition); 

sử dụng thay cho:

if !(defined('CONSTANT')) { 
    define('CONSTANT', somedefinition); 
} 

Có sự khác biệt trong cách sử dụng'() hoặc 'thay vì' || ' trong phương pháp đầu tiên, tôi đã thấy cả trong sách.

Trả lời

8

Do || (trong C, Java, C#, php) là "ngắn mạch" (nếu toán hạng đầu tiên là true, thứ hạng không được đánh giá vì biểu thức đã được đánh giá là đúng, bất kể thứ hai là bao nhiêu.

Vì vậy, đây là hành động "ngắn gọn" kiểu C cổ điển đang hoạt động. Sử dụng càng ít dòng mã càng tốt, mặc dù nó thực hiện chính xác giống như một dòng mã nào đó dài hơn,

Vì vậy, nó đọc: if defined (...), không làm các định nghĩa() bit ... nếu không được xác định(), hãy cố gắng để đánh giá xác định() bit và trong quá trình, nó sẽ xác định các hằng số:

+0

Vì vậy cú pháp 'được định nghĩa ('CONSTANT') hoặc xác định ('CONSTANT', định nghĩa somedefinition);' không hợp lệ vì 'hoặc'operator không được" đoản mạch "? –

+0

@David Casillas: Đúng vậy. Nhìn vào câu trả lời của tôi để giải thích sự khác biệt giữa '||' và 'hoặc ' – Mchl

+0

@Mchl, tôi đã nghĩ rằng' hoặc' không phải là "ngắn mạch", nhưng nó chỉ là '||' với ưu tiên khác nhau. –

3
defined('CONSTANT') || define('CONSTANT', somedefinition); 

Thực sự là một mẹo nhỏ. Bạn thấy đấy, || toán tử chỉ thực hiện phần thứ hai của biểu thức khi phần đầu tiên là false :) Đó là một cách nhanh chóng, ngắn để viết cùng một mã hoạt động.

+3

Các từ khóa ở đây là * đánh giá ngắn mạch *. – deceze

+0

Một số ngôn ngữ có xu hướng sử dụng nó một cách ưu việt (perl), vì vậy có lẽ những ngôn ngữ thực hiện nó trong php làm điều đó phần lớn là do thói quen. Bất kỳ ý tưởng nào nếu có bất kỳ sự khác biệt về hiệu suất nào? – Joubarc

4

một phần của câu hỏi của bạn, vì vậy tôi sẽ lấy câu hỏi sau:

Theo như or|| là có liên quan không có sự khác biệt trong trường hợp cụ thể này. Tuy nhiên, or có số điện thoại operator precedence thấp hơn = (toán tử gán), trong khi || cao hơn. Điều này là quan trọng, nếu bạn muốn sử dụng ngắn mạch để làm nhiệm vụ.

xem xét:

$a = 2 or $b = 2; 
var_dump($a); // int(2) 


$a = 3 || $b = 3; 
var_dump($a); // bool(true) 

Trong ví dụ thứ hai, || đã đánh giá trước =. Sử dụng dấu ngoặc đơn nó sẽ trông như thế này

$a = (3 || $b = 3); 

trong khi người đầu tiên một

($a = 2) or ($b = 2); 
1

Vì vậy, giả thiết của tôi là ngắn mạch nhanh hơn, kể từ khi tuyên bố nếu được lấy giá trị boolean từ xác định và lật nó sử dụng một không điều hành, nhưng chỉ để được triệt để, đây là thử nghiệm benchmark của tôi:


PHP 5.6:

0.23026204109192 - Test1a: Ngắn mạch: Định nghĩa động trên vòng đầu tiên.
0.22264909744263 - Test1b: Nếu tuyên bố: Định nghĩa động trên vòng lặp đầu tiên.
0.22433304786682 - Test2a: Ngắn mạch: Định nghĩa tĩnh trước khi chạy thử nghiệm.
0.22339177131653 - Test2b: Nếu tuyên bố: Định nghĩa tĩnh trước khi chạy thử nghiệm.
0.27459692955017 - Test3a: Ngắn mạch: Không bao giờ xác định biến.
0.28696393966675 - Test3b: Nếu tuyên bố: Không bao giờ xác định biến.

Kết luận
Quá gần để nói, mặc dù chúng ta có thể thấy một sự cải thiện tốc độ đáng kể cho ngắn mạch nếu biến không bao giờ được xác định.


PHP 7:

0,031289100646973 - Test1a: ngắn mạch: động xác định trên vòng đầu tiên.
0.041652917861938 - Test1b: Nếu tuyên bố: Định nghĩa động trên vòng lặp đầu tiên.
0.023349046707153 - Test2a: Ngắn mạch: Định nghĩa tĩnh trước khi chạy thử nghiệm.
0.052791118621826 - Test2b: Nếu tuyên bố: Định nghĩa tĩnh trước khi chạy thử nghiệm.
0.064755916595459 - Test3a: Ngắn mạch: Không bao giờ xác định biến.
0.056003093719482 - Test3b: Nếu tuyên bố: Không bao giờ xác định biến.

Kết luận PHP 7 tối ưu hóa rõ ràng cho ngắn mạch trong trường hợp hằng số/biến được xác định, mặc dù chúng ta thấy ngược lại nếu hằng số không bao giờ được xác định. Điều này ngụ ý rằng việc kiểm tra các hằng số thực sự tồn tại đã được cải thiện đáng kể, làm cho nó dễ dàng hơn để xem xử lý bổ sung được yêu cầu bởi toán tử không được thêm vào trong câu lệnh if.

Nhìn chung Kết luận

Sự khác biệt là không đáng kể (trừ khi bạn đang đi vào hàng triệu vô số cùng một dòng code) để sử dụng bất cứ điều gì làm cho ý nghĩa nhất cho bạn và nhóm của bạn.

Ngoài ra, người đàn ông, PHP7 hút thuốc 6,5 PHP về hiệu suất của các thử nghiệm này!


Code:

$c1a=0; 
$title1a = 'Test1a: Short circuit: Dynamic define on first loop.'; 
$c1b=0; 
$title1b = 'Test1b: If Statement: Dynamic define on first loop.'; 

$c2a=0; 
$title2a = 'Test2a: Short circuit: Static define before test is run.'; 
$c2b=0; 
$title2b = 'Test2b: If Statement: Static define before test is run.'; 

$c3a=0; 
$title3a = 'Test3a: Short circuit: Never define variable.'; 
$c3b=0; 
$title3b = 'Test3b: If Statement: Never define variable.'; 

$start1a = microtime(true); 
while ($c1a < 1000000) { 
    ++$c1a; 
    defined('TEST_CONST_1A') || define('TEST_CONST_1A', 'test'); 
} 
$stop1a = microtime(true); 

$start1b = microtime(true); 
while ($c1b < 1000000) { 
    ++$c1b; 
    if (!defined('TEST_CONST_1B')) { 
    define('TEST_CONST_1B', 'test'); 
    } 
} 
$stop1b = microtime(true); 

define('TEST_CONST_2A', 'test'); 
$start2a = microtime(true); 
while ($c2a < 1000000) { 
    ++$c2a; 
    defined('TEST_CONST_2A') || define('TEST_CONST_2A', 'test'); 
} 
$stop2a = microtime(true); 

define('TEST_CONST_2B', 'test'); 
$start2b = microtime(true); 
while ($c2b < 1000000) { 
    ++$c2b; 
    if (!defined('TEST_CONST_2B')) { 
    define('TEST_CONST_2B', 'test'); 
    } 
} 
$stop2b = microtime(true); 

$start3a = microtime(true); 
while ($c3a < 1000000) { 
    ++$c3a; 
    defined('TEST_CONST_3A') || $c3a; 
} 
$stop3a = microtime(true); 

$start3b = microtime(true); 
while ($c3b < 1000000) { 
    ++$c3b; 
    if (!defined('TEST_CONST_3B')) { 
    $c3b; 
    } 
} 
$stop3b = microtime(true); 

print ($stop1a - $start1a) . ' - ' . $title1a . "\n"; 
print ($stop1b - $start1b) . ' - ' . $title1b . "\n"; 
print ($stop2a - $start2a) . ' - ' . $title2a . "\n"; 
print ($stop2b - $start2b) . ' - ' . $title2b . "\n"; 
print ($stop3a - $start3a) . ' - ' . $title3a . "\n"; 
print ($stop3b - $start3b) . ' - ' . $title3b . "\n"; 
Các vấn đề liên quan