패턴 매칭은지도 조회와 같은 O(log(n))
시간에 발생합니다.
는 컴파일 된 어셈블리 코드는이 정수의 인수에 이진 검색을하고
.text
.align 4,0x90
.long _F_f_srt-(_sl8_info)+0
.long 0
.long 65568
_sl8_info:
.Lcma:
movl 3(%esi),%eax
cmpl $4,%eax
jl .Lcmq
cmpl $6,%eax
jl .Lcmi
cmpl $7,%eax
jl .Lcme
cmpl $7,%eax
jne .Lcmc
movl $_ghczmprim_GHCziCString_unpackCStringzh_closure,%esi
movl $_cm7_str,0(%ebp)
jmp _stg_ap_n_fast
.Lcmc:
movl $_ghczmprim_GHCziCString_unpackCStringzh_closure,%esi
movl $_clB_str,0(%ebp)
jmp _stg_ap_n_fast
.Lcme:
cmpl $6,%eax
jne .Lcmc
movl $_ghczmprim_GHCziCString_unpackCStringzh_closure,%esi
movl $_cm3_str,0(%ebp)
jmp _stg_ap_n_fast
.Lcmg:
cmpl $4,%eax
jne .Lcmc
movl $_ghczmprim_GHCziCString_unpackCStringzh_closure,%esi
movl $_clV_str,0(%ebp)
jmp _stg_ap_n_fast
.Lcmi:
cmpl $5,%eax
jl .Lcmg
cmpl $5,%eax
jne .Lcmc
movl $_ghczmprim_GHCziCString_unpackCStringzh_closure,%esi
movl $_clZ_str,0(%ebp)
jmp _stg_ap_n_fast
.Lcmk:
cmpl $2,%eax
jne .Lcmc
movl $_ghczmprim_GHCziCString_unpackCStringzh_closure,%esi
movl $_clN_str,0(%ebp)
jmp _stg_ap_n_fast
.Lcmm:
testl %eax,%eax
jne .Lcmc
movl $_ghczmprim_GHCziCString_unpackCStringzh_closure,%esi
movl $_clF_str,0(%ebp)
jmp _stg_ap_n_fast
.Lcmo:
cmpl $1,%eax
jl .Lcmm
cmpl $1,%eax
jne .Lcmc
movl $_ghczmprim_GHCziCString_unpackCStringzh_closure,%esi
movl $_clJ_str,0(%ebp)
jmp _stg_ap_n_fast
.Lcmq:
cmpl $2,%eax
jl .Lcmo
cmpl $3,%eax
jl .Lcmk
cmpl $3,%eax
jne .Lcmc
movl $_ghczmprim_GHCziCString_unpackCStringzh_closure,%esi
movl $_clR_str,0(%ebp)
jmp _stg_ap_n_fast
.text
.align 4,0x90
.long _F_f_srt-(_F_f_info)+0
.long 65541
.long 0
.long 65551
.globl _F_f_info
_F_f_info:
.Lcmu:
movl 0(%ebp),%esi
movl $_sl8_info,0(%ebp)
testl $3,%esi
jne .Lcmx
jmp *(%esi)
.Lcmx:
jmp _sl8_info
입니다 ghc -S
module F (
f
) where
f :: Int -> String
f 0 = "Zero"
f 1 = "One"
f 2 = "Two"
f 3 = "Three"
f 4 = "Four"
f 5 = "Five"
f 6 = "Six"
f 7 = "Seven"
f _ = "Undefined"
에 의해 86 어셈블리로 컴파일 다음 코드를 살펴 보자. .Lcma
그 < 1에있는 지점, .Lcmo
간다로부터 제 2 비교 < 다음 < 3. 분기되는 < 6 다음 < 7. 제 comparsion가 .Lcmq
간다 < 다음 4 분파된다.대신 우리는 우리가 같은 패턴을 볼 수있는 곳을 얻을 ghc -O2 -S
와
:
.text
.align 4,0x90
.long _F_zdwf_srt-(_F_zdwf_info)+0
.long 65540
.long 0
.long 33488911
.globl _F_zdwf_info
_F_zdwf_info:
.LcqO:
movl 0(%ebp),%eax
cmpl $4,%eax
jl .Lcr6
cmpl $6,%eax
jl .LcqY
cmpl $7,%eax
jl .LcqU
cmpl $7,%eax
jne .LcqS
movl $_F_f1_closure,%esi
addl $4,%ebp
andl $-4,%esi
jmp *(%esi)
.LcqS:
movl $_F_f9_closure,%esi
addl $4,%ebp
andl $-4,%esi
jmp *(%esi)
.LcqU:
cmpl $6,%eax
jne .LcqS
movl $_F_f2_closure,%esi
addl $4,%ebp
andl $-4,%esi
jmp *(%esi)
.LcqW:
cmpl $4,%eax
jne .LcqS
movl $_F_f4_closure,%esi
addl $4,%ebp
andl $-4,%esi
jmp *(%esi)
.LcqY:
cmpl $5,%eax
jl .LcqW
cmpl $5,%eax
jne .LcqS
movl $_F_f3_closure,%esi
addl $4,%ebp
andl $-4,%esi
jmp *(%esi)
.Lcr0:
cmpl $2,%eax
jne .LcqS
movl $_F_f6_closure,%esi
addl $4,%ebp
andl $-4,%esi
jmp *(%esi)
.Lcr2:
testl %eax,%eax
jne .LcqS
movl $_F_f8_closure,%esi
addl $4,%ebp
andl $-4,%esi
jmp *(%esi)
.Lcr4:
cmpl $1,%eax
jl .Lcr2
cmpl $1,%eax
jne .LcqS
movl $_F_f7_closure,%esi
addl $4,%ebp
andl $-4,%esi
jmp *(%esi)
.Lcr6:
cmpl $2,%eax
jl .Lcr4
cmpl $3,%eax
jl .Lcr0
cmpl $3,%eax
jne .LcqS
movl $_F_f5_closure,%esi
addl $4,%ebp
andl $-4,%esi
jmp *(%esi)
.section .data
.align 4
.align 1
_F_f_srt:
.long _F_zdwf_closure
.data
.align 4
.align 1
.globl _F_f_closure
_F_f_closure:
.long _F_f_info
.long 0
.text
.align 4,0x90
.long _F_f_srt-(_srh_info)+0
.long 0
.long 65568
_srh_info:
.Lcrv:
movl 3(%esi),%eax
movl %eax,0(%ebp)
jmp _F_zdwf_info
.text
.align 4,0x90
.long _F_f_srt-(_F_f_info)+0
.long 65541
.long 0
.long 65551
.globl _F_f_info
_F_f_info:
.Lcrz:
movl 0(%ebp),%esi
movl $_srh_info,0(%ebp)
testl $3,%esi
jne _srh_info
jmp *(%esi)
우리는 가지 < 5에있는
f :: Int -> String
f 1 = "Zero"
f 2 = "One"
f 3 = "Two"
f 4 = "Three"
f 5 = "Four"
f 6 = "Five"
f 7 = "Six"
f 8 = "Seven"
f _ = "Undefined"
, < 7 원래의 코드를 변경하는 경우 , < 8, < 5가 < 3, < 4 등이 될 수 있습니다. 따라서 인수를 정렬하면이 작업을 수행 할 수 있습니다. , < 30 < (50)는가는, 가지가, < (50)에 여전히 < 70, < 80입니다
f :: Int -> String
f 20 = "Zero"
f 80 = "One"
f 70 = "Two"
f 30 = "Three"
f 40 = "Four"
f 50 = "Five"
f 10 = "Six"
f 60 = "Seven"
f _ = "Undefined"
과연 < 40 : 우리는 숫자를 스크램블링, 심지어 그들 사이에 간격을 추가하여 그것을 테스트 할 수 있습니다 등등.
'String'은 효율성에 관심이있는 경우 대부분의 경우에 사용할 좋은 유형이 아닙니다. GHC 개발자가 패턴 매칭을위한 특별한 최적화를 작성하려고 시도하지도 않았습니다.'String's - 다른리스트와 같은 방식으로 일치한다고 상상해보십시오. – dfeuer
문자열의 경우,'bytestring'과'bytestring-trie' 패키지를 사용해보십시오. – dfeuer