Tiếng AnhTiếng PhápTiếng Tây Ban Nha

Biểu tượng yêu thích OnWorks

PDL :: PPp - Trực tuyến trên đám mây

Chạy PDL :: PPp trong nhà cung cấp dịch vụ lưu trữ miễn phí OnWorks trên Ubuntu Online, Fedora Online, trình giả lập trực tuyến Windows hoặc trình mô phỏng trực tuyến MAC OS

Đây là lệnh PDL :: PPp có thể chạy trong nhà cung cấp dịch vụ lưu trữ miễn phí OnWorks bằng cách sử dụng một trong nhiều máy trạm trực tuyến miễn phí của chúng tôi như Ubuntu Online, Fedora Online, trình giả lập trực tuyến Windows hoặc trình mô phỏng trực tuyến MAC OS

CHƯƠNG TRÌNH:

TÊN


PDL :: PP - Tạo quy trình PDL từ các mô tả ngắn gọn

SYNOPSIS


ví dụ

pp_def (
'sumover',
Phân tích cú pháp => 'a (n); [o] b (); ',
Mã => q {
tmp kép = 0;
loop (n)% {
tmp + = $ a ();
%}
$ b () = tmp;
},
);

pp_done ();

CHỨC NĂNG


Đây là danh sách tham khảo nhanh về các hàm được cung cấp bởi PDL :: PP.

pp_add_boot
Thêm mã vào phần BOOT của tệp XS được tạo

pp_add_exported
Thêm các chức năng vào danh sách các chức năng đã xuất

pp_add_isa
Thêm các mục vào danh sách @ISA

pp_addbắt đầu
Đặt mã sẽ được thêm vào đầu tệp .pm tạo

pp_addhdr
Thêm mã và đưa vào phần C của tệp XS được tạo

pp_addpm
Thêm mã vào tệp .pm đã tạo

pp_addxs
Thêm mã XS bổ sung vào tệp XS đã tạo

pp_beginwrap
Thêm gói BEGIN-block vào mã cho tệp .pm được tạo

pp_may mắn
Đặt gói mà mã XS được thêm vào (mặc định là PDL)

pp_boundscheck
Trạng thái kiểm soát của hoạt động kiểm tra giới hạn PDL

pp_core_importList
Chỉ định những gì được nhập từ PDL :: Core

pp_def
Xác định một hàm PDL mới

pp_deprecate_module
Thêm cảnh báo thời gian chạy và POD về một mô-đun không được dùng nữa

pp_done
Đánh dấu phần cuối của các định nghĩa PDL :: PP trong tệp

pp_export_nothing
Xóa danh sách xuất cho mô-đun đã tạo của bạn

pp_line_numbers
Thêm thông tin số dòng để đơn giản hóa việc gỡ lỗi mã PDL :: PP

pp_setversion
Đặt phiên bản cho các tệp .pm và .xs

TỔNG QUAN


Tại sao chúng ta cần PP? Một số lý do: trước tiên, chúng tôi muốn có thể tạo chương trình con
mã cho từng kiểu dữ liệu PDL (PDL_Byte, PDL_Short, v.v.). TỰ ĐỘNG. Thứ hai,
khi đề cập đến các lát của mảng PDL trong Perl (ví dụ: "$ a-> lát ('0: 10: 2,:')" hoặc khác
những thứ chẳng hạn như chuyển vị) thật tuyệt khi có thể làm điều này một cách minh bạch và có thể
để thực hiện điều này 'tại chỗ' - tức là không phải tạo bản sao bộ nhớ của phần. Tay cầm PP
tất cả các yếu tố cần thiết và bù đắp số học cho bạn. Cũng có những quan niệm về
phân luồng (gọi lặp lại cùng một quy trình cho nhiều lát, xem PDL :: Lập chỉ mục)
và luồng dữ liệu (xem PDL :: Dataflow) mà việc sử dụng PP cho phép.

Trong phần lớn những gì tiếp theo, chúng tôi sẽ cho rằng người đọc đã quen thuộc với các khái niệm về
các thao tác lập chỉ mục và phân luồng ngầm và rõ ràng trong PDL. Nếu bạn chưa
đã nghe nói về những khái niệm này hoặc không cảm thấy thoải mái với chúng, đã đến lúc kiểm tra
PDL :: Lập chỉ mục.

Như bạn có thể đánh giá cao từ tên của nó PDL :: PP là một Bộ xử lý trước, tức là nó mở rộng mã thông qua
thay thế để tạo mã C thực. Về mặt kỹ thuật, đầu ra là mã XS (xem perlx) nhưng
đó là rất gần với C.

Vậy bạn sử dụng PP như thế nào? Đối với hầu hết các phần, bạn chỉ cần viết mã C thông thường ngoại trừ
cấu trúc PP đặc biệt có dạng:

$ cái gì đó (cái gì đó khác)

hoặc:

PP chức năng% {

%}

Cấu trúc PP quan trọng nhất là dạng "$ array ()". Hãy xem xét PP rất đơn giản
hàm tính tổng các phần tử của một vectơ 1D (trên thực tế, điều này rất giống với
mã được sử dụng bởi 'sumover'):

pp_def ('sumit',
Phân tích cú pháp => 'a (n); [o] b (); ',
Mã => q {
đôi tmp;
tmp = 0;
loop (n)% {
tmp + = $ a ();
%}
$ b () = tmp;
}
);

Chuyện gì đang xảy ra vậy? Dòng "Phân tích cú pháp =>" rất quan trọng đối với PP - nó chỉ định tất cả
đối số và chiều của chúng. Chúng tôi gọi đây là chữ ký của hàm PP (so sánh
cũng như các giải thích trong PDL :: Lập chỉ mục). Trong trường hợp này, quy trình có chức năng 1-D như
đầu vào và trả về giá trị vô hướng 0-D dưới dạng đầu ra. Cấu trúc PP "$ a ()" được sử dụng để truy cập
các phần tử của mảng a (n) cho bạn - PP điền vào tất cả các mã C cần thiết.

Bạn sẽ nhận thấy rằng chúng tôi đang sử dụng toán tử dấu ngoặc kép "q {}". Đây không phải là một
Tai nạn. Bạn thường muốn sử dụng các dấu ngoặc kép để biểu thị các phần Mã PP của mình. PDL :: PP
sử dụng "$ var ()" để phân tích cú pháp và nếu bạn không sử dụng các dấu ngoặc kép, Perl sẽ cố gắng
nội suy "$ var ()". Ngoài ra, việc sử dụng toán tử dấu ngoặc kép "q" với dấu ngoặc nhọn làm cho nó
giống như bạn đang tạo một khối mã, đó là Ý nghĩa của bạn. (Perl đủ thông minh để
tìm dấu ngoặc nhọn lồng nhau và không đóng dấu ngoặc kép cho đến khi tìm thấy dấu ngoặc nhọn phù hợp
dấu ngoặc nhọn, vì vậy sẽ an toàn khi có các khối lồng nhau.) Trong các trường hợp khác, chẳng hạn như khi bạn
ghép khối Mã lại với nhau bằng cách sử dụng nối chuỗi, nó thường dễ sử dụng nhất
dấu ngoặc kép thực như

Code => 'something'. $ Interpolatable.'somethingelse; '

Trong trường hợp đơn giản ở đây, nơi tất cả các phần tử được truy cập, cấu trúc PP "loop (n)% {...
%} "được sử dụng để lặp qua tất cả các phần tử trong thứ nguyên" n ". Lưu ý đặc điểm này của PP: ALL
KÍCH THƯỚC ĐƯỢC CHỈ ĐỊNH THEO TÊN.

Điều này được làm rõ ràng hơn nếu chúng ta tránh PP vòng() xây dựng và viết vòng lặp một cách rõ ràng
sử dụng C thông thường:

pp_def ('sumit',
Phân tích cú pháp => 'a (n); [o] b (); ',
Mã => q {
int i, n_size;
đôi tmp;
n_size = $ SIZE (n);
tmp = 0;
cho (i = 0; i
tmp + = $ a (n => i);
}
$ b () = tmp;
},
);

tương tự như trước đây, nhưng dài dòng hơn. Bạn có thể xem để lấy phần tử "i" trong số
a () chúng ta nói "$ a (n => i)" - chúng ta đang chỉ định thứ nguyên bằng tên "n". Trong 2D, chúng ta có thể nói:

Phân tích cú pháp => 'a (m, n);',
...
tmp + = $ a (m => i, n => j);
...

Cú pháp "m => i" vay mượn từ hàm băm Perl, trên thực tế được sử dụng trong việc triển khai
của PP. Người ta cũng có thể nói "$ a (n => j, m => i)" vì thứ tự không quan trọng.

Bạn cũng có thể thấy trong ví dụ trên, việc sử dụng một cấu trúc PP khác - $ SIZE (n) để lấy
chiều dài của thứ nguyên "n".

Tuy nhiên, cần lưu ý rằng bạn không nên viết một vòng lặp C rõ ràng khi bạn có thể
đã sử dụng cấu trúc "vòng lặp" PP vì PDL :: PP sẽ tự động kiểm tra giới hạn vòng lặp đối với
bạn, việc sử dụng "vòng lặp" làm cho mã ngắn gọn hơn, v.v. Nhưng chắc chắn có những tình huống
nơi bạn cần kiểm soát rõ ràng vòng lặp và bây giờ bạn biết cách làm điều đó;).

Để xem lại 'Why PP?' - mã trên cho sumit () sẽ được tạo cho mỗi kiểu dữ liệu. Nó
sẽ hoạt động trên các lát của mảng 'tại chỗ'. Nó sẽ tự động phân luồng - ví dụ: nếu một 2D
mảng được cung cấp, nó sẽ được gọi nhiều lần cho mỗi hàng 1D (kiểm tra lại PDL :: Lập chỉ mục cho
các chi tiết của ren). Và sau đó b () sẽ là một mảng 1D các tổng của mỗi hàng. Chúng ta có thể
thay vào đó gọi nó với $ a-> xchg (0,1) để tính tổng các cột. Và theo dõi luồng dữ liệu, v.v. sẽ
có sẵn.

Bạn có thể thấy PP giúp lập trình viên không phải viết nhiều mã C lặp đi lặp lại không cần thiết -
theo ý kiến ​​của chúng tôi, đây là một trong những tính năng tốt nhất của PDL giúp viết các chương trình con C mới
cho PDL một bài tập ngắn gọn đáng kinh ngạc. Lý do thứ hai là khả năng làm cho PP mở rộng
định nghĩa mã ngắn gọn của bạn thành mã C khác nhau dựa trên nhu cầu của máy tính
kiến trúc được đề cập. Hãy tưởng tượng ví dụ bạn may mắn có một siêu máy tính tại
ban tay của bạn; trong trường hợp đó, bạn muốn PDL :: PP chắc chắn tạo ra mã tận dụng
của các tính năng điện toán song song / tạo vecto của máy tính của bạn (đây là một dự án dành cho
Tương lai). Trong mọi trường hợp, điểm mấu chốt là mã không thay đổi của bạn vẫn phải mở rộng thành
làm việc mã XS ngay cả khi nội bộ của PDL thay đổi.

Ngoài ra, bởi vì bạn đang tạo mã trong một tập lệnh Perl thực tế, có rất nhiều điều thú vị
những điều mà bạn có thể làm. Giả sử rằng bạn cần viết cả sumit (như trên) và multit.
Với một chút sáng tạo, chúng ta có thể làm

for ({Name => 'sumit', Init => '0', Op => '+ ='},
{Name => 'multit', Init => '1', Op => '* ='}) {
pp_def ($ _-> {Tên},
Phân tích cú pháp => 'a (n); [o] b (); ',
Mã => '
đôi tmp;
tmp = '. $ _-> {Init}.';
loop (n)% {
tmp '. $ _-> {Op}.' $ a ();
%}
$ b () = tmp;
');
}

xác định cả hai chức năng một cách dễ dàng. Bây giờ, nếu sau này bạn cần thay đổi chữ ký hoặc
kích thước hoặc bất cứ điều gì, bạn chỉ cần thay đổi một vị trí trong mã của bạn. Ừ chắc chắn,
trình soạn thảo của bạn có 'cắt và dán' và 'tìm kiếm và thay thế' nhưng nó vẫn ít hơn
khó chịu và chắc chắn là khó khăn hơn khi chỉ quên một chỗ và có những lỗi lạ
leo vào. Ngoài ra, thêm 'orit' (theo chiều dọc hoặc) vào sau là một lớp lót.

Và hãy nhớ rằng bạn thực sự có đầy đủ khả năng của Perl bên mình - bạn có thể rất dễ dàng đọc
bất kỳ tệp đầu vào nào và thực hiện các quy trình từ thông tin trong tệp đó. Đối với những trường hợp đơn giản như
ở trên, tác giả (Tjl) hiện ủng hộ cú pháp băm như trên - nó không quá
nhiều ký tự hơn cú pháp mảng tương ứng nhưng dễ hiểu hơn nhiều và
thay đổi.

Ở đây chúng ta cũng nên đề cập đến khả năng đưa con trỏ đến đầu dữ liệu trong
bộ nhớ - điều kiện tiên quyết để giao tiếp PDL với một số thư viện. Điều này được xử lý với
Chỉ thị "$ P (var)", xem bên dưới.

Khi bắt đầu công việc trên một hàm pp_def'ined mới, nếu bạn mắc lỗi, bạn sẽ thường
tìm một đống lỗi trình biên dịch chỉ ra số dòng trong tệp XS được tạo. nếu bạn
biết cách đọc các tệp XS (hoặc nếu bạn muốn tìm hiểu một cách khó khăn), bạn có thể mở
đã tạo tệp XS và tìm kiếm số dòng có lỗi. Tuy nhiên, một gần đây
bổ sung cho PDL :: PP giúp báo cáo số dòng chính xác của các lỗi của bạn:
"pp_line_numbers". Làm việc với ví dụ hội nghị ban đầu, nếu bạn viết sai chính tả
tmp trong mã của bạn, bạn có thể thay đổi mã (sai sót) thành một cái gì đó như thế này và
trình biên dịch sẽ cung cấp cho bạn nhiều thông tin hữu ích hơn:

pp_def ('sumit',
Phân tích cú pháp => 'a (n); [o] b (); ',
Mã => pp_line_numbers (__ LINE__, q {
đôi tmp;
tmp = 0;
loop (n)% {
tmp + = $ a ();
%}
$ b () = rmp;
})
);

Đối với tình huống trên, trình biên dịch của tôi cho tôi biết:

...
test.pd: 15: error: 'rmp' không được khai báo (lần đầu tiên sử dụng trong hàm này)
...

Trong tập lệnh ví dụ của tôi (được gọi là test.pd), dòng 15 chính xác là dòng mà tôi đã tạo
typo: "rmp" thay vì "tmp".

Vì vậy, sau phần tổng quan nhanh này về hương vị chung của việc lập trình các quy trình PDL bằng cách sử dụng
PDL :: PP hãy tóm tắt những trường hợp nào bạn thực sự nên sử dụng cái này
bộ tiền xử lý / trình biên dịch trước. Bạn nên sử dụng PDL :: PP nếu bạn muốn

· Giao diện PDL với một số thư viện bên ngoài

· Viết một số thuật toán sẽ chậm nếu được mã hóa bằng Perl (điều này không thường xuyên như bạn
nghĩ; trước tiên hãy xem luồng và luồng dữ liệu).

· Là một nhà phát triển PDL (và thậm chí sau đó nó không bắt buộc)

CẢNH BÁO


Do kiến ​​trúc của nó, một mặt PDL :: PP có thể linh hoạt và dễ sử dụng,
nhưng đồng thời cực kỳ phức tạp. Hiện tại, một phần của vấn đề là lỗi đó
tin nhắn không có nhiều thông tin và nếu có vấn đề gì xảy ra, bạn nên biết những gì bạn
đang làm và có thể xâm nhập theo cách của bạn thông qua nội bộ (hoặc có thể tìm ra bằng cách
thử và sửa lỗi những gì sai với args của bạn thành "pp_def"). Mặc dù công việc đang được thực hiện để
đưa ra các cảnh báo tốt hơn, đừng ngại gửi câu hỏi của bạn đến danh sách gửi thư nếu
bạn gặp rắc rối.

MÔ TẢ


Bây giờ bạn đã có một số ý tưởng về cách sử dụng "pp_def" để xác định các hàm PDL mới, đã đến lúc
giải thích cú pháp chung của "pp_def". "pp_def" nhận làm đối số đầu tiên là tên của
chức năng bạn đang xác định và sau đó là một danh sách băm có thể chứa các khóa khác nhau.

Dựa trên các khóa này, PP tạo mã XS và tệp .pm. Hàm "pp_done" (xem
ví dụ trong SYNOPSIS) được sử dụng để nói với PDL :: PP rằng không còn định nghĩa nào nữa trong
tệp này và đã đến lúc tạo .xs và
.pm tệp.

Do đó, có thể có một số pp_def () các cuộc gọi bên trong một tệp (theo các tệp quy ước
với mã PP có phần mở rộng .pd hoặc .pp) nhưng thường chỉ có một pp_done ().

Có hai kiểu sử dụng khác nhau chính của pp_def (), 'hoạt động dữ liệu' và 'lát cắt
hoạt động 'nguyên mẫu.

'Thao tác dữ liệu' được sử dụng để lấy một số dữ liệu, xử lý dữ liệu đó và xuất ra một số dữ liệu khác; điều này
bao gồm ví dụ: phép toán '+', nghịch đảo ma trận, sumover, v.v. và tất cả các ví dụ
chúng tôi đã nói về trong tài liệu này cho đến nay. Chủ đề ẩn và rõ ràng và
việc tạo ra kết quả được thực hiện tự động trong các hoạt động đó. Bạn có thể
thực hiện luồng dữ liệu với "sumit", "sumover", v.v. (đừng mất tinh thần nếu bạn không hiểu
khái niệm về luồng dữ liệu trong PDL rất tốt; nó vẫn còn rất nhiều thử nghiệm).

'Thao tác cắt' là một kiểu hoạt động khác: trong thao tác lát, bạn không
thay đổi bất kỳ dữ liệu nào, bạn đang xác định sự tương ứng giữa các phần tử khác nhau của hai
piddles (ví dụ bao gồm các định nghĩa về thao tác lập chỉ mục / chức năng cắt trong tệp
Slice.pd đó là một phần của phân phối PDL; nhưng hãy cẩn thận, đây không phải là cấp độ giới thiệu
chất liệu).

Nếu PDL được biên dịch với sự hỗ trợ cho các giá trị không hợp lệ (tức là "WITH_BADVAL => 1"), thì bổ sung
khóa là bắt buộc cho "pp_def", như được giải thích bên dưới.

Nếu bạn chỉ quan tâm đến việc giao tiếp với một số thư viện bên ngoài (ví dụ: một số
đại số tuyến tính / thư viện ma trận), bạn thường sẽ muốn 'hoạt động dữ liệu', vì vậy chúng tôi sẽ
để thảo luận về điều đó trước.

Ngày hoạt động


A đơn giản ví dụ
Trong thao tác dữ liệu, bạn phải biết bạn cần những thứ nguyên nào của dữ liệu. Đầu tiên, một ví dụ
với vô hướng:

pp_def ('thêm',
Phân tích cú pháp => 'a (); b (); [o] c (); ',
Mã => '$ c () = $ a () + $ b ();'
);

Điều đó trông hơi kỳ lạ nhưng chúng ta hãy mổ xẻ nó. Dòng đầu tiên rất dễ dàng: chúng tôi đang xác định một
quy trình với tên 'add'. Dòng thứ hai chỉ đơn giản khai báo các tham số của chúng tôi và
dấu ngoặc đơn có nghĩa là chúng là vô hướng. Chúng tôi gọi chuỗi xác định các tham số của chúng tôi và
kích thước của họ chữ ký của chức năng đó. Vì sự liên quan của nó đối với
các thao tác phân luồng và lập chỉ mục kiểm tra trang PDL :: Lập chỉ mục người đàn ông.

Dòng thứ ba là hoạt động thực tế. Bạn cần sử dụng các ký hiệu đô la và dấu ngoặc đơn
để tham chiếu đến các thông số của bạn (điều này có thể sẽ thay đổi vào một thời điểm nào đó trong tương lai, sau khi
cú pháp tốt được tìm thấy).

Những dòng này là tất cả những gì cần thiết để thực sự xác định chức năng cho PDL (tốt,
thực sự nó không phải là; bạn cũng cần viết Makefile.PL (xem bên dưới) và xây dựng
module (một cái gì đó như 'perl Makefile.PL; make'); nhưng chúng ta hãy bỏ qua điều đó vào lúc này).
Vì vậy, bây giờ bạn có thể làm

sử dụng MyModule;
$ a = pdl 2,3,4;
$ b = pdl 5;

$ c = add ($ a, $ b);
# hoặc là
add ($ a, $ b, ($ c = null)); # Biểu mẫu thay thế, hữu ích nếu $ c đã được
# đặt trước cho một cái gì đó lớn, không hữu ích ở đây.

và phân luồng hoạt động chính xác (kết quả là $ c == [7 8 9]).

Sản phẩm Pars phần: các chữ ký of a PP chức năng
Nhìn thấy đoạn mã ví dụ trên, chắc hẳn bạn sẽ hỏi: "$ c = null" kỳ lạ này là gì
cú pháp trong lần gọi thứ hai đến chức năng "thêm" mới của chúng tôi? Nếu bạn có một cái nhìn khác về
định nghĩa của "add", bạn sẽ nhận thấy rằng đối số thứ ba "c" được gắn cờ
định tính "[o]" cho PDL :: PP biết rằng đây là một đối số đầu ra. Vì vậy, cuộc gọi ở trên để
add có nghĩa là 'tạo $ c mới từ đầu với kích thước chính xác' - "null" là một đặc biệt
mã thông báo cho 'trống piddle' (bạn có thể hỏi tại sao chúng tôi không sử dụng giá trị "undef" để gắn cờ điều này
thay vì "null" cụ thể PDL; chúng tôi hiện đang suy nghĩ về nó;).

[Điều này cũng nên được giải thích trong một số phần khác của sách hướng dẫn !!] Lý do cho
có cú pháp này như một sự thay thế là nếu bạn có những bí quyết thực sự lớn, bạn có thể làm

$ c = PDL-> null;
for (một số vòng lặp dài) {
# munge a, b
thêm ($ a, $ b, $ c);
# munge c, đặt cái gì đó trở lại a, b
}

và tránh phân bổ và phân bổ $ c mỗi lần. Nó được phân bổ một lần ở lần đầu tiên
thêm vào() và sau đó bộ nhớ vẫn còn cho đến khi $ c bị phá hủy.

Nếu bạn chỉ nói

$ c = add ($ a, $ b);

mã do PP tạo ra sẽ tự động điền vào "$ c = null" và trả về kết quả. Nếu như
bạn muốn tìm hiểu thêm về lý do tại sao PDL :: PP hỗ trợ kiểu này khi đầu ra
các đối số được đưa ra khi các đối số cuối cùng kiểm tra trang PDL :: Lập chỉ mục người đàn ông.

"[o]" không phải là định nghĩa duy nhất mà đối số pdl có thể có trong chữ ký. Nữa
định tính quan trọng là tùy chọn "[t]" gắn cờ pdl là tạm thời. Cái gì vậy
nghĩa là? Bạn nói với PDL :: PP rằng pdl này chỉ được sử dụng cho các kết quả tạm thời trong quá trình
tính toán và bạn không quan tâm đến giá trị của nó sau khi tính toán đã
hoàn thành. Nhưng tại sao PDL :: PP lại muốn biết về điều này ngay từ đầu? Nguyên nhân
có liên quan chặt chẽ đến các khái niệm về tạo tự động pdl (bạn đã nghe về điều đó ở trên) và
phân luồng ngầm. Nếu bạn sử dụng phân luồng ngầm định thì kích thước của tự động
pdls được tạo thực sự lớn hơn so với quy định trong chữ ký. Với "[o]" được gắn cờ
pdls sẽ được tạo để chúng có các kích thước bổ sung theo yêu cầu của số
của kích thước chủ đề ngầm định. Tuy nhiên, khi tạo một pdl tạm thời, nó sẽ luôn chỉ
được tạo đủ lớn để nó có thể giữ kết quả cho một lần lặp trong vòng lặp luồng, tức là
lớn như yêu cầu của chữ ký. Vì vậy, ít bộ nhớ bị lãng phí hơn khi bạn gắn cờ pdl là
tạm thời. Thứ hai, bạn có thể sử dụng tính năng tạo tự động đầu ra với các pdls tạm thời ngay cả khi bạn
đang sử dụng phân luồng rõ ràng bị cấm đối với các pdls đầu ra bình thường được gắn cờ "[o]"
(xem PDL :: Lập chỉ mục).

Đây là một ví dụ trong đó chúng tôi sử dụng định tính [t]. Chúng tôi xác định hàm "callf"
gọi một quy trình C "f" cần một mảng tạm thời có cùng kích thước và kiểu như mảng
"a" (xin lỗi về tham chiếu chuyển tiếp cho $ P; đó là quyền truy cập con trỏ, xem bên dưới):

pp_def ('callf',
Phân tích cú pháp => 'a (n); [t] tmp (n); [o] b () ',
Mã => 'int ns = $ SIZE (n);
f ($ P (a), $ P (b), $ P (tmp), ns);
'
);

Tranh luận kích thước các chữ ký
Bây giờ chúng ta vừa nói về kích thước của pdls và chữ ký. Họ có liên quan với nhau như thê nào?
Giả sử rằng chúng ta muốn thêm một đại lượng vô hướng + số chỉ mục vào một vectơ:

pp_def ('add2',
Phân tích cú pháp => 'a (n); b (); [o] c (n); ',
Mã => 'loop (n)% {
$ c () = $ a () + $ b () + n;
%} '
);

Có một số điểm cần lưu ý ở đây: đầu tiên, đối số "Phân tích cú pháp" hiện chứa n
đối số để cho thấy rằng chúng tôi có một thứ nguyên duy nhất trong ac. Điều quan trọng cần lưu ý
rằng thứ nguyên là các thực thể thực tế được truy cập bằng tên nên điều này khai báo ac đến
tương tự kích thước đầu tiên. Trong hầu hết các định nghĩa PP, kích thước của các kích thước được đặt tên sẽ
được đặt từ các kích thước tương ứng của các pdls không phải đầu ra (những pdf không có cờ "[o]") nhưng
đôi khi bạn có thể muốn đặt kích thước của một thứ nguyên được đặt tên một cách rõ ràng thông qua một
tham số nguyên. Xem bên dưới trong mô tả của phần "OtherPars" hoạt động như thế nào.

Liên tục đối số kích thước in các chữ ký
Giả sử bạn muốn một piddle đầu ra được tạo tự động và bạn biết rằng trên mọi
gọi kích thước của nó sẽ có cùng kích thước (giả sử 9) bất kể kích thước của
đầu vào piddles. Trong trường hợp này, bạn sử dụng cú pháp sau trong phần Phân tích cú pháp để chỉ định
kích thước của thứ nguyên:

'[o] y (n = 9); '

Như mong đợi, các kích thước phụ theo yêu cầu của luồng sẽ được tạo nếu cần thiết. nếu bạn
cần chỉ định một thứ nguyên được đặt tên theo một công thức phức tạp hơn (hơn một hằng số)
bạn phải sử dụng khóa "RedoDimsCode" được mô tả bên dưới.

Kiểu chuyển đổi các chữ ký
Chữ ký cũng xác định các chuyển đổi kiểu sẽ được thực hiện khi một PP
hàm được gọi. Vì vậy, điều gì sẽ xảy ra khi chúng ta gọi một trong những
các hàm với các pdls thuộc loại khác nhau, ví dụ:

add2 ($ a, $ b, ($ ret = null));

trong đó $ a thuộc loại "PDL_Float" và $ b thuộc loại "PDL_Short"? Với chữ ký như hình
định nghĩa của "add2" phía trên kiểu dữ liệu của hoạt động (như được xác định trong thời gian chạy) là
của pdl với loại 'cao nhất' (chuỗi là byte <ngắn <ushort <dài <float
<gấp đôi). Trong ví dụ add2, kiểu dữ liệu của hoạt động là float ($ a có
loại dữ liệu). Tất cả các đối số pdl sau đó được chuyển đổi kiểu thành kiểu dữ liệu đó (chúng không
được chuyển đổi tại chỗ nhưng một bản sao với đúng loại sẽ được tạo nếu đối số pdl không có
loại hoạt động). Null pdls không đóng góp một loại trong việc xác định
loại hoạt động. Tuy nhiên, chúng sẽ được tạo với kiểu dữ liệu của hoạt động;
ở đây, ví dụ, $ ret sẽ có kiểu float. Bạn nên biết các quy tắc này khi
gọi các hàm PP với các pdls thuộc các loại khác nhau để lấy thêm dung lượng lưu trữ và
yêu cầu thời gian chạy được tính đến.

Các chuyển đổi kiểu này đúng với hầu hết các hàm mà bạn thường xác định bằng "pp_def".
Tuy nhiên, có một số trường hợp nhất định trong đó hành vi chuyển đổi loại được sửa đổi một chút là
mong muốn. Đối với những trường hợp này, các dấu hiệu định tính bổ sung trong chữ ký có thể được sử dụng để chỉ định
thuộc tính mong muốn liên quan đến chuyển đổi kiểu. Các vòng loại này có thể được kết hợp với
những người chúng tôi đã gặp phải ( tạo vòng loại "[o]" và "[t]"). Đi nào
thông qua danh sách các bộ định lượng thay đổi hành vi chuyển đổi loại.

Điều quan trọng nhất là định tính "int" có ích khi đối số pdl
đại diện cho các chỉ số thành một pdl khác. Hãy xem một ví dụ từ "PDL :: Ufunc":

pp_def ('Maximum_ind',
Phân tích cú pháp => 'a (n); int [o] b () ',
Mã => '$ GENERIC () cur;
int curin;
loop (n)% {
if (! n || $ a ()> cur) {cur = $ a (); curind = n;}
%}
$ b () = curind; ',
);

Hàm "Maximum_ind" tìm chỉ số của phần tử lớn nhất của một vectơ. Nếu bạn nhìn
tại chữ ký, bạn nhận thấy rằng đối số đầu ra "b" đã được khai báo với
bổ sung định tính "int". Điều này có những hậu quả sau đây đối với chuyển đổi kiểu:
bất kể loại đầu vào pdl "a", đầu ra pdl "b" sẽ thuộc loại "PDL_Long"
điều này có ý nghĩa vì "b" sẽ đại diện cho một chỉ mục thành "a". Hơn nữa, nếu bạn gọi
với một đầu ra hiện có pdl "b", kiểu của nó sẽ không ảnh hưởng đến kiểu dữ liệu của
hoạt động (xem ở trên). Do đó, ngay cả khi "a" thuộc loại nhỏ hơn "b", nó sẽ không
được chuyển đổi để phù hợp với loại "b" nhưng vẫn không bị ảnh hưởng, giúp tiết kiệm bộ nhớ và chu kỳ CPU
và là điều đúng đắn cần làm khi "b" đại diện cho các chỉ số. Cũng lưu ý rằng bạn có thể sử dụng
vòng loại 'int' cùng với các vòng loại khác (vòng loại "[o]" và "[t]"). Đặt hàng là
các bộ định nghĩa kiểu quan trọng đứng trước bộ định nghĩa tạo ("[o]" và "[t]").

Ví dụ trên cũng minh họa cách sử dụng điển hình của macro "$ GENERIC ()". Nó mở rộng
đến loại hiện tại trong một vòng lặp được gọi là chung. Vòng lặp chung là gì? Như bạn đã
nghe nói một hàm PP có kiểu dữ liệu thời gian chạy được xác định bởi kiểu của các đối số pdl
nó đã được gọi với. Do đó, mã XS được tạo PP cho chức năng này chứa một
chuyển đổi như "switch (type) {case PDL_Byte: ... case PDL_Double: ...}" để chọn một trường hợp
dựa trên kiểu dữ liệu thời gian chạy của hàm (nó được gọi là kiểu `` vòng lặp '' vì ở đó
là một vòng lặp trong mã PP tạo ra các trường hợp). Trong mọi trường hợp, mã của bạn được chèn một lần
cho mỗi loại PDL vào câu lệnh switch này. Macro "$ GENERIC ()" chỉ mở rộng thành
nhập tương ứng vào từng bản sao mã được phân tích cú pháp của bạn trong câu lệnh "switch" này, ví dụ: trong
"case PDL_Byte" phần "cur" sẽ mở rộng thành "PDL_Byte", v.v. đối với trường hợp khác
các câu lệnh. Tôi đoán bạn nhận ra rằng đây là một macro hữu ích để giữ các giá trị của pdls trong một số
Mã.

Có một vài từ định tính khác có hiệu ứng tương tự như "int". Cho của bạn
sự tiện lợi có các định tính "float" và "double" với các hệ quả tương tự trên
nhập các chuyển đổi là "int". Hãy giả sử bạn có một rất mảng lớn mà bạn muốn
tính tổng của hàng và cột với hàm tương đương với hàm "sumover". Tuy nhiên, với
định nghĩa thông thường của "sumover", bạn có thể gặp vấn đề khi dữ liệu của bạn, ví dụ:
gõ ngắn. Một cuộc gọi như

sumover ($ large_pdl, ($ sums = null));

sẽ dẫn đến số tiền $ thuộc loại ngắn và do đó dễ bị lỗi tràn nếu
$ large_pdl là một mảng rất lớn. Mặt khác kêu gọi

@dims = $ large_pdl-> mờ; shift @dims;
sumover ($ large_pdl, ($ sums = zeroes (double, @ dims)));

cũng không phải là một sự thay thế tốt. Bây giờ chúng tôi không gặp sự cố tràn với $ sums nhưng tại
chi phí chuyển đổi kiểu từ $ large_pdl thành gấp đôi, điều này thật tệ nếu đây thực sự là
một pdl lớn. Đó là nơi mà "double" có ích:

pp_def ('sumoverd',
Phân tích cú pháp => 'a (n); double [o] b () ',
Mã => 'double tmp = 0;
loop (n)% {tmp + = a (); %}
$ b () = tmp; ',
);

Điều này giúp chúng tôi giải quyết các vấn đề chuyển đổi kiểu và tràn. Một lần nữa, tương tự như
"int" vòng loại "double" cho kết quả là "b" luôn thuộc loại double bất kể loại
của "a" mà không dẫn đến chuyển đổi kiểu thành "a" như một tác dụng phụ.

Cuối cùng, có các vòng loại "type +" trong đó type là một trong các "int" hoặc "float". Gì
có nghĩa là. Hãy minh họa định nghĩa "int +" với định nghĩa thực tế của
tổng kết:

pp_def ('sumover',
Phân tích cú pháp => 'a (n); int + [o] b () ',
Mã => '$ GENERIC (b) tmp = 0;
loop (n)% {tmp + = a (); %}
$ b () = tmp; ',
);

Như chúng ta đã thấy đối với các định tính "int", "float" và "double", một pdl được đánh dấu bằng
định tính "type +" không ảnh hưởng đến kiểu dữ liệu của hoạt động pdl. Ý nghĩa của nó là
"tạo pdl này ít nhất là loại" loại "hoặc cao hơn, theo yêu cầu của loại
hoạt động ". Trong ví dụ sumover, điều này có nghĩa là khi bạn gọi hàm bằng" a "
thuộc loại PDL_Short, pdl đầu ra sẽ thuộc loại PDL_Long (giống như
trường hợp với định tính "int"). Điều này một lần nữa cố gắng tránh sự cố tràn khi sử dụng
kiểu dữ liệu nhỏ (ví dụ: hình ảnh byte). Tuy nhiên, khi kiểu dữ liệu của hoạt động cao hơn
hơn loại được chỉ định trong bộ định tính "loại +" "b" sẽ được tạo với kiểu dữ liệu là
hoạt động, ví dụ: khi "a" là kiểu double thì "b" cũng sẽ là double. Chúng tôi hy vọng
bạn đồng ý rằng đây là hành vi hợp lý đối với "sumover". Rõ ràng là làm thế nào
Bộ định tính "float +" hoạt động theo phép loại suy. Nó có thể trở nên cần thiết để có thể chỉ định một tập hợp
của các loại thay thế cho các tham số. Tuy nhiên, điều này có thể sẽ không được thực hiện
cho đến khi ai đó nghĩ ra cách sử dụng hợp lý cho nó.

Lưu ý rằng bây giờ chúng ta phải chỉ định macro $ GENERIC với tên của pdl để lấy ra
gõ từ đối số đó. Tại sao vậy? Nếu bạn cẩn thận làm theo những giải thích của chúng tôi, bạn sẽ
đã nhận ra rằng trong một số trường hợp, "b" sẽ có kiểu khác với kiểu của
hoạt động. Gọi macro '$ GENERIC' với "b" làm đối số đảm bảo rằng loại
sẽ luôn giống như của "b" trong phần đó của vòng lặp chung.

Đây là tất cả những gì cần nói về phần "Phân tích cú pháp" trong lệnh gọi "pp_def". Bạn nên
hãy nhớ rằng phần này xác định chữ ký của một hàm được định nghĩa PP, bạn có thể sử dụng
một số tùy chọn để đủ điều kiện cho các đối số nhất định dưới dạng các giá trị đầu ra và tạm thời và tất cả
thứ nguyên mà bạn có thể tham khảo sau này trong phần "Mã" được xác định theo tên.

Điều quan trọng là bạn phải hiểu ý nghĩa của chữ ký kể từ trong PDL mới nhất
các phiên bản bạn có thể sử dụng nó để xác định các hàm theo luồng từ bên trong Perl, tức là những gì chúng tôi gọi là
Perl cấp luồng. Vui lòng kiểm tra PDL :: Lập chỉ mục để biết chi tiết.

Sản phẩm phần
Phần "Mã" chứa mã XS thực tế sẽ nằm ở phần trong cùng của
vòng lặp luồng (nếu bạn không biết vòng lặp luồng là gì thì bạn vẫn chưa đọc
PDL :: Lập chỉ mục; làm điều đó ngay bây giờ;) sau khi bất kỳ macro PP nào (như $ GENERIC) và các hàm PP đã được
được mở rộng (giống như hàm "loop" mà chúng tôi sẽ giải thích tiếp theo).

Hãy nhanh chóng nhắc lại ví dụ "sumover":

pp_def ('sumover',
Phân tích cú pháp => 'a (n); int + [o] b () ',
Mã => '$ GENERIC (b) tmp = 0;
loop (n)% {tmp + = a (); %}
$ b () = tmp; ',
);

Cấu trúc "vòng lặp" trong phần "Mã" cũng đề cập đến tên thứ nguyên, vì vậy bạn không
cần chỉ định bất kỳ giới hạn nào: vòng lặp có kích thước chính xác và mọi thứ được thực hiện cho bạn,
một lần nữa.

Tiếp theo, có một thực tế đáng ngạc nhiên là "$ a ()" và "$ b ()" làm không chứa chỉ mục. Điều này
không cần thiết vì chúng tôi đang lặp lại n và cả hai biến đều biết thứ nguyên nào
họ có để họ tự động biết họ đang bị lặp lại.

Tính năng này rất tiện dụng ở nhiều nơi và làm cho mã ngắn hơn nhiều. Của
tất nhiên, có những lúc bạn muốn phá vỡ điều này; đây là một chức năng tạo ra một
ma trận đối xứng và phục vụ như một ví dụ về cách mã hóa vòng lặp rõ ràng:

pp_def ('symm',
Phân tích cú pháp => 'a (n, n); [o] c (n, n); ',
Mã => 'loop (n)% {
int n2;
for (n2 = n; n2 <$ SIZE (n); n2 ++) {
$ c (n0 => n, n1 => n2) =
$ c (n0 => n2, n1 => n) =
$ a (n0 => n, n1 => n2);
}
%}
'
);

Hãy mổ xẻ những gì đang xảy ra. Thứ nhất, chức năng này phải làm gì? Từ nó
bạn thấy rằng nó có một ma trận 2D với số cột và hàng bằng nhau và
xuất ra một ma trận có cùng kích thước. Từ một ma trận đầu vào nhất định $ a, nó tính một đối xứng
ma trận đầu ra $ c (đối xứng theo nghĩa ma trận rằng A ^ T = A trong đó ^ T nghĩa là ma trận
chuyển vị, hoặc theo cách nói của PDL $ c == $ c-> xchg (0,1)). Nó thực hiện điều này bằng cách chỉ sử dụng các giá trị
trên và dưới đường chéo của $ a. Trong ma trận đầu ra $ c tất cả các giá trị trên và dưới
đường chéo giống như những đường trong $ a trong khi những đường chéo nằm trên đường chéo là hình ảnh phản chiếu của
những cái bên dưới đường chéo (phía trên và bên dưới ở đây được hiểu theo cách mà PDL in
Pdls 2D). Nếu lời giải thích này vẫn còn hơi lạ, hãy tiếp tục, tạo một tệp nhỏ
mà bạn viết định nghĩa này, hãy xây dựng phần mở rộng PDL mới (xem phần trên
Makefiles cho mã PP) và dùng thử với một vài ví dụ.

Sau khi giải thích những gì chức năng được cho là để làm, có một vài điểm đáng giá
lưu ý từ quan điểm cú pháp. Đầu tiên, chúng tôi nhận được kích thước của thứ nguyên có tên
"n" lại bằng cách sử dụng macro $ SIZE. Thứ hai, đột nhiên có những "n0" và "n1" vui nhộn này
tên chỉ mục trong mã mặc dù chữ ký chỉ xác định thứ nguyên "n". Tại sao lại thê nay? Các
lý do trở nên rõ ràng khi bạn lưu ý rằng cả thứ nguyên thứ nhất và thứ hai của $ a và $ b
được đặt tên là "n" trong chữ ký của "symm". Điều này cho PDL :: PP biết rằng thứ nhất và thứ hai
thứ nguyên của các đối số này phải có cùng kích thước. Nếu không, hàm được tạo
sẽ gây ra lỗi thời gian chạy. Tuy nhiên, bây giờ trong quyền truy cập vào $ a và $ c PDL :: PP không thể tìm
chỉ số nào "n" đề cập đến bất kỳ chỉ mục nào nữa chỉ từ tên của chỉ mục. Do đó,
các chỉ số có tên thứ nguyên bằng nhau được đánh số từ trái sang phải bắt đầu từ 0, ví dụ: trong
ví dụ trên "n0" đề cập đến thứ nguyên đầu tiên của $ a và $ c, "n1" là thứ hai và
Sớm.

Trong tất cả các ví dụ cho đến nay, chúng tôi chỉ sử dụng các thành viên "Phân tích cú pháp" và "Mã" của hàm băm
đã được chuyển tới "pp_def". Chắc chắn có các khóa khác được PDL :: PP và
chúng ta sẽ nghe về một số trong số chúng trong quá trình của tài liệu này. Tìm một (không đầy đủ)
danh sách các khóa trong Phụ lục A. Danh sách các macro và hàm PP (chúng tôi mới chỉ gặp
một số trong các ví dụ trên) được mở rộng trong các giá trị của đối số băm
thành "pp_def" được tóm tắt trong Phụ lục B.

Tại thời điểm này, có thể thích hợp khi đề cập rằng PDL :: PP không hoàn toàn tĩnh,
được thiết kế tốt về các quy trình (như Tuomas đã nói: "đừng nghĩ đến PP như một tập hợp
những thói quen được khắc trên đá ") mà là một tập hợp những thứ mà tác giả PDL :: PP
(Tuomas J. Lukka) cho rằng anh ấy sẽ phải viết thường xuyên vào các thói quen mở rộng PDL của mình.
PP cố gắng có thể mở rộng để trong tương lai, khi có nhu cầu mới, mã chung mới có thể
được trừu tượng hóa trở lại nó. Nếu bạn muốn tìm hiểu thêm về lý do tại sao bạn có thể muốn thay đổi
PDL :: PP và cách thực hiện kiểm tra phần bên trong PDL :: PP.

Xử lý xấu giá trị
Nếu bạn không có hỗ trợ giá trị xấu được biên dịch thành PDL, bạn có thể bỏ qua phần này và
các khóa liên quan: "BadCode", "HandleBad", ... (thử in ra giá trị của
$ PDL :: Bad :: Trạng thái - nếu nó bằng 0 thì tiếp tục).

Có một số khóa và macro được sử dụng khi viết mã để xử lý các giá trị xấu. Người đầu tiên
một là khóa "HandleBad":

HandleBad => 0
Điều này gắn cờ một quy trình pp là KHÔNG xử lý các giá trị xấu. Nếu quy trình này được gửi piddles
với "badflag" được đặt, sau đó một thông báo cảnh báo được in tới STDOUT và piddles
được xử lý như thể giá trị được sử dụng để đại diện cho các giá trị xấu là một số hợp lệ. Các
giá trị "badflag" không được đề xuất cho các piddles đầu ra.

Một ví dụ về thời điểm điều này được sử dụng cho các quy trình FFT, thường không có cách
bỏ qua một phần dữ liệu.

HandleBad => 1
Điều này khiến PDL :: PP viết mã bổ sung để đảm bảo phần BadCode được sử dụng và
rằng macro "$ ISBAD ()" (và những người anh em của nó) hoạt động.

HandleBad không được đưa ra
Nếu bất kỳ piddles đầu vào nào có đặt "badflag", thì các piddles đầu ra sẽ
đặt "badflag" của họ, nhưng bất kỳ Mã BadCode nào được cung cấp đều bị bỏ qua.

Giá trị của "HandleBad" được sử dụng để xác định nội dung của khóa "BadDoc", nếu nó không phải là
được.

Để xử lý các giá trị xấu, mã phải được viết hơi khác; ví dụ,

$ c () = $ a () + $ b ();

trở thành một cái gì đó giống như

if ($ a ()! = BADVAL && $ b ()! = BADVAL) {
$ c () = $ a () + $ b ();
} Else {
$ c () = BADVAL;
}

Tuy nhiên, chúng tôi chỉ muốn phiên bản thứ hai nếu các giá trị xấu có trong các piddles đầu vào
(và hỗ trợ giá trị xấu đó là cần thiết!) - nếu không, chúng tôi thực sự muốn mã gốc.
Đây là nơi chứa khóa "BadCode"; bạn sử dụng nó để chỉ định mã thực thi nếu xấu
các giá trị có thể có và PP sử dụng cả nó và phần "Mã" để tạo ra một cái gì đó
như:

if (bad_values_are_present) {
ưa thích_threadloop_stuff {
mã xấu
}
} Else {
ưa thích_threadloop_stuff {

}
}

Cách tiếp cận này có nghĩa là hầu như không có chi phí khi các giá trị xấu không xuất hiện
(tức là quy trình badflag trả về 0).

Phần BadCode có thể sử dụng các macro và cấu trúc lặp giống như phần Mã.
Tuy nhiên, nó sẽ không được sử dụng nhiều nếu không có các macro bổ sung sau:

$ ISBAD (var)
Để kiểm tra xem giá trị của piddle có xấu hay không, hãy sử dụng macro $ ISBAD:

if ($ ISBAD (a ())) {printf ("a () la sai \ n"); }

Bạn cũng có thể truy cập các phần tử nhất định của một piddle:

if ($ ISBAD (a (n => l))) {printf ("phần tử% d của a () là xấu \ n", l); }

$ ISGOOD (var)
Điều này ngược lại với macro $ ISBAD.

$ SETBAD (var)
Đối với trường hợp bạn muốn thiết lập một phần tử của một piddle bad.

$ ISBADVAR (c_var, pdl)
Nếu bạn đã lưu trữ giá trị của một piddle "$ a ()" vào một biến c ("foo" say), thì hãy
kiểm tra xem nó có xấu hay không, sử dụng "$ ISBADVAR (foo, a)".

$ ISGOODVAR (c_var, pdl)
Như trên, nhưng lần này kiểm tra xem giá trị được lưu trong bộ nhớ cache không phải là xấu.

$ SETBADVAR (c_var, pdl)
Để sao chép giá trị bad của một piddle vào biến ac, hãy sử dụng "$ SETBADVAR (foo, a)".

LÀM: đề cập đến các macro "$ PPISBAD ()", v.v.

Sử dụng các macro này, mã trên có thể được chỉ định là:

Mã => '$ c () = $ a () + $ b ();',
BadCode => '
if ($ ISBAD (a ()) || $ ISBAD (b ())) {
$ SETBAD (c ());
} Else {
$ c () = $ a () + $ b ();
} ',

Vì đây là Perl, TMTOWTDI, nên bạn cũng có thể viết:

BadCode => '
if ($ ISGOOD (a ()) && $ ISGOOD (b ())) {
$ c () = $ a () + $ b ();
} Else {
$ SETBAD (c ());
} ',

Nếu bạn muốn truy cập vào giá trị của badflag cho một trò chơi đã cho, bạn có thể sử dụng
Macro "$ PDLSTATExxxx ()":

$ PDLSTATEISBAD (pdl)
$ PDLSTATEISGOOD (pdl)
$ PDLSTATESETBAD (pdl)
$ PDLSTATESETGOOD (pdl)

LÀM: cũng đề cập đến các tùy chọn "FindBadStatusCode" và "CopyBadStatusCode" cho "pp_def"
làm khóa "BadDoc".

Giao diện qua một vài thao tác đơn giản về riêng / thư viện chức năng sử dụng PP
Bây giờ, hãy xem xét những điều sau: bạn có hàm C của riêng mình (trên thực tế có thể là một phần của
một số thư viện mà bạn muốn giao tiếp với PDL) lấy làm đối số là hai con trỏ tới
vectơ kép:

void myfunc (int n, double * v1, double * v2);

Cách chính xác để xác định hàm PDL là

pp_def ('myfunc',
Phân tích cú pháp => 'a (n); [o] b (n); ',
GenericTypes => ['D'],
Mã => 'myfunc ($ SIZE (n), $ P (a), $ P (b));'
);

"$ P ("mệnhCú pháp ")" trả về một con trỏ đến phần tử đầu tiên và các phần tử khác là
đảm bảo sẽ nói dối sau đó.

Lưu ý rằng ở đây có thể mắc nhiều lỗi. Đầu tiên, $ SIZE (n) phải được sử dụng
thay vì "n". Thứ hai, bạn không nên đặt bất kỳ vòng lặp nào trong mã này. Thứ ba, ở đây chúng ta gặp
một khóa băm mới được PDL :: PP công nhận: khai báo "GenericTypes" yêu cầu PDL :: PP
CHỈ TẠO TYPELOOP DANH SÁCH CÁC LOẠI ĐƯỢC CHỈ ĐỊNH CỤ THỂ. Trong trường hợp này là "gấp đôi". Điều này
có hai lợi thế. Thứ nhất, kích thước của mã đã biên dịch được giảm đáng kể, thứ hai nếu
các đối số không phải kép được chuyển đến "myfunc ()" PDL sẽ tự động chuyển đổi chúng thành
nhân đôi trước khi chuyển sang thói quen C bên ngoài và chuyển đổi chúng trở lại sau đó.

Người ta cũng có thể sử dụng "Phân tích cú pháp" để xác định các loại đối số riêng lẻ. Vì vậy, người ta cũng có thể
viết cái này là:

pp_def ('myfunc',
Phân tích cú pháp => 'double a (n); double [o] b (n); ',
Mã => 'myfunc ($ SIZE (n), $ P (a), $ P (b));'
);

Đặc tả kiểu trong "Phân tích cú pháp" loại trừ đối số khỏi biến thể trong typeloop -
thay vào đó nó cũng được tự động chuyển đổi và từ kiểu được chỉ định. Đây rõ ràng là
hữu ích trong một ví dụ tổng quát hơn, ví dụ:

void myfunc (int n, float * v1, long * v2);

pp_def ('myfunc',
Phân tích cú pháp => 'float a (n); long [o] b (n); ',
GenericTypes => ['F'],
Mã => 'myfunc ($ SIZE (n), $ P (a), $ P (b));'
);

Lưu ý rằng chúng tôi vẫn sử dụng "GenericTypes" để giảm kích thước của vòng lặp kiểu, rõ ràng PP có thể
về nguyên tắc, hãy phát hiện điều này và thực hiện nó tự động mặc dù mã vẫn chưa đạt được điều đó
mức độ tinh vi!

Cuối cùng lưu ý khi các loại được chuyển đổi tự động, người ta PHẢI sử dụng bộ định nghĩa "[o]" cho
các biến đầu ra hoặc bạn khó thay đổi một trong những thay đổi sẽ được tối ưu hóa bằng PP!

Nếu bạn giao diện một thư viện lớn, bạn có thể tự động hóa giao diện hơn nữa. Perl có thể
giúp bạn một lần nữa (!) trong việc này. Trong nhiều thư viện, bạn có một số quy ước gọi điện nhất định.
Điều này có thể được khai thác. Tóm lại, bạn có thể viết một trình phân tích cú pháp nhỏ (mà thực sự không
khó trong Perl) sau đó tạo các lệnh gọi đến "pp_def" từ các mô tả được phân tích cú pháp của
các chức năng trong thư viện đó. Để có ví dụ, vui lòng kiểm tra đá phiến giao diện trong
Cây "Lib" của phân phối PDL. Nếu bạn muốn kiểm tra (trong khi gỡ lỗi) cuộc gọi đến
PP chức năng mã Perl của bạn được tạo ra một gói trợ giúp nhỏ có ích
thay thế các hàm PP bằng các hàm được đặt tên giống hệt nhau để kết xuất các đối số của chúng thành hàm stdout.

Chỉ cần nói

perl -MPDL :: PP :: Dump myfile.pd

để xem các cuộc gọi đến "pp_def" và bạn bè. Hãy thử nó với ops.pdđá phiến.pd. Nếu bạn
quan tâm (hoặc muốn nâng cao nó), nguồn là Basic / Gen / PP / Dump.pm

Nền tảng khác macro chức năng in các phần
Macro: Cho đến nay chúng ta đã gặp các macro $ SIZE, $ GENERIC và $ P. Bây giờ chúng ta sẽ
giải thích nhanh các macro khác được mở rộng trong phần "Mã" của PDL :: PP cùng
với các ví dụ về cách sử dụng của chúng.

$ T Macro $ T được sử dụng cho các công tắc loại. Điều này rất hữu ích khi bạn phải sử dụng
các hàm bên ngoài (ví dụ như thư viện) khác nhau tùy thuộc vào kiểu đầu vào của các đối số.
Cú pháp chung là

$ Ttypeletters (type_alternatives)

trong đó "typeletters" là sự hoán vị của một tập hợp con các chữ cái "BSULFD" đứng
đối với Byte, Short, Ushort, v.v. và "type_alternatives" là các phần mở rộng khi loại
của hoạt động PP tương đương với được chỉ ra bằng chữ cái tương ứng. Hãy
minh họa mô tả khó hiểu này bằng một ví dụ. Giả sử bạn có hai C
các chức năng với nguyên mẫu

void float_func (float * in, float * out);
void double_func (double * in, double * out);

về cơ bản làm điều tương tự nhưng một cái chấp nhận float và các con trỏ kép khác.
Bạn có thể giao diện chúng với PDL bằng cách xác định một hàm chung "foofunc" (sẽ
gọi hàm đúng tùy thuộc vào kiểu biến đổi):

pp_def ('foofunc',
Phân tích cú pháp => 'a (n); [o] b (); ',
Mã => '$ TFD (float_func, double_func) ($ P (a), $ P (b));'
GenericTypes => [qw (FD)],
);

Xin lưu ý rằng bạn không thể nói

Mã => '$ TFD (float, double) _func ($ P (a), $ P (b));'

vì macro $ T mở rộng với dấu cách ở cuối, tương tự như macro C tiền xử lý.
Hình thức dài hơn một chút được minh họa ở trên là chính xác. Nếu bạn thực sự muốn ngắn gọn, bạn
tất nhiên có thể làm

'$ TBSULFD ('. (Tham gia ',', bản đồ {"long_identifier_name _ $ _"}
qw / byt ngắn không dấu phòng chờ flotte dubble /). ');'

$ PP
Macro $ PP được sử dụng cho cái gọi là vật lý con trỏ truy cập. Các vật lý đề cập đến
một số tối ưu hóa nội bộ của PDL (đối với những người đã quen thuộc với lõi PDL, chúng tôi
nói về sự tối ưu hóa vaffine). Macro này chủ yếu để sử dụng nội bộ và bạn
không cần phải sử dụng nó trong bất kỳ mã thông thường nào của bạn.

$ COMP (và phần "OtherPars")
Macro $ COMP được sử dụng để truy cập các giá trị không phải pdl trong phần mã. Tên của nó là
bắt nguồn từ việc thực hiện các phép biến đổi trong PDL. Các biến bạn có thể tham khảo
để sử dụng $ COMP là các thành viên của cấu trúc `` biên dịch '' đại diện cho PDL
chuyển đổi được đề cập nhưng chưa chứa bất kỳ thông tin nào về các thứ nguyên
(để biết thêm chi tiết, hãy kiểm tra PDL :: Internals). Tuy nhiên, bạn có thể coi $ COMP chỉ là một
hộp đen mà không biết bất cứ điều gì về việc thực hiện các phép biến đổi trong PDL.
Vì vậy, khi nào bạn sẽ sử dụng macro này? Cách sử dụng chính của nó là để truy cập các giá trị của các đối số
được khai báo trong phần "OtherPars" của định nghĩa "pp_def". Nhưng sau đó bạn đã không
đã nghe nói về khóa "OtherPars" chưa ?! Hãy lấy một ví dụ khác minh họa
cách sử dụng điển hình của cả hai tính năng mới:

pp_def ('pnmout',
Phân tích cú pháp => 'a(m) ',
OtherPars => "char * fd",
GenericTypes => [qw (BUSL)],
Mã => 'PerlIO * fp;
IO * io;

io = GvIO (gv_fetchpv ($ COMP (fd), FALSE, SVt_PVIO));
if (! io ||! (fp = IoIFP (io)))
croak ("Không thể tìm ra FP");

if (PerlIO_write (fp, $ P (a), len)! = len)
croak ("Lỗi ghi tệp pnm");
');

Hàm này được sử dụng để ghi dữ liệu từ pdl vào tệp. Bộ mô tả tệp được chuyển
dưới dạng một chuỗi vào hàm này. Tham số này không đi vào phần "Phân tích cú pháp"
vì nó không thể được xử lý một cách hữu ích như pdl mà là theo tên aptly
Phần "OtherPars". Các thông số trong phần "OtherPars" tuân theo các thông số trong phần "Phân tích cú pháp"
khi gọi hàm, tức là

mở FILE, "> out.dat" hoặc chết "không thể mở out.dat";
pnmout ($ pdl, 'FILE');

Khi bạn muốn truy cập tham số này bên trong phần mã, bạn phải nói với PP bằng cách
sử dụng macro $ COMP, tức là bạn viết "$ COMP (fd)" như trong ví dụ. Nếu không thì PP
sẽ không biết rằng "fd" mà bạn đang đề cập đến giống với "fd" được chỉ định trong
Phần "OtherPars".

Một cách sử dụng khác cho phần "OtherPars" là đặt một thứ nguyên được đặt tên trong chữ ký.
Hãy xem một ví dụ về cách thực hiện:

pp_def ('setdim',
Phân tích cú pháp => '[o] a (n)',
OtherPars => 'int ns => n',
Code => 'loop (n)% {$ a () = n; %} ',
);

Điều này nói rằng thứ nguyên được đặt tên "n" sẽ được khởi tạo từ giá trị của khác
tham số "ns" thuộc kiểu số nguyên (Tôi đoán bạn đã nhận ra rằng chúng tôi sử dụng
Cú pháp "CType From => names_dim"). Bây giờ bạn có thể gọi hàm này theo cách thông thường:

setdim (($ a = null), 5);
in $ a;
[0 1 ​​2 ​​3 ​​4]

Phải thừa nhận rằng chức năng này không hữu ích lắm nhưng nó cho thấy nó hoạt động như thế nào. nếu bạn
gọi hàm với một pdl hiện có và bạn không cần chỉ định rõ ràng
kích thước của "n" vì PDL :: PP có thể tìm ra nó từ các kích thước của pdl không rỗng. Trong
trường hợp đó bạn chỉ cần cung cấp tham số thứ nguyên là "-1":

$ a = hist ($ b);
setdim ($ a, -1);

Nên làm vậy.

Hàm PP duy nhất mà chúng tôi đã sử dụng trong các ví dụ cho đến nay là "vòng lặp". Ngoài ra,
hiện có hai chức năng khác được công nhận trong phần "Mã":

vòng chỉ
Như chúng ta đã nghe ở trên, chữ ký của một hàm được định nghĩa PP xác định kích thước của tất cả
các đối số pdl liên quan đến một nguyên thủy hoạt động. Tuy nhiên, bạn thường gọi
các hàm mà bạn đã xác định bằng PP với pdls có nhiều thứ nguyên hơn
được chỉ định trong chữ ký. Trong trường hợp này, hoạt động nguyên thủy được thực hiện trên tất cả
các tập con của kích thước thích hợp trong cái được gọi là Chủ đề vòng lặp (Xem thêm
tổng quan ở trên và PDL :: Lập chỉ mục). Giả sử bạn có một số khái niệm về khái niệm này, bạn
có thể sẽ đánh giá cao rằng hoạt động được chỉ định trong phần mã phải
được tối ưu hóa vì đây là vòng lặp chặt chẽ nhất bên trong một vòng chuỗi. Tuy nhiên, nếu bạn truy cập lại
ví dụ mà chúng tôi xác định hàm "pnmout", bạn sẽ nhanh chóng nhận ra rằng
lên bộ mô tả tệp "IO" trong vòng lặp chuỗi bên trong không hiệu quả khi viết
một pdl với nhiều hàng. Một cách tiếp cận tốt hơn sẽ là tra cứu bộ mô tả "IO" một lần
bên ngoài vòng ren và sử dụng giá trị của nó sau đó bên trong vòng ren chặt chẽ nhất. Đây là
chính xác nơi mà chức năng "threadloop" có ích. Đây là một định nghĩa được cải thiện
của "pnmout" sử dụng chức năng này:

pp_def ('pnmout',
Phân tích cú pháp => 'a(m) ',
OtherPars => "char * fd",
GenericTypes => [qw (BUSL)],
Mã => 'PerlIO * fp;
IO * io;
int len;

io = GvIO (gv_fetchpv ($ COMP (fd), FALSE, SVt_PVIO));
if (! io ||! (fp = IoIFP (io)))
croak ("Không thể tìm ra FP");

len = $KÍCH THƯỚC(m) * sizeof ($ GENERIC ());

threadloop% {
if (PerlIO_write (fp, $ P (a), len)! = len)
croak ("Lỗi ghi tệp pnm");
%}
');

Điều này hoạt động như sau. Thông thường, mã C bạn viết bên trong phần "Mã" được đặt
bên trong một vòng lặp luồng (nghĩa là PP tạo ra mã XS bao bọc xung quanh nó).
Tuy nhiên, khi bạn sử dụng rõ ràng hàm "threadloop", PDL :: PP nhận ra điều này và
không quấn mã của bạn bằng một vòng lặp chuỗi bổ sung. Điều này có tác dụng mã bạn
ghi bên ngoài vòng lặp chỉ được thực hiện một lần cho mỗi lần chuyển đổi và chỉ mã
với cặp "% {...%}" xung quanh được đặt trong vòng lặp chuỗi chặt chẽ nhất. Điều này
cũng có ích khi bạn muốn thực hiện một quyết định (hoặc bất kỳ mã nào khác, đặc biệt là
Mã chuyên sâu của CPU) chỉ một lần cho mỗi luồng, tức là

pp_addhdr ('
#xác định RAW 0
#xác định ASCII 1
');
pp_def ('do_raworascii',
Phân tích cú pháp => 'a (); b (); [o] c () ',
OtherPars => 'int mode',
Code => 'switch ($COMP(chế độ)) {
trường hợp RAW:
threadloop% {
/ * làm đồ thô * /
%}
phá vỡ;
trường hợp ASCII:
threadloop% {
/ * làm nội dung ASCII * /
%}
phá vỡ;
mặc định:
croak ("chế độ không xác định");
}'
);

loại
Hàm loại hoạt động tương tự như macro $ T. Tuy nhiên, với chức năng "loại",
mã trong khối sau (được phân tách bằng "% {" và "%}" như thường lệ) được thực thi cho tất cả
những trường hợp mà kiểu dữ liệu của hoạt động là bất kì of các loại được đại diện bởi
các chữ cái trong đối số thành "type", ví dụ:

Mã => '...

loại (BSUL)% {
/ * thực hiện thao tác kiểu số nguyên * /
%}
loại (FD)% {
/ * thực hiện phép toán dấu phẩy động * /
%}
... '

Sản phẩm Làm lạiDimsMã Phần
Khóa "RedoDimsCode" là một khóa tùy chọn được sử dụng để tính toán kích thước của các piddles tại
thời gian chạy trong trường hợp các quy tắc tiêu chuẩn cho kích thước tính toán từ chữ ký không
hợp lý. Nội dung của mục nhập "RedoDimsCode" được diễn giải theo cùng một cách
phần Mã được diễn giải-- tức là, Macro PP được mở rộng và kết quả là
được hiểu là mã C. Mục đích của mã là đặt kích thước của một số kích thước
xuất hiện trong chữ ký. Phân bổ bộ nhớ và chuỗi vòng lặp, v.v. sẽ được thiết lập như
nếu thứ nguyên được tính toán đã xuất hiện trong chữ ký. Trong mã của bạn, trước tiên bạn tính toán
kích thước mong muốn của kích thước được đặt tên trong chữ ký theo nhu cầu của bạn và sau đó
gán giá trị đó cho nó thông qua $KÍCH CỠ() vĩ mô.

Ví dụ, hãy xem xét tình huống sau đây. Bạn đang giao tiếp với một thư viện bên ngoài
quy trình yêu cầu một mảng tạm thời cho không gian làm việc được chuyển dưới dạng đối số. Hai
mảng dữ liệu đầu vào được thông qua là p(m) và x (n). Mảng dữ liệu đầu ra là y (n). Các
quy trình yêu cầu một mảng không gian làm việc có độ dài n + m * m và bạn muốn lưu trữ
được tạo tự động giống như đối với bất kỳ trò chơi nào được gắn cờ [t] hoặc [o]. Gì
bạn muốn nói điều gì đó giống như

pp_def ("myexternalfunc",
Phân tích cú pháp => " p(m); x (n); [o] y; [t] việc (n + m * m); ", ...

nhưng điều đó sẽ không hiệu quả, bởi vì PP không thể giải thích các biểu thức bằng số học trong
Chữ ký. Thay vào đó bạn viết

pp_def ("myexternalfunc",
Phân tích cú pháp => " p(m); x (n); [o] y; [t] việc (wn); ",
RedoDimsCode => "
int im = $ PDL (p) -> dims [0];
int in = $ PDL (x) -> dims [0];
int min = trong + im * im;
int inw = $ PDL (công việc) -> dims [0];
$ SIZE (wn) = inw> = min? inw: tối thiểu; ",
Mã => "
externalfunc ($ P (p), $ P (x), $KÍCH THƯỚC(m), $ SIZE (n), $ P (công việc));
";)

Mã này hoạt động như sau: Macro $ PDL (p) mở rộng thành một con trỏ đến cấu trúc pdl cho
piddle p. Bạn không muốn một con trỏ đến dữ liệu (tức là $ P) trong trường hợp này, bởi vì bạn
muốn truy cập các phương thức cho piddle ở mức C. Bạn nhận được kích thước đầu tiên của
mỗi câu đố và lưu trữ chúng dưới dạng số nguyên. Sau đó, bạn tính độ dài tối thiểu
mảng công việc có thể được. Nếu người dùng đã gửi một "tác phẩm" piddle có đủ bộ nhớ, thì hãy để nó
một mình. Nếu người dùng đã gửi, giả sử pdl rỗng hoặc không có pdl nào, thì kích thước của wn sẽ là
XNUMX và bạn đặt lại nó về giá trị nhỏ nhất. Trước mã trong phần Mã là
PP được thực thi sẽ tạo ra bộ nhớ thích hợp cho "công việc" nếu nó không tồn tại. Lưu ý rằng bạn
chỉ lấy thứ nguyên đầu tiên của "p" và "x" vì người dùng có thể đã gửi các câu đố bằng
kích thước ren phụ. Tất nhiên, "công việc" tạm thời (lưu ý cờ [t])
không nên cung cấp bất kỳ kích thước luồng nào.

Bạn cũng có thể sử dụng "RedoDimsCode" để đặt thứ nguyên của một piddle được gắn cờ [o]. Trong này
trường hợp bạn đặt kích thước cho thứ nguyên được đặt tên trong chữ ký bằng cách sử dụng $KÍCH CỠ() như trong
ví dụ tiếp theo. Tuy nhiên, vì piddle được gắn cờ [o] thay vì [t],
kích thước ren sẽ được thêm vào nếu được yêu cầu giống như kích thước của kích thước
tính từ chữ ký theo các quy tắc thông thường. Đây là một ví dụ từ
PDL :: Toán học

pp_def ("nhiều đường",
Phân tích cú pháp => 'cr (n); ci (n); [o]rr(m); [o]ri(m); ',
RedoDimsCode => 'int sn = $ PDL (cr) -> dims [0]; $KÍCH THƯỚC(m) = sn-1; ',

Các piddles đầu vào là phần thực và phần ảo của các hệ số phức của một
đa thức. Các piddles đầu ra là các phần thực và ảo của rễ. Có "n"
căn đến đa thức bậc "n" và đa thức như vậy có hệ số "n + 1" (
zeoreth thông qua thứ "n"). Trong ví dụ này, phân luồng sẽ hoạt động chính xác. Đó là,
kích thước đầu tiên của piddle đầu ra với kích thước của nó được điều chỉnh, nhưng luồng khác
thứ nguyên sẽ được chỉ định như thể không có "RedoDimsCode".

Sơ đồ đánh máy xử lý in các "OtherPars" phần
Phần "OtherPars" được thảo luận ở trên thường rất quan trọng khi bạn
giao diện các thư viện bên ngoài với PDL. Tuy nhiên, trong nhiều trường hợp, các thư viện bên ngoài
sử dụng các kiểu dẫn xuất hoặc con trỏ của nhiều kiểu khác nhau.

Cách tiêu chuẩn để xử lý điều này trong Perl là sử dụng tệp "sơ đồ đánh máy". Điều này được thảo luận trong
một số chi tiết về perlx trong tài liệu Perl tiêu chuẩn. Trong PP, chức năng rất
tương tự, vì vậy bạn có thể tạo tệp "typemap" trong thư mục chứa tệp PP của bạn
và khi nó được xây dựng, nó sẽ tự động được đọc để tìm ra bản dịch thích hợp
giữa loại C và loại tích hợp của Perl.

Điều đó nói rằng, có một vài điểm khác biệt quan trọng so với việc xử lý chung các loại
trong XS. Điều đầu tiên, và có lẽ là quan trọng nhất, là tại thời điểm này, các con trỏ đến các loại là
không được phép trong phần "OtherPars". Để khắc phục hạn chế này, bạn phải sử dụng
Loại "IV" (cảm ơn Judd Taylor đã chỉ ra rằng điều này là cần thiết cho tính di động).

Có lẽ tốt nhất là minh họa điều này bằng một vài đoạn mã:

Ví dụ, hàm "gsl_spline_init" có khai báo C sau:

int gsl_spline_init (gsl_spline * spline,
const double xa [], const double ya [], size_t size);

Rõ ràng các mảng "xa" và "ya" là các ứng cử viên để được chuyển vào dưới dạng piddles và
đối số "size" chỉ là độ dài của các piddles này để có thể được xử lý bởi
Macro "$ SIZE ()" trong PP. Vấn đề là con trỏ đến loại "gsl_spline". Tự nhiên
giải pháp sẽ là viết một khai báo "OtherPars" của biểu mẫu

OtherPars => 'gsl_spline * spl'

và viết một tệp "sơ đồ đánh máy" ngắn xử lý loại này. Điều này không hoạt động hiện tại
Tuy nhiên! Vì vậy, những gì bạn phải làm là giải quyết vấn đề một chút (và theo một số cách
điều này cũng dễ dàng hơn!):

Giải pháp là khai báo "spline" trong phần "OtherPars" bằng cách sử dụng "Giá trị số nguyên",
"IV". Điều này ẩn bản chất của biến khỏi PP và sau đó bạn cần phải (tốt để tránh
ít nhất là cảnh báo trình biên dịch!) thực hiện kiểu ép kiểu khi bạn sử dụng biến trong mã của mình.
Do đó, "OtherPars" sẽ có dạng:

OtherPars => 'IV spl'

và khi bạn sử dụng nó trong mã, bạn sẽ viết

INT2PTR (gsl_spline *, $ COMP (spl))

trong đó macro Perl API "INT2PTR" đã được sử dụng để xử lý truyền con trỏ để tránh
cảnh báo và sự cố trình biên dịch đối với các máy có Perl 32bit và 64bit hỗn hợp
cấu hình. Kết hợp điều này lại với nhau như Andres Jordan đã làm (với sự sửa đổi
sử dụng "IV" của Judd Taylor) trong "gsl_interp.pd" trong nguồn phân phối mà bạn nhận được:

pp_def ('init_meat',
Phân tích cú pháp => 'double x (n); nhân đôi y (n); ',
OtherPars => 'IV spl',
Mã => '
gsl_spline_init, (INT2PTR (gsl_spline *, $ COMP (spl)), $ P (x), $ P (y), $ SIZE (n))); '
);

nơi tôi đã xóa lệnh gọi trình bao bọc macro, nhưng điều đó sẽ che khuất cuộc thảo luận.

Sự khác biệt nhỏ khác so với việc xử lý bản đồ chuẩn trong Perl, là
người dùng không thể chỉ định các vị trí bản đồ đánh máy không chuẩn hoặc tên tập tin bản đồ chính tả bằng cách sử dụng
Tùy chọn "TYPEMAPS" trong MakeMaker ... Vì vậy, bạn chỉ có thể sử dụng một tệp có tên "typemap" và / hoặc
Thủ thuật "IV" ở trên.

Nền tảng khác hữu ích PP phím in dữ liệu hoạt động các định nghĩa
Bạn đã nghe nói về khóa "OtherPars". Hiện tại, không có nhiều khóa khác
cho một hoạt động dữ liệu sẽ hữu ích trong lập trình PP bình thường (bất kể đó là gì). Trong
thực tế, sẽ rất thú vị khi nghe về một trường hợp mà bạn nghĩ rằng bạn cần nhiều hơn những gì
được cung cấp vào lúc này. Vui lòng lên tiếng về một trong các danh sách gửi thư PDL. Phần lớn khác
các khóa được "pp_def" nhận dạng chỉ thực sự hữu ích cho những gì chúng tôi gọi là lát hoạt động (xem
cũng ở trên).

Một điều đang được lên kế hoạch mạnh mẽ là số lượng đối số thay đổi, sẽ là
chút khôn lanh.

Danh sách không đầy đủ các khóa khả dụng:

Tại chỗ
Đặt phím này đánh dấu quy trình là hoạt động tại chỗ - tức là đầu vào và đầu ra
piddles cũng giống nhau. Một ví dụ là "$ a-> inplace-> sqrt ()" (hoặc "sqrt (inplace ($ a))").

Tại chỗ => 1
Sử dụng khi quy trình là một hàm đơn phân, chẳng hạn như "sqrt".

Tại chỗ => ['a']
Nếu có nhiều hơn một piddles đầu vào, hãy chỉ định tên của nó có thể là
đã thay đổi vị trí bằng cách sử dụng tham chiếu mảng.

Vào chỗ => ['a', 'b']
Nếu có nhiều hơn một chốt đầu ra, hãy chỉ định tên của chốt đầu vào và
xuất piddle trong tham chiếu mảng 2 phần tử. Điều này có thể không cần thiết, nhưng trái
trong cho sự hoàn chỉnh.

Nếu các giá trị xấu đang được sử dụng, phải cẩn thận để đảm bảo sự lan truyền của
badflag khi tại chỗ đang được sử dụng; coi đoạn trích này từ Basic / Bad / bad.pd:

pp_def ('Replacebad', HandleBad => 1,
Phân tích cú pháp => 'a (); [o] b (); ',
OtherPars => 'double newval',
Tại chỗ => 1,
CopyBadStatusCode =>
'/ * đề xuất badflag nếu ở vị trí VÀ nó đã thay đổi * /
if (a == b && $ ISPDLSTATEBAD (a))
PDL-> propogate_badflag (b, 0);

/ * luôn đảm bảo đầu ra là "tốt" * /
$ SETPDLSTATEGOOD (b);
',
...

Vì quy trình này loại bỏ tất cả các giá trị xấu, nên piddle đầu ra có cờ xấu
đã xóa. Nếu chạy tại chỗ (vì vậy "a == b"), thì chúng ta phải cho tất cả các con của "a"
rằng cờ xấu đã được xóa (để tiết kiệm thời gian, chúng tôi đảm bảo rằng chúng tôi gọi
"PDL-> propogate_badgflag" chỉ khi đầu vào piddle đã đặt cờ không hợp lệ).

LƯU Ý: một ý tưởng là tài liệu cho quy trình có thể tự động
được gắn cờ để chỉ ra rằng nó có thể được thực thi tại chỗ, tức là một cái gì đó tương tự như cách
"HandleBad" đặt "BadDoc" nếu nó không được cung cấp (đây không phải là giải pháp lý tưởng).

Nền tảng khác PDL :: PP chức năng đến hỗ trợ ngắn gọn gói định nghĩa
Cho đến nay, chúng tôi đã mô tả các hàm "pp_def" và "pp_done". PDL :: PP xuất khẩu một số
các chức năng khác để hỗ trợ bạn viết các định nghĩa gói mở rộng PDL ngắn gọn.

pp_addhdr

Thông thường, khi bạn giao diện các chức năng thư viện như trong ví dụ trên, bạn phải bao gồm
bổ sung C bao gồm các tệp. Vì tệp XS được tạo bằng PP, chúng tôi cần một số phương tiện để
làm cho PP chèn các chỉ thị bao gồm thích hợp vào đúng vị trí vào XS được tạo
tập tin. Cuối cùng, có hàm "pp_addhdr". Đây cũng là chức năng sử dụng
khi bạn muốn xác định một số hàm C để sử dụng nội bộ bởi một số hàm XS
(hầu hết là các hàm được định nghĩa bởi "pp_def"). Bằng cách đưa các chức năng này vào đây, bạn
đảm bảo rằng PDL :: PP chèn mã của bạn trước điểm mà mô-đun XS thực tế
phần bắt đầu và do đó sẽ không được xsubpp tác động đến (x. perlxperlxstut
trang người đàn ông).

Một cuộc gọi điển hình sẽ là

pp_addhdr ('
#bao gồm / * chúng tôi cần độ phân giải XXXX * /
#include "libprotos.h" / * nguyên mẫu của các hàm thư viện * /
#include "mylocaldecs.h" / * Decs cục bộ * /

static void do_the real_work (PDL_Byte * in, PDL_Byte * out, int n)
{
/ * thực hiện một số phép tính với dữ liệu * /
}
');

Điều này đảm bảo rằng tất cả các hằng số và nguyên mẫu bạn cần sẽ được đưa vào đúng cách và
mà bạn có thể sử dụng các hàm bên trong được định nghĩa tại đây trong s "pp_def", ví dụ:

pp_def ('barfoo',
Phân tích cú pháp => 'a (n); [o] b (n) ',
GenericTypes => ['B'],
Mã => 'int ns = $ SIZE (n);
do_the_real_work ($ P (a), $ P (b), ns);
',
);

pp_addpm

Trong nhiều trường hợp, mã PP thực tế (có nghĩa là các đối số cho lệnh gọi "pp_def") chỉ là một phần của
gói bạn hiện đang triển khai. Thường có thêm mã Perl và XS
mã mà bạn thường ghi vào các tệp pm và XS, hiện đang tự động
do PP tạo ra. Vậy làm cách nào để đưa nội dung này vào các tệp được tạo động đó?
May mắn thay, có một số hàm, thường được gọi là "pp_addXXX" hỗ trợ bạn
khi làm điều này.

Giả sử bạn có mã Perl bổ sung sẽ đi vào pm-tập tin. Điều này
có thể dễ dàng đạt được bằng lệnh "pp_addpm":

pp_addpm (<< 'EOD');

= head1 NAME

PDL :: Lib :: Mylib - một giao diện PDL cho thư viện Mylib

= head1 DESCRIPTION

Gói này thực hiện một giao diện cho gói Mylib với đầy đủ
hỗ trợ phân luồng và lập chỉ mục (xem L ).

= cắt

sử dụng PGPLOT;

= head2 use_myfunc
chức năng này áp dụng hoạt động myfunc cho tất cả
các phần tử của pdl đầu vào bất kể kích thước
và trả về tổng kết quả
= cắt

sử dụng phụ_myfunc {
của tôi $ pdl = shift;

myfunc ($ pdl-> clump (-1), ($ res = null));

trả về $ res-> sum;
}

DOE

pp_add_exported

Bạn có thể đã có ý tưởng. Trong một số trường hợp, bạn cũng muốn xuất phần bổ sung của mình
chức năng. Để tránh gặp rắc rối với PP vốn cũng gây rắc rối với @EXPORT
mảng bạn chỉ cần yêu cầu PP thêm các hàm của bạn vào danh sách các hàm đã xuất:

pp_add_exported ('use_myfunc gethynx');

pp_add_isa

Lệnh "pp_add_isa" hoạt động giống như hàm "pp_add_exported". Các đối số để
"pp_add_isa" được thêm vào danh sách @ISA, ví dụ:

pp_add_isa ('Some :: Other :: Class');

pp_may mắn

Nếu quy trình pp_def của bạn được sử dụng làm phương thức đối tượng, hãy sử dụng "pp_bless" để chỉ định
gói (tức là lớp) mà pp_defphương thức ed sẽ được thêm vào. Ví dụ,
"pp_bless ('PDL :: MyClass')". Giá trị mặc định là "PDL" nếu điều này bị bỏ qua.

pp_addxs

Đôi khi bạn muốn thêm mã XS bổ sung của riêng mình (thường không liên quan đến
bất kỳ vấn đề phân luồng / lập chỉ mục nào nhưng cung cấp một số chức năng khác mà bạn muốn truy cập
từ phía Perl) sang tệp XS được tạo, ví dụ:

pp_addxs ('', '

# Xác định độ bền của máy

int
isbigendian ()
Mã hàng:
không dấu i ngắn;
PDL_Byte * b;

i = 42; b = (PDL_Byte *) (void *) & i;

nếu (* b == 42)
TRẢ LẠI = 0;
khác nếu (* (b + 1) == 42)
TRẢ LẠI = 1;
khác
croak ("Không thể - máy không lớn cũng không nhỏ !! \ n");
ĐẦU RA:
TRUYỀN HÌNH LẠI
');

Đặc biệt "pp_add_exported" và "pp_addxs" nên được sử dụng cẩn thận. PP sử dụng
PDL :: Exporter, do đó để PP xuất chức năng của bạn có nghĩa là chúng được thêm vào
danh sách tiêu chuẩn của chức năng được xuất theo mặc định (danh sách được xác định bởi thẻ xuất
``: Hàm ''). Nếu bạn sử dụng "pp_addxs", bạn không nên cố gắng làm bất cứ điều gì liên quan đến luồng
hoặc lập chỉ mục trực tiếp. PP tốt hơn nhiều trong việc tạo mã thích hợp từ
các định nghĩa.

pp_add_boot

Cuối cùng, bạn có thể muốn thêm một số mã vào phần BOOT của tệp XS (nếu bạn không
biết kiểm tra đó là gì perlx). Điều này có thể dễ dàng thực hiện với lệnh "pp_add_boot":

pp_add_boot (<
descrip = mylib_initialize (KEEP_OPEN);

nếu (mô tả == NULL)
croak ("Không thể khởi tạo thư viện");

GlobalStruc-> descrip = mô tả;
GlobalStruc-> maxfiles = 200;
EOB

pp_export_nothing

Theo mặc định, PP.pm đặt tất cả các con được xác định bằng cách sử dụng hàm pp_def vào đầu ra .pm
danh sách XUẤT của tệp. Điều này có thể tạo ra sự cố nếu bạn đang tạo một đối tượng phân lớp ở đó
bạn không muốn xuất bất kỳ phương thức nào. (nghĩa là các phương thức sẽ chỉ được gọi bằng cách sử dụng
cú pháp phương thức $ object->).

Đối với những trường hợp này bạn có thể gọi pp_export_nothing () để xóa danh sách xuất. Ví dụ (Tại
cuối tệp .pd):

pp_export_nothing ();
pp_done ();

pp_core_importList

Theo mặc định, PP.pm đặt 'use Core;' dòng vào tệp .pm đầu ra. Điều này nhập khẩu Core's
đã xuất tên vào không gian tên hiện tại, điều này có thể tạo ra sự cố nếu bạn vượt quá
cưỡi một trong các phương thức của Core trong tệp hiện tại. Bạn sẽ nhận được những tin nhắn như
"Cảnh báo: sub sumover được xác định lại trong tệp subclass.pm" khi chạy chương trình.

Đối với những trường hợp này, pp_core_importList có thể được sử dụng để thay đổi những gì được nhập từ
Core.pm. Ví dụ:

pp_core_importList ('()')

Điều này sẽ dẫn đến

sử dụng Core ();

được tạo trong tệp .pm đầu ra. Điều này sẽ dẫn đến không có tên nào được nhập từ
Core.pm. Tương tự, gọi

pp_core_importList ('qw / barf /')

sẽ dẫn đến

sử dụng Core qw / barf /;

được tạo trong tệp .pm đầu ra. Điều này sẽ dẫn đến việc chỉ nhập 'barf'
từ Core.pm.

pp_setversion

Tôi khá chắc chắn rằng điều này cho phép bạn đặt đồng thời các tệp .pm và .xs '
phiên bản, do đó tránh được sự lệch phiên bản không cần thiết giữa hai phiên bản. Để sử dụng điều này, chỉ cần có
dòng sau tại một số điểm trong tệp .pd của bạn:

pp_setversion ('0.0.3');

Tuy nhiên, không sử dụng điều này nếu bạn sử dụng Module :: Build :: PDL. Xem tài liệu của mô-đun đó để biết
chi tiết.

pp_deprecate_module

Nếu một mô-đun cụ thể được coi là lỗi thời, thì chức năng này có thể được sử dụng để đánh dấu nó là
không dùng nữa. Điều này có tác dụng phát ra cảnh báo khi người dùng cố gắng "sử dụng"
mô-đun. POD được tạo cho mô-đun này cũng có thông báo ngừng sử dụng. Các
mô-đun thay thế có thể được chuyển như một đối số như sau:

pp_deprecate_module (infavor => "PDL :: NewNonDeprecatedModule");

Lưu ý rằng chức năng ảnh hưởng đến có thể cảnh báo thời gian chạy và POD.

Làm qua một vài thao tác đơn giản về PP chức năng "riêng"


Giả sử rằng bạn có một chức năng trong mô-đun của mình được gọi là PDL :: foo sử dụng PP
hàm "bar_pp" để nâng vật nặng. Nhưng bạn không muốn quảng cáo "bar_pp" đó
tồn tại. Để làm điều này, bạn phải di chuyển hàm PP lên đầu tệp mô-đun, sau đó
cuộc gọi

pp_export_nothing ()

để xóa danh sách "XUẤT". Để đảm bảo rằng không có tài liệu nào (ngay cả tài liệu PP mặc định)
tạo ra, thiết lập

Doc => undef

và để ngăn hàm được thêm vào bảng ký hiệu, hãy đặt

PMFunc => ''

trong khai báo pp_def của bạn (xem Image2D.pd để làm ví dụ). Điều này có hiệu quả sẽ làm cho
hàm PP của bạn "riêng tư". Tuy nhiên nó là luôn luôn có thể truy cập qua PDL :: bar_pp do Perl's
thiết kế mô-đun. Tuy nhiên, việc đặt nó ở chế độ riêng tư sẽ khiến người dùng bỏ rất xa
cách sử dụng nó, vì vậy anh ta hoặc cô ấy gánh vác hậu quả!

Slice hoạt động


Phần thao tác lát của sách hướng dẫn này được cung cấp bằng cách sử dụng luồng dữ liệu và đánh giá lười biếng:
khi cần thì nhờ Tjl viết hộ. giao hàng sau một tuần kể từ khi tôi nhận được email
có thể xảy ra 95% và khả năng giao hàng trong hai tuần là 99%.

Và dù sao đi nữa, các hoạt động của lát cắt đòi hỏi kiến ​​thức sâu sắc hơn nhiều về nội bộ PDL
hơn các hoạt động dữ liệu. Hơn nữa, sự phức tạp của các vấn đề liên quan là
cao hơn đáng kể so với hoạt động dữ liệu trung bình. Nếu bạn muốn thuyết phục
bản thân bạn về thực tế này, hãy nhìn vào Basic / Slices / slice.pd tệp trong PDL
phân bổ :-). Tuy nhiên, các chức năng được tạo bằng cách sử dụng các hoạt động lát cắt ở
trung tâm của khả năng thao tác chỉ mục và luồng dữ liệu của PDL.

Ngoài ra, có rất nhiều vấn đề bẩn thỉu với piddles và vaffines ảo mà chúng tôi sẽ
hoàn toàn bỏ qua ở đây.

Slices xấu giá trị
Các hoạt động Slice cần có khả năng xử lý các giá trị xấu (nếu hỗ trợ được biên dịch thành PDL).
Điều dễ dàng nhất để làm là nhìn vào Basic / Slices / slice.pd để xem cách này hoạt động như thế nào.

Cùng với "BadCode", còn có các khóa "BadBackCode" và "BadRedoDimsCode" cho
"pp_def". Tuy nhiên, bất kỳ "EquivCPOffsCode" nào cũng nên không cần thay đổi, vì bất kỳ thay đổi nào cũng
được đưa vào định nghĩa của macro "$ EQUIVCPOFFS ()" (tức là nó được xử lý
tự động bởi PDL :: PP>.

A vài ghi chú on viết a cắt lát lịch trình...
Một vài đoạn sau đây mô tả việc viết một quy trình cắt mới ('range'); bất kì
lỗi là của CED. (--CED ngày 26 tháng 2002 năm XNUMX)

Xử lý of "cảnh báo" "barf" in PP


Để in các thông báo cảnh báo hoặc hủy bỏ / chết, bạn có thể gọi "warning" hoặc "barf" từ PP
mã số. Tuy nhiên, bạn nên biết rằng những cuộc gọi này đã được xác định lại bằng cách sử dụng C
macro tiền xử lý thành "PDL-> barf" và "PDL-> warning". Những định nghĩa lại này được đưa ra để
giúp bạn không vô tình gọi trực tiếp "warning" hoặc "barf" của perl, điều này có thể gây ra
mặc định trong quá trình pthreading (tức là bộ xử lý đa luồng).

Các phiên bản riêng của PDL của "barf" và "warning" sẽ xếp hàng đợi cảnh báo hoặc thông báo barf cho đến sau
pthreading hoàn tất, và sau đó gọi các phiên bản perl của các quy trình này.

Xem PDL :: ParallelCPU để biết thêm thông tin về pthreading.

HỮU ÍCH TUYẾN


Cấu trúc PDL "Core", được định nghĩa trong Basic / Core / pdlcore.h.PL, chứa các con trỏ đến một
số lượng thói quen có thể hữu ích cho bạn. Phần lớn các thói quen này giải quyết
thao tác piddles, nhưng một số cách tổng quát hơn:

PDL-> qsort_B (PDL_Byte * xx, int a, int b)
Sắp xếp mảng "xx" giữa các chỉ số "a" và "b". Ngoài ra còn có các phiên bản cho
các kiểu dữ liệu PDL khác, với hậu tố "_S", "_U", "_L", "_F" và "_D". Bất kỳ mô-đun nào sử dụng
điều này phải đảm bảo rằng "PDL :: Ufunc" được tải.

PDL-> qsort_ind_B (PDL_Byte * xx, int * ix, int a, int b)
Đối với "PDL-> qsort_B", nhưng lần này sắp xếp các chỉ số chứ không phải dữ liệu.

Quy trình "med2d" trong Lib / Image2D / image2d.pd cho thấy cách các thói quen như vậy được sử dụng.

TỆP TẠO CHO PP CÁC TẬP TIN


Nếu bạn định tạo một gói từ tệp PP của mình (các phần mở rộng tệp điển hình là
".pd" hoặc ".pp" đối với các tệp có chứa mã PP), cách dễ nhất và an toàn nhất là bỏ đi
tạo các lệnh thích hợp cho Makefile. Sau đây chúng tôi sẽ phác thảo
định dạng điển hình của Perl Makefile để tự động xây dựng và cài đặt gói của bạn từ
một mô tả trong một tệp PP. Hầu hết các quy tắc để tạo xs, pm và các tệp bắt buộc khác
từ tệp PP đã được xác định trước trong gói PDL :: Core :: Dev. Chúng ta chỉ cần
yêu cầu MakeMaker sử dụng nó.

Trong hầu hết các trường hợp, bạn có thể xác định Makefile của mình như

# Makefile.PL cho một gói được xác định bởi mã PP.

sử dụng PDL :: Core :: Dev; # Đón đầu các tiện ích phát triển
sử dụng ExtUtils :: MakeMaker;

$ package = ["mylib.pd", Mylib, PDL :: Lib :: Mylib];
% hash = pdlpp_stdargs ($ gói);
$ băm {OBJECT}. = 'extra_Ccode $ (OBJ_EXT)';
$ hash {clean} -> {FILES}. = 'todelete_Ccode $ (OBJ_EXT)';
$ băm {'VERSION_FROM'} = 'mylib.pd';
WriteMakefile (% băm);

sub MY :: postamble {pdlpp_postamble ($ gói); }

Ở đây, danh sách trong gói $ là: đầu tiên: tên tệp nguồn PP, sau đó là tiền tố cho
các tệp được sản xuất và cuối cùng là toàn bộ tên gói. Bạn có thể sửa đổi hàm băm trong bất cứ điều gì
theo cách bạn muốn nhưng sẽ là hợp lý nếu ở trong một số giới hạn để gói hàng của bạn
sẽ tiếp tục hoạt động với các phiên bản sau của PDL.

Nếu bạn không muốn sử dụng các đối số đóng gói trước, đây là Makefile.PL cái đó bạn có thể
thích ứng với nhu cầu của riêng bạn:

# Makefile.PL cho một gói được xác định bởi mã PP.

sử dụng PDL :: Core :: Dev; # Đón đầu các tiện ích phát triển
sử dụng ExtUtils :: MakeMaker;

WriteMakefile (
'NAME' => 'PDL :: Lib :: Mylib',
'VERSION_FROM' => 'mylib.pd',
'TYPEMAPS' => [& PDL_TYPEMAP ()],
'OBJECT' => 'mylib $ (OBJ_EXT) add_Ccode $ (OBJ_EXT)',
'PM' => {'Mylib.pm' => '$ (INST_LIBDIR) /Mylib.pm'},
'INC' => & PDL_INCLUDE (), # add bao gồm dirs theo yêu cầu của lib của bạn
'LIBS' => [''], # thêm chỉ thị liên kết nếu cần
'sạch' => {'FILES' =>
'Mylib.pm Mylib.xs Mylib $ (OBJ_EXT)
add_Ccode $ (OBJ_EXT) '},
);

# Thêm quy tắc genpp; điều này sẽ gọi PDL :: PP trên tệp PP của chúng tôi
# đối số là một tham chiếu mảng trong đó mảng có ba phần tử chuỗi:
# arg1: tên của tệp nguồn chứa mã PP
# arg2: tên cơ sở của các tệp xs và pm sẽ được tạo
# arg3: tên của gói sẽ được tạo
sub MY :: postamble {pdlpp_postamble (["mylib.pd", Mylib, PDL :: Lib :: Mylib]); }

Để làm cho cuộc sống trở nên dễ dàng hơn, PDL :: Core :: Dev xác định hàm "pdlpp_stdargs" trả về
một hàm băm với các giá trị mặc định có thể được chuyển (trực tiếp hoặc sau khi thích hợp
sửa đổi) cho một cuộc gọi đến WriteMakefile. Hiện tại, "pdlpp_stdargs" trả về một hàm băm trong đó
các phím được điền như sau:

(
'NAME' => $ mod,
'TYPEMAPS' => [& PDL_TYPEMAP ()],
'OBJECT' => "$ pref \ $ (OBJ_EXT)",
PM => {"$ pref.pm" => "\ $ (INST_LIBDIR) / $ pref.pm"},
MAN3PODS => {"$ src" => "\ $ (INST_MAN3DIR) / $ mod. \ $ (MAN3EXT)"},
'INC' => & PDL_INCLUDE (),
'LIBS' => [''],
'clean' => {'FILES' => "$ pref.xs $ pref.pm $ pref \ $ (OBJ_EXT)"},
)

Ở đây, $ src là tên của tệp nguồn có mã PP, $ pref là tiền tố cho tệp được tạo
các tệp .pm và .xs và $ mod tên của mô-đun mở rộng cần tạo.

NỘI BỘ


Nội bộ của phiên bản hiện tại bao gồm một bảng lớn cung cấp các quy tắc
theo những thứ nào được dịch và các phụ thực hiện các quy tắc này.

Sau này, sẽ rất tốt nếu người dùng có thể sửa đổi bảng sao cho khác
những thứ có thể được thử.

[Nhận xét meta: ở đây hy vọng sẽ có nhiều hơn trong tương lai; hiện tại, đặt cược tốt nhất của bạn sẽ là
để đọc mã nguồn :-( hoặc hỏi trong danh sách (thử cái sau trước)]

Phụ lục A: Một số phím được công nhận by PDL :: PP


Trừ khi được chỉ định khác, các đối số là chuỗi. Các phím được đánh dấu bằng (xấu) chỉ là
được sử dụng nếu hỗ trợ giá trị xấu được biên dịch thành PDL.

Pars
xác định chữ ký của chức năng của bạn

KhácPars
đối số không phải là pdls. Mặc định: không có gì. Đây là danh sách được phân tách bằng dấu chấm phẩy về
các đối số, ví dụ: "OtherPars => 'int k; double value; char * fd'". Xem $ COMP (x) và cả
mục tương tự trong Phụ lục B.


mã thực tế triển khai chức năng; một số macro PP và các hàm PP
được công nhận trong giá trị chuỗi

HandleBad (xấu)
Nếu được đặt thành 1, quy trình được giả định là hỗ trợ các giá trị xấu và mã trong BadCode
key được sử dụng nếu có giá trị xấu; nó cũng thiết lập mọi thứ để "$ ISBAD ()"
vv có thể sử dụng macro. Nếu được đặt thành 0, hãy làm cho quy trình in cảnh báo nếu có
các piddles đầu vào có bộ cờ xấu của chúng.

BadCode (xấu)
Cung cấp mã sẽ được sử dụng nếu các giá trị xấu có thể xuất hiện trong các piddles đầu vào. Chỉ được sử dụng
nếu "HandleBad => 1".

Loại chung
Một tham chiếu mảng. Mảng có thể chứa bất kỳ tập hợp con nào của các chuỗi một ký tự `B ',
`S ',` U', `L ',` Q', `F 'và` D', chỉ định kiểu thao tác của bạn sẽ chấp nhận.
Ý nghĩa của mỗi loại là:

B - byte có dấu (tức là ký tự có dấu)
S - ký tự ngắn (số nguyên hai byte)
U - viết tắt không dấu
L - dài có dấu (số nguyên bốn byte, int trên hệ thống 32 bit)
Q - dài dài có dấu (số nguyên tám byte)
F - phao
D - đôi

Điều này rất hữu ích (và quan trọng!) Khi giao tiếp với một thư viện bên ngoài. Vỡ nợ:
[qw / BSULQFD /]

Tại chỗ
Đánh dấu một chức năng là có thể hoạt động tại chỗ.

Inplace => 1 if Pars => 'a (); [o] b (); '
Inplace => ['a'] if Phân tích cú pháp => 'a (); b (); [o] c (); '
Inplace => ['a', 'b'] if Phân tích cú pháp => 'a (); b (); [o] c (); [o] d (); '

Nếu các giá trị xấu đang được sử dụng, phải cẩn thận để đảm bảo sự lan truyền của
badflag khi tại chỗ đang được sử dụng; ví dụ: xem mã cho "Replacebad" trong
Basic / Bad / bad.pd.

Doc Được sử dụng để chỉ định một chuỗi tài liệu ở định dạng Pod. Xem PDL :: Doc để biết thông tin về
Quy ước tài liệu PDL. Lưu ý: trong trường hợp đặc biệt khi chuỗi PP 'Doc' là
một dòng này hoàn toàn được sử dụng để tham khảo nhanh VÀ tài liệu!

Nếu trường Tài liệu bị bỏ qua, PP sẽ tạo tài liệu mặc định (sau tất cả những gì nó biết
về Chữ ký).

Nếu bạn thực sự muốn hàm KHÔNG được ghi lại theo bất kỳ cách nào tại thời điểm này (ví dụ:
cho một quy trình nội bộ hoặc vì bạn đang thực hiện nó ở nơi khác trong mã) một cách rõ ràng
chỉ định "Doc => undef".

BadDoc (xấu)
Chứa văn bản được trả về bởi lệnh "badinfo" (trong "perldl") hoặc công tắc "-b"
sang tập lệnh shell "pdldoc". Trong nhiều trường hợp, bạn sẽ không cần chỉ định điều này, vì
thông tin có thể được tạo tự động bởi PDL :: PP. Tuy nhiên, vì lợi ích của máy tính-
văn bản được tạo ra, nó khá cứng; nó có thể tốt hơn nhiều để làm điều đó cho mình!

KhôngPthread
Cờ tùy chọn để chỉ ra chức năng PDL nên không sử dụng các luồng xử lý (tức là
luồng pthreads hoặc POSIX) để phân chia công việc trên nhiều lõi CPU khác nhau. Tùy chọn này là
thường được đặt thành 1 nếu hàm PDL bên dưới không an toàn cho luồng. Nếu tùy chọn này
không có mặt, thì hàm được giả định là threadsafe. Tùy chọn này chỉ áp dụng
nếu PDL đã được biên dịch với các luồng POSIX được kích hoạt.

mã PM
Các hàm PDL cho phép bạn chuyển một thao tác khó mà bạn muốn lưu đầu ra. Điều này
rất tiện dụng bởi vì bạn có thể phân bổ một piddle đầu ra một lần và sử dụng lại nó nhiều lần; các
phương pháp thay thế sẽ là PDL tạo ra một công cụ mới mỗi lần, điều này có thể lãng phí tính toán
chu kỳ hoặc nhiều khả năng là RAM. Tính linh hoạt bổ sung này đi kèm với chi phí nhiều hơn
độ phức tạp: PDL :: PP phải viết các hàm đủ thông minh để đếm
các đối số được chuyển tới nó và tạo các piddles mới ngay lập tức, nhưng chỉ khi bạn muốn chúng.

PDL :: PP đủ thông minh để làm điều đó, nhưng có những hạn chế về thứ tự đối số và
như thế. Nếu bạn muốn một hàm linh hoạt hơn, bạn có thể viết Perl-side của riêng mình
trình bao bọc và chỉ định nó trong khóa PMCode. Chuỗi mà bạn cung cấp phải (nên)
xác định một hàm Perl với một tên phù hợp với những gì bạn đã đặt cho pp_def trong lần đầu tiên
địa điểm. Khi cuối cùng bạn muốn gọi hàm do PP tạo, bạn sẽ cần
cung cấp tất cả các piddles theo thứ tự chính xác được chỉ định trong chữ ký: piddles đầu ra là
không phải là tùy chọn và hàm do PP tạo sẽ không trả về bất kỳ thứ gì. Sự khó hiểu
tên mà bạn sẽ gọi là _ _ gợi ý.

Tôi tin rằng tài liệu này cần được làm rõ thêm, nhưng điều này sẽ phải làm.
:-(

PMFunc
Khi pp_def tạo ra các hàm, nó thường định nghĩa chúng trong gói PDL. Sau đó,
trong tệp .pm mà nó tạo cho mô-đun của bạn, nó thường thêm một dòng
về cơ bản sao chép chức năng đó vào bảng ký hiệu gói hiện tại của bạn với mã
trông như thế này:

* func_name = \ & PDL :: func_name;

Nó thông minh hơn một chút (nó biết khi nào nên bọc loại thứ đó trong một
Ví dụ: khối BEGIN và nếu bạn chỉ định một cái gì đó khác cho pp_bless), nhưng
đó là ý chính của nó. Nếu bạn không muốn nhập hàm vào hiện tại của mình
bảng ký hiệu của gói, bạn có thể chỉ định

PMFunc => '',

PMFunc không có tác dụng phụ nào khác, vì vậy bạn có thể sử dụng nó để chèn mã Perl tùy ý
vào mô-đun của bạn nếu bạn thích. Tuy nhiên, bạn nên sử dụng pp_addpm nếu bạn muốn thêm Perl
mã cho mô-đun của bạn.

Phụ lục B: PP macro chức năng


Macros
Các macro có nhãn (xấu) chỉ được sử dụng nếu hỗ trợ giá trị xấu được biên dịch thành PDL.

$tên_biến_từ_sig()
truy cập một pdl (theo tên của nó) đã được chỉ định trong chữ ký

$ COMP (x)
truy cập một giá trị trong cấu trúc dữ liệu riêng tư của chuyển đổi này (chủ yếu được sử dụng để
sử dụng một đối số được chỉ định trong phần "OtherPars")

$ SIZE (n)
được thay thế trong thời gian chạy bằng kích thước thực của một tên kích thước (như được chỉ định trong
chữ ký)

$CHUNG()
được thay thế bằng kiểu C tương đương với kiểu thời gian chạy của hoạt động

$ P (a) một con trỏ truy cập đến PDL có tên "a" trong chữ ký. Hữu ích để giao tiếp với C
chức năng

$ PP (a) một truy cập con trỏ vật lý tới pdl "a"; chủ yếu để sử dụng nội bộ

$ TXXX (Thay thế, Thay thế)
các lựa chọn thay thế mở rộng theo loại hoạt động thời gian chạy, trong đó XXX là một số
chuỗi được so khớp bởi "/ [BSULFD +] /".

$ PDL (a)
trả về một con trỏ đến cấu trúc dữ liệu pdl (pdl *) của piddle "a"

$ ISBAD (a ()) (xấu)
trả về true nếu giá trị được lưu trữ trong "a ()" bằng với giá trị không hợp lệ của piddle này.
Yêu cầu "HandleBad" được đặt thành 1.

$ ISGOOD (a ()) (xấu)
trả về true nếu giá trị được lưu trữ trong "a ()" không bằng giá trị xấu của giá trị này
chăm. Yêu cầu "HandleBad" được đặt thành 1.

$ SETBAD (a ()) (xấu)
Đặt "a ()" để bằng giá trị xấu cho piddle này. Yêu cầu "HandleBad" được đặt
để 1.

chức năng
"vòng lặp (DIMS)% {...%}"
lặp qua các thứ nguyên được đặt tên; giới hạn được tạo tự động bởi PP

"threadloop% {...%}"
bao gồm mã sau trong một vòng lặp chuỗi

"loại (TYPES)% {...%}"
thực thi mã sau nếu loại hoạt động là bất kỳ "TYPES" nào

Phụ lục C: Chức năng nhập khẩu by PDL :: PP


Một số hàm được nhập khi bạn "sử dụng PDL :: PP". Chúng bao gồm các chức năng
kiểm soát mã C hoặc XS được tạo, các chức năng kiểm soát mã Perl được tạo và
các hàm thao tác với các gói và bảng ký hiệu mà mã được tạo ra.

Tạo C XS
Mục đích chính của PDL :: PP là giúp bạn dễ dàng quấn công cụ luồng xung quanh
riêng mã C, nhưng bạn cũng có thể làm một số việc khác.

pp_def
Được sử dụng để quấn công cụ phân luồng xung quanh mã C của bạn. Hầu như tất cả tài liệu này
thảo luận về việc sử dụng pp_def.

pp_done
Cho biết bạn đã hoàn thành với PDL :: PP và nó sẽ tạo ra các tệp .xs và .pm
dựa trên các hàm pp_ * khác mà bạn đã gọi. Chức năng này không có
lập luận.

pp_addxs
Điều này cho phép bạn thêm mã XS vào tệp .xs của mình. Điều này rất hữu ích nếu bạn muốn tạo Perl-
các hàm có thể truy cập gọi mã C nhưng không thể hoặc không nên gọi luồng
động cơ. XS là phương tiện tiêu chuẩn mà bạn bọc mã C có thể truy cập Perl. Bạn có thể
tìm hiểu thêm tại perlxs.

pp_add_boot
Hàm này thêm bất kỳ chuỗi nào bạn chuyển vào phần XS BOOT. Phần BOOT
là mã C được Perl gọi khi mô-đun của bạn được tải và hữu ích cho
khởi tạo tự động. Bạn có thể tìm hiểu thêm về XS và phần BOOT tại perlxs.

pp_addhdr
Thêm mã pure-C vào tệp XS của bạn. Tệp XS được cấu trúc sao cho mã C thuần túy phải
đến trước thông số kỹ thuật XS. Điều này cho phép bạn chỉ định mã C như vậy.

pp_boundscheck
PDL thường kiểm tra giới hạn truy cập của bạn trước khi thực hiện chúng. Bạn có thể biến điều đó
bật hoặc tắt trong thời gian chạy bằng cách đặt MyPackage :: set_boundscheck. Chức năng này cho phép bạn
để loại bỏ tính linh hoạt trong thời gian chạy đó và không bao giờ kiểm tra giới hạn. Nó cũng trả về
trạng thái kiểm tra giới hạn hiện tại nếu được gọi mà không có bất kỳ đối số nào.

LƯU Ý: Tôi không tìm thấy bất cứ điều gì về việc kiểm tra giới hạn trong tài liệu khác. Điều đó
cần được giải quyết.

Tạo Perl
Nhiều hàm được nhập khi bạn sử dụng PDL :: PP cho phép bạn sửa đổi nội dung của
tệp .pm được tạo. Ngoài pp_def và pp_done, vai trò của các hàm này là
chủ yếu để thêm mã vào các phần khác nhau của tệp .pm đã tạo của bạn.

pp_addpm
Thêm mã Perl vào tệp .pm được tạo. PDL :: PP thực sự theo dõi ba
các phần khác nhau của mã được tạo: Trên cùng, Giữa và Dưới cùng. Bạn có thể thêm
Perl mã đến phần Giữa bằng cách sử dụng biểu mẫu một đối số, trong đó đối số là
Mã Perl bạn muốn cung cấp. Ở dạng hai đối số, đối số đầu tiên là một
hàm băm ẩn danh chỉ với một khóa chỉ định vị trí đặt đối số thứ hai,
là chuỗi mà bạn muốn thêm vào tệp .pm. Hàm băm là một trong những
ba:

{At => 'Top'}
{Tại => 'Giữa'}
{At => 'Bot'}

Ví dụ:

pp_addpm ({At => 'Bot'}, <

= head1 Một số tài liệu

Tôi biết tôi đang nhập cái này ở giữa tệp của mình, nhưng nó sẽ xuất hiện lúc
dưới cùng.

= cắt

POD

Cảnh báo: Nếu, ở giữa tệp .pd, bạn đặt tài liệu dành cho
dưới cùng của nhóm của bạn, bạn sẽ hoàn toàn nhầm lẫn CPAN. Mặt khác, nếu trong
giữa tệp .pd của bạn, bạn thêm một số mã Perl dành cho cuối hoặc trên cùng của
.pm tệp, bạn chỉ có mình mình để nhầm lẫn. :-)

pp_beginwrap
Thêm gói BEGIN-block. Tuy nhiên, một số khai báo nhất định có thể được bao bọc trong các khối BEGIN
hành vi mặc định là không có gói như vậy.

pp_addbắt đầu
Đặt mã được thêm vào đầu tệp .pm của bạn, ngay cả trên mã mà bạn chỉ định
với "pp_addpm ({At => 'Top'}, ...)". Không giống như pp_addpm, việc gọi này sẽ ghi đè lên bất cứ điều gì
đã có trước đây. Nói chung, bạn có thể không nên sử dụng nó.

Theo dõi Dòng Số
Khi bạn gặp lỗi biên dịch, từ mã C-like hoặc mã Perl của bạn, nó có thể giúp
để đưa những lỗi đó trở lại số dòng trong tệp nguồn mà tại đó lỗi
xảy ra.

pp_line_numbers
Lấy một số dòng và một chuỗi mã (thường dài). Số dòng phải
cho biết dòng bắt đầu trích dẫn. Đây thường là "__LINE__" của Perl
theo nghĩa đen, trừ khi bạn đang sử dụng heredocs, trong trường hợp đó nó là "__LINE__ + 1". Các
chuỗi trả về có các chỉ thị # dòng xen kẽ để giúp trình biên dịch báo lỗi
trên dòng thích hợp.

Sửa đổi các Bàn Xuất khẩu Hành vi
PDL :: PP thường xuất tất cả các hàm được tạo bằng pp_def và thường cài đặt chúng
vào bảng ký hiệu PDL. Tuy nhiên, bạn có thể sửa đổi hành vi này với các chức năng này.

pp_may mắn
Đặt gói (bảng ký hiệu) mà mã XS được thêm vào. Mặc định là PDL,
mà nói chung là những gì bạn muốn. Nếu bạn sử dụng phước lành mặc định và bạn tạo
hàm myfunc, sau đó bạn có thể làm như sau:

$ piddle-> myfunc ( );
PDL :: myfunc ($ piddle, );

Mặt khác, nếu bạn phù hợp với các chức năng của mình vào một gói khác, bạn không thể gọi
chúng dưới dạng các phương thức PDL và phải gọi chúng dưới dạng:

MyPackage :: myfunc ($ piddle, );

Tất nhiên, bạn luôn có thể sử dụng phím PMFunc để thêm chức năng của mình vào biểu tượng PDL
bàn, nhưng tại sao lại làm như vậy?

pp_add_isa
Thêm vào danh sách các mô-đun mà từ đó mô-đun kế thừa. Danh sách mặc định là

qw (PDL :: Exporter DynaLoader)

pp_core_importlist
Ở đầu tệp .pm đã tạo của bạn là một dòng giống như sau:

sử dụng PDL :: Core;

Bạn có thể sửa đổi điều đó bằng cách chỉ định một chuỗi thành pp_core_importlist. Ví dụ,

pp_core_importlist (':: Blarg');

sẽ cho kết quả

sử dụng PDL :: Core :: Blarg;

Ví dụ, bạn có thể sử dụng điều này để thêm danh sách các ký hiệu cần nhập từ PDL :: Core. Vì
thí dụ:

pp_core_importlist ("': Internal'");

sẽ dẫn đến câu lệnh sử dụng sau:

sử dụng PDL :: Core ': Internal';

pp_setversion
Đặt phiên bản mô-đun của bạn. Phiên bản phải nhất quán giữa .xs và .pm
và được sử dụng để đảm bảo rằng các thư viện Perl của bạn không bị phiên bản
nghiêng.

pp_add_exported
Thêm vào danh sách xuất bất kỳ tên nào bạn đặt cho nó. Các hàm được tạo bằng pp_def
được tự động thêm vào danh sách. Hàm này rất hữu ích nếu bạn xác định bất kỳ Perl nào
các hàm sử dụng pp_addpm hoặc pp_addxs mà bạn cũng muốn xuất.

pp_export_nothing
Điều này đặt lại danh sách các biểu tượng đã xuất thành không có gì. Cái này có lẽ được gọi là tốt hơn
"pp_export_clear", vì bạn có thể thêm các ký hiệu đã xuất sau khi gọi
"pp_export_nothing". Khi được gọi ngay trước khi gọi pp_done, điều này đảm bảo rằng
mô-đun không xuất bất kỳ thứ gì, ví dụ: nếu bạn chỉ muốn các lập trình viên sử dụng
các chức năng như các phương thức.

Sử dụng PDL :: PPp trực tuyến bằng các dịch vụ onworks.net


Máy chủ & Máy trạm miễn phí

Tải xuống ứng dụng Windows & Linux

  • 1
    góifilemanager
    góifilemanager
    Đây là trình quản lý tệp gói Total War
    dự án, bắt đầu từ phiên bản 1.7. Một
    giới thiệu ngắn về Warscape
    mod: ...
    Tải xuống packfilemanager
  • 2
    IPerf2
    IPerf2
    Một công cụ lưu lượng mạng để đo lường
    Hiệu suất TCP và UDP với các chỉ số
    xung quanh cả thông lượng và độ trễ. Các
    các mục tiêu bao gồm duy trì một hoạt động
    cá tuyết iperf ...
    Tải xuống IPerf2
  • 3
    fre: ac - công cụ chuyển đổi âm thanh miễn phí
    fre: ac - công cụ chuyển đổi âm thanh miễn phí
    fre:ac là một công cụ chuyển đổi âm thanh và đĩa CD miễn phí
    trình trích xuất cho các định dạng và bộ mã hóa khác nhau.
    Nó có tính năng MP3, MP4/M4A, WMA, Ogg
    Định dạng Vorbis, FLAC, AAC và Bonk
    ủng hộ, ...
    Tải xuống fre:ac - trình chuyển đổi âm thanh miễn phí
  • 4
    Matplotlib
    Matplotlib
    Matplotlib là một thư viện toàn diện
    để tạo tĩnh, động và
    trực quan hóa tương tác bằng Python.
    Matplotlib giúp mọi thứ trở nên dễ dàng và
    điều khó ...
    Tải xuống Matplotlib
  • 5
    người máy
    người máy
    Viết logic chatbot của bạn một lần và
    kết nối nó với một trong những cái có sẵn
    dịch vụ nhắn tin, bao gồm cả Amazon
    Alexa, Facebook Messenger, Slack,
    Telegram hoặc thậm chí yo ...
    Tải xuống BotMan
  • 6
    Joplin
    Joplin
    Joplin là một mã nguồn mở và miễn phí
    ứng dụng ghi chú và việc cần làm
    có thể xử lý một số lượng lớn các ghi chú trong
    Đánh dấu định dạng, sắp xếp chúng thành
    sổ ghi chép và ...
    Tải xuống Joplin
  • Khác »

Lệnh Linux

Ad