2017-11-23 9 views
1
변수

에 폐쇄 형 안정 따라 전진 즉 N의 값에 의해 결정되는 x의 유형을 사용하여 N에 종속 된 함수를 생성합니다. 기본적으로, 나는 이것에서 나오는 기능을 실행하기 바란다. 그러나 function_maker은 그 자체가 퍼포먼스가 될 필요가 없다. 왜냐하면 그것은 전역 범위 나 기능 장벽 이상에서만 사용되기 때문이다.함수</p> <pre><code>function function_maker(N) if N == 1 x = 1.0 else x = 1 end f(y) = x+y end </code></pre> <p>I 형 안정되지이 출력을 싶지만은 입력 - 안정한 <code>f</code>를 생성 할 들면 촬상

f = function_maker(1) 
@code_warntype f(1) 

Variables: 
    #self#::#f#9 
    y::Int64 

Body: 
    begin 
     return ((Core.getfield)((Core.getfield)(#self#::#f#9, :x)::ANY, :contents)::ANY + y::Int64)::ANY 
    end::ANY 

이것은 기본적으로 발생하지 않습니다. 나는 f(y) = x::typeof(x)+y을 시도했지만 그 중 하나도 작동하지 않았다. 이 작업을 수행하는 간단한 방법이 있습니까?

답변

2

있다 :

julia> function function_maker2(N) 
      if N == 1 
       let x = 1.0 
        return f(y) = x + y 
       end 
      else 
       let x = 1 
        return f(y) = x + y 
       end 
      end 
     end 
function_maker2 (generic function with 1 method) 

julia> f2 = function_maker2(1) 
(::f) (generic function with 1 method) 

julia> @code_warntype f2(1) 
Variables: 
    #self#::#f#5{Float64} 
    y::Int64 

Body: 
    begin 
     return (Base.add_float)((Core.getfield)(#self#::#f#5{Float64}, :x)::Float64, (Base.sitofp)(Float64, y::Int64)::Float64)::Float64 
    end::Float64 

이 버전은 let 블록 내부의 각 지점에서 x을 분리합니다. 그렇지 않으면 컴파일러가 혼란스러워 보입니다.

+1

재미 있습니다! 변수 (x와 xx)를 변경해도 도움이되지 않습니다 : function function_maker3 (N) N == 1 && begin x = 1. return y -> x + y end || begin xx = 1; return y -> xx + y end end'. 하지만 첫 번째 (!)'begin '만'let'으로 바꾸면됩니다. 두 번째 파일 만 바꾸면 작동하지 않습니다. – Liso

+1

정말로 멋진 답변입니다! 이것은 확실히 명심해야 할 트릭입니다. –

+0

@Liso 당신이 묘사하는 것은 흥미 롭습니다. 두 개의 변수 이름 함수가 타입 안정적인'f'를 반환하도록하려면, 조건부에'local x :: Float64, xx :: Int64'를 추가해야했습니다. 아마도 컴파일러는 타입에 대해 불확실성이 없습니다. 해제되지 않은 조건부 경로의 지역 변수. 첫 번째와 두 번째 사이의 '비대칭'비대칭에 관해서는'function_maker (1)'과'function_maker (2)'둘 다로 반환 된'f'의 안정성을 테스트 해 보셨습니까? 아마도'let' 가지는 안정적이고 다른 한 가지는 그렇지 않습니다. –