簡體   English   中英

Prolog是否有像Haskell這樣的別名“運算符”?

[英]Does Prolog have an alias “operator” like Haskell?

在Haskell中,有一種稱為“as”-operator的語言特性(有時稱為別名)。 這個想法如下:假設您有一個函數,例如將列表作為輸入並希望返回所有尾部,您可以將其實現為:

tails a@(_:xs) = a : tails xs
tails [] = [[]]

@確保您既可以引用整個參數,也可以引用參數結構的某些部分。 這是智能性能(它更像是性能破解,因為在第一行的主體中重構數組(x:xs) ),如果沒有被編譯器優化,將導致分配新對象,修改字段等。有關更多信息,請參見此處

我想知道Prolog是否有相同的東西:例如,如果你想在Prolog中實現尾部,可以通過以下方式完成:

tails([H|T],[[H|T]|TA]) :-
    tails(T,TA).
tails([],[[]]).

但如果有一個“as”運算符,它可能會更有效:

tails(L@[_|T],[L|TA]) :-  %This does not compile
    tails(T,TA).
tails([],[[]]).

有沒有這樣的結構或語言擴展?

TL; DR:好主意1 加速似乎限制在約20%(對於大多數列表大小)。

在這個答案中,我們比較了三個不同的謂詞,它們在@ -like數據重用方面有所不同:

list_tails([], [[]]).                % (1) like `tails/2` given by the OP ...
list_tails([E|Es], [[E|Es]|Ess]) :-  %     ....... but with a better name :-)
   list_tails(Es, Ess).

list_sfxs1(Es, [Es|Ess]) :-          % (2) "re-use, mutual recursion"
   aux_list_sfxs1(Es, Ess).          %     "sfxs" is short for "suffixes"

aux_list_sfxs1([], []).
aux_list_sfxs1([_|Es], Ess) :-
   list_sfxs1(Es, Ess).

list_sfxs2([], [[]]).                % (3) "re-use, direct recursion"
list_sfxs2(Es0, [Es0|Ess]) :-
   Es0 = [_|Es],
   list_sfxs2(Es, Ess).

要測量運行時,我們使用以下代碼:

:-( dif(D,sicstus), current_prolog_flag(dialect,D)
  ; use_module(library(between))
  ).

run_benchs(P_2s, P_2, L, N, T_ms) :-
   between(1, 6, I),
   L is 10^I,
   N is 10^(8-I),
   length(Xs, L),
   member(P_2, P_2s),
   garbage_collect,
   call_walltime(run_bench_core(P_2,Xs,N), T_ms).

run_bench_core(P_2, Xs, N) :-
   between(1, N, _),
   call(P_2, Xs, _),
   false.
run_bench_core(_, _, _).

為了測量 2,我們利用call_ walltime /2 2的變異-a call_time/2

call_walltime(G, T_ms) :-
   statistics(walltime, [T0|_]),
   G,
   statistics(walltime, [T1|_]),
   T_ms is T1 - T0.

讓我們將上面的代碼變體放到測試中......

  • ...使用不同的列表長度L ...
  • ...並且每次測試運行N次(為了更好的准確性)。

首先,我們使用版本7.3.14(64位):

?- run_benchs([list_sfxs1,list_sfxs2,list_tails], P_2, L, N, T_ms).
   P_2 = list_sfxs1, L*N = 10*10000000, T_ms =  7925
;  P_2 = list_sfxs2, L*N = 10*10000000, T_ms =  7524
;  P_2 = list_tails, L*N = 10*10000000, T_ms =  6936
;
   P_2 = list_sfxs1, L*N = 100*1000000, T_ms =  6502
;  P_2 = list_sfxs2, L*N = 100*1000000, T_ms =  5861
;  P_2 = list_tails, L*N = 100*1000000, T_ms =  5618
;
   P_2 = list_sfxs1, L*N = 1000*100000, T_ms =  6434
;  P_2 = list_sfxs2, L*N = 1000*100000, T_ms =  5817
;  P_2 = list_tails, L*N = 1000*100000, T_ms =  9916
;
   P_2 = list_sfxs1, L*N = 10000*10000, T_ms =  6328
;  P_2 = list_sfxs2, L*N = 10000*10000, T_ms =  5688
;  P_2 = list_tails, L*N = 10000*10000, T_ms =  9442
;
   P_2 = list_sfxs1, L*N = 100000*1000, T_ms = 10255
;  P_2 = list_sfxs2, L*N = 100000*1000, T_ms = 10296
;  P_2 = list_tails, L*N = 100000*1000, T_ms = 14592
;
   P_2 = list_sfxs1, L*N = 1000000*100, T_ms =  6955
;  P_2 = list_sfxs2, L*N = 1000000*100, T_ms =  6534
;  P_2 = list_tails, L*N = 1000000*100, T_ms =  9738.

然后,我們使用版本4.3.2(64位)重復上一個查詢3

?- run_benchs([list_sfxs1,list_sfxs2,list_tails], P_2, L, N, T_ms).
   P_2 = list_sfxs1, L*N = 10*10000000, T_ms =  1580
;  P_2 = list_sfxs2, L*N = 10*10000000, T_ms =  1610
;  P_2 = list_tails, L*N = 10*10000000, T_ms =  1580
;
   P_2 = list_sfxs1, L*N = 100*1000000, T_ms =   710
;  P_2 = list_sfxs2, L*N = 100*1000000, T_ms =   750
;  P_2 = list_tails, L*N = 100*1000000, T_ms =   840
;
   P_2 = list_sfxs1, L*N = 1000*100000, T_ms =   650 
;  P_2 = list_sfxs2, L*N = 1000*100000, T_ms =   660
;  P_2 = list_tails, L*N = 1000*100000, T_ms =   740
;  
   P_2 = list_sfxs1, L*N = 10000*10000, T_ms =   620
;  P_2 = list_sfxs2, L*N = 10000*10000, T_ms =   650
;  P_2 = list_tails, L*N = 10000*10000, T_ms =   740
;
   P_2 = list_sfxs1, L*N = 100000*1000, T_ms =   670
;  P_2 = list_sfxs2, L*N = 100000*1000, T_ms =   650
;  P_2 = list_tails, L*N = 100000*1000, T_ms =   750
;
   P_2 = list_sfxs1, L*N = 1000000*100, T_ms = 12610
;  P_2 = list_sfxs2, L*N = 1000000*100, T_ms = 12560
;  P_2 = list_tails, L*N = 1000000*100, T_ms = 33460.

摘要:

  • 別名可以並且確實顯着提高了性能
  • 在上面的測試中,與SWI-Prolog相比,SICStus Prolog 4的 速度提高10倍

腳注1:為什么把(@)/2放在規則頭上的噱頭? 最終得到非慣用的 Prolog代碼?
腳注2:我們對總運行時間感興趣。 為什么? 因為垃圾收集成本顯示更大的數據量!
腳注3:為了便於閱讀,答案序列已經過后處理。
腳注4:4.3.0版以來可用。 目前的目標架構包括IA-32AMD64

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM