Julia Language
반복문
수색…
통사론
- 시작 (itr)
- 다음 (itr, s)
- 완료 됨 (itr, s)
- 테이크 (itr, n)
- 드롭 (itr, n)
- 주기 (itr)
- Base.product (xs, ys)
매개 변수
매개 변수 | 세부 |
---|---|
에 대한 | 모든 기능 |
itr | 조작 할 수있는 반복 가능 요소. |
에 대한 | next 및 done |
s | 반복의 현재 위치를 설명하는 반복자 상태입니다. |
에 대한 | take 와 drop |
n | 가져 오거나 놓을 요소의 수. |
에 대한 | Base.product |
xs | 쌍의 첫 번째 요소를 가져 오는 반복 가능 |
ys | 쌍의 두 번째 요소를 가져 오는 반복 가능 |
... | product 은 여러 개의 인수를 허용하며 두 개 이상이 제공되면 두 개 이상의 길이 인 튜플을 생성합니다. |
새로운 반복 가능한 유형
반복 가능 객체를 통해 반복 할 때 줄리아에서, I
으로 수행 for
구문 :
for i = I # or "for i in I" # body end
뒤에서 이것은 번역 된 것입니다 :
state = start(I) while !done(I, state) (i, state) = next(I, state) # body end
당신이 원하는 경우에 따라서, I
반복 가능으로, 당신은 정의 할 필요가 start
, next
과 done
의 유형에 대한 방법을. 배열 을 필드 중 하나로 포함하는 Foo
유형 을 정의한다고 가정 해 보겠습니다.
type Foo bar::Array{Int,1} end
다음과 같이 Foo
객체를 인스턴스화합니다.
julia> I = Foo([1,2,3])
Foo([1,2,3])
julia> I.bar
3-element Array{Int64,1}:
1
2
3
Foo
를 반복하면서 반복 할 때마다 각 요소 bar
가 반환되면 메서드를 정의합니다.
import Base: start, next, done start(I::Foo) = 1 next(I::Foo, state) = (I.bar[state], state+1) function done(I::Foo, state) if state == length(I.bar) return true end return false end
이 함수 는 Base
모듈에 속하기 때문에 먼저 새 모듈을 추가하기 전에 이름을 import
합니다.
메소드가 정의 된 후 Foo
는 반복자 인터페이스와 호환 가능합니다.
julia> for i in I println(i) end 1 2 3
게으른 반복문 결합하기
표준 라이브러리에는 풍부한 lery iterables 모음이 있습니다 ( Iterator.jl 과 같은 라이브러리는 더 많이 제공합니다). 게으른 반복문은 일정 시간 내에 더 강력한 반복문을 생성하도록 구성 될 수 있습니다. 가장 중요한 lazy iterables는 take와 drop으로 , 다른 많은 함수를 생성 할 수 있습니다.
느슨하게 반복 가능한 슬라이스
배열은 슬라이스 표기법으로 슬라이스 할 수 있습니다. 예를 들어, 다음은 배열의 10 번째부터 15 번째까지를 반환합니다.
A[10:15]
그러나 슬라이스 표기법은 모든 반복 가능 코드에서 작동하지 않습니다. 예를 들어 생성자 표현식을 슬라이스 할 수 없습니다.
julia> (i^2 for i in 1:10)[3:5]
ERROR: MethodError: no method matching getindex(::Base.Generator{UnitRange{Int64},##1#2}, ::UnitRange{Int64})
슬라이스 문자열 에 예상되는 유니 코드 동작이 없을 수 있습니다.
julia> "αααα"[2:3]
ERROR: UnicodeError: invalid character index
in getindex(::String, ::UnitRange{Int64}) at ./strings/string.jl:130
julia> "αααα"[3:4]
"α"
우리는 lazysub(itr, range::UnitRange)
함수를 정의하여 임의의 iterables에서 이런 종류의 조각을 수행 할 수 있습니다. 이는 take
앤 drop
이라는 용어로 정의됩니다.
lazysub(itr, r::UnitRange) = take(drop(itr, first(r) - 1), last(r) - first(r) + 1)
UnitRange
값 a:b
의 경우 다음 단계가 수행되기 때문에 여기 구현됩니다.
- 첫 번째
a-1
요소를 삭제합니다. - 는
a+(ba)=b
th 요소가 될 때까지a
번째 요소,a+1
번째 요소 등을 취한다
전체적으로 ba
요소가 사용됩니다. 위의 각 사례에서 구현이 올바른지 확인할 수 있습니다.
julia> collect(lazysub("αααα", 2:3))
2-element Array{Char,1}:
'α'
'α'
julia> collect(lazysub((i^2 for i in 1:10), 3:5))
3-element Array{Int64,1}:
9
16
25
반복적으로 반복적으로 순환 이동
배열에 대한 circshift
시프트 연산은 배열을 마치 원으로 바꾸고 다시 선형화합니다. 예를 들어,
julia> circshift(1:10, 3)
10-element Array{Int64,1}:
8
9
10
1
2
3
4
5
6
7
모든 iterables에 대해이 작업을 지연시킬 수 있습니까? 우리는 사용 cycle
, drop
, 그리고 take
이 기능을 구현하기 위해 반복 가능 객체를.
lazycircshift(itr, n) = take(drop(cycle(itr), length(itr) - n), length(itr))
많은 경우에 게으른 유형이 더 많은 성능을 제공함과 함께, 그렇지 않으면 지원하지 않는 유형에서 circshift
와 같은 기능을 수행 할 수 있습니다.
julia> circshift("Hello, World!", 3)
ERROR: MethodError: no method matching circshift(::String, ::Int64)
Closest candidates are:
circshift(::AbstractArray{T,N}, ::Real) at abstractarraymath.jl:162
circshift(::AbstractArray{T,N}, ::Any) at abstractarraymath.jl:195
julia> String(collect(lazycircshift("Hello, World!", 3)))
"ld!Hello, Wor"
곱하기 테이블 만들기
lazy 반복 가능한 함수를 사용하여 행렬을 만드는 곱셈 테이블 을 만듭니다.
여기에 사용되는 핵심 기능은 다음과 같습니다.
-
Base.product
: 데카르트 제품 을 계산합니다. -
prod
는 정규 제품을 계산합니다 (곱셈과 같이). -
:
범위를 만드는 -
map
: 컬렉션의 각 요소에 함수를 적용하는 고차 함수입니다.
해결책은 다음과 같습니다.
julia> map(prod, Base.product(1:10, 1:10))
10×10 Array{Int64,2}:
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
느슨하게 평가 된 목록
가변 유형 및 클로저를 사용하여 간단한 지연 평가 목록을 만들 수 있습니다. 느슨하게 평가되는 목록은 요소가 구성 될 때 평가되지 않고 액세스 될 때만 평가되는 목록입니다. 지연 평가 목록의 이점에는 무한대의 가능성이 포함됩니다.
import Base: getindex
type Lazy
thunk
value
Lazy(thunk) = new(thunk)
end
evaluate!(lazy::Lazy) = (lazy.value = lazy.thunk(); lazy.value)
getindex(lazy::Lazy) = isdefined(lazy, :value) ? lazy.value : evaluate!(lazy)
import Base: first, tail, start, next, done, iteratorsize, HasLength, SizeUnknown
abstract List
immutable Cons <: List
head
tail::Lazy
end
immutable Nil <: List end
macro cons(x, y)
quote
Cons($(esc(x)), Lazy(() -> $(esc(y))))
end
end
first(xs::Cons) = xs.head
tail(xs::Cons) = xs.tail[]
start(xs::Cons) = xs
next(::Cons, xs) = first(xs), tail(xs)
done(::List, ::Cons) = false
done(::List, ::Nil) = true
iteratorsize(::Nil) = HasLength()
iteratorsize(::Cons) = SizeUnknown()
모든리스트가 느슨하게 평가되는 Haskell 과 같은 언어로 실제로 작동합니다.
julia> xs = @cons(1, ys)
Cons(1,Lazy(false,#3,#undef))
julia> ys = @cons(2, xs)
Cons(2,Lazy(false,#5,#undef))
julia> [take(xs, 5)...]
5-element Array{Int64,1}:
1
2
1
2
1
실제로는 Lazy.jl 패키지를 사용하는 것이 좋습니다. 그러나 위의 lazy list 구현은 자신의 반복 가능한 (iterable) 유형을 만드는 방법에 대한 중요한 세부 사항을 밝혀줍니다.