수색…


통사론

  • 시작 (itr)
  • 다음 (itr, s)
  • 완료 됨 (itr, s)
  • 테이크 (itr, n)
  • 드롭 (itr, n)
  • 주기 (itr)
  • Base.product (xs, ys)

매개 변수

매개 변수 세부
에 대한 모든 기능
itr 조작 할 수있는 반복 가능 요소.
에 대한 nextdone
s 반복의 현재 위치를 설명하는 반복자 상태입니다.
에 대한 takedrop
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 , nextdone 의 유형에 대한 방법을. 배열 을 필드 중 하나로 포함하는 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에서 이런 종류의 조각을 수행 할 수 있습니다. 이는 takedrop 이라는 용어로 정의됩니다.

lazysub(itr, r::UnitRange) = take(drop(itr, first(r) - 1), last(r) - first(r) + 1)

UnitRangea: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"
0.5.0

곱하기 테이블 만들기

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) 유형을 만드는 방법에 대한 중요한 세부 사항을 밝혀줍니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow