Không có gì bí ẩn trong mô hình thực hiện của Pharo. Đoạn đệ quy
^ self * (self - 1) factorial
điều đó xảy ra bên trong thứ hai ifTrue:
biên dịch với trình tự sau đây của bytecode:
39 <70> self ; receiver of outer message *
40 <70> self ; receiver of inner message -
41 <76> pushConstant: 1 ; argument of self - 1
42 <B1> send: - ; subtract
43 <D0> send: factorial ; send factorial (nothing special here!)
44 <B8> send: * ; multiply
45 <7C> returnTop ; return
Lưu ý rằng trong dòng 43 có gì đặc biệt xảy ra. Mã chỉ gửi factorial
theo cách tương tự, có bộ chọn là bất kỳ mã nào khác. Đặc biệt, chúng ta có thể thấy rằng không có thao tác đặc biệt nào của ngăn xếp ở đây.
Điều này không có nghĩa là không thể tối ưu hóa trong mã gốc cơ bản. Nhưng đó là một cuộc thảo luận khác. Đó là việc thực hiện mô hình là vấn đề quan trọng đối với lập trình viên bởi vì bất kỳ tối ưu hóa nào bên dưới bytecode đều có nghĩa là hỗ trợ mô hình này ở cấp độ khái niệm.
CẬP NHẬT
Điều thú vị là phiên bản không đệ quy
factorial2
| f |
f := 1.
2 to: self do: [:i | f := f * i].
^f
là một chút chậm mà một trong những đệ quy (Pharo). Lý do phải là chi phí liên quan đến việc tăng i
lớn hơn một chút so với cơ chế gửi đệ quy.
Dưới đây là những biểu hiện tôi đã cố gắng:
[25000 factorial] timeToRun
[25000 factorial2] timeToRun
Nguồn
2016-05-07 15:51:04
Bạn _could_ chỉ cần đặt điểm ngắt trong trường hợp 'ifTrue:' đầu tiên và chỉ đếm số lần cùng một phương thức trên ngăn xếp ... ;-) –