기능 구성(컴퓨터 과학)
Function composition (computer science)컴퓨터 과학에서 함수 구성은 단순한 기능을 결합하여 더 복잡한 기능을 만드는 행위 또는 메커니즘입니다.수학에서 일반적인 함수 구성처럼, 각 함수의 결과는 다음 함수의 인수로 전달되고, 마지막 함수의 결과는 전체의 결과이다.
프로그래머는 다른 함수의 결과에 함수를 적용하는 경우가 많고, 거의 모든 프로그래밍 언어가 이를 허용합니다.경우에 따라서는 함수의 구성이 나중에 사용할 수 있는 그 자체의 함수로 흥미롭다.이러한 함수는 항상 정의할 수 있지만, 퍼스트 클래스 함수를 가진 언어는 더 쉽게 정의할 수 있습니다.
함수를 쉽게 구성할 수 있기 때문에 유지 보수성과 코드 재사용을 위해 함수를 인수분해(분할)할 수 있습니다.보다 일반적으로, 큰 시스템은 전체 프로그램을 구성함으로써 구축될 수 있습니다.
좁게 말하면, 함수 구성은 유한한 양의 데이터에 대해 동작하는 함수에 적용되며, 각 단계는 그것을 다음 단계로 넘기기 전에 순차적으로 처리한다.잠재적인 무한 데이터(스트림 또는 기타 코다타)에서 작동하는 함수는 필터로 알려져 있으며, 대신 함수 구성과 유사하며 동시에 실행할 수 있는 파이프라인으로 연결됩니다.
함수 호출을 구성하는 중
예를 들어, z = f(y) 및 y = g(x)와 같이 두 개의 함수 f와 g가 있다고 가정합니다.이 값을 구성한다는 것은 먼저 y = g(x)를 계산한 다음 y를 사용하여 z = f(y)를 계산한다는 것을 의미합니다.C 언어의 예를 다음에 나타냅니다.
흘러가다 x, y, z; // ... y = g(x); z = f(y); 중간 결과에 이름을 지정하지 않으면 단계를 조합할 수 있습니다.
z = f(g(x)); 길이는 다르지만 이 두 구현은 동일한 결과를 산출합니다.두 번째 구현에는 코드 한 줄만 필요하며, 일반적으로 "고도의 구성" 형식이라고 합니다.가독성과 유지관리성은 고도로 구성된 폼의 장점 중 하나입니다. 이는 프로그램의 "서피스 영역"[1]을 최소화하여 코드 줄이 적게 필요하기 때문입니다.DeMarco와 Lister는 표면적과 유지 [2]보수성 사이의 역관계를 경험적으로 검증합니다.한편, 고도로 구성된 양식을 과도하게 사용할 수도 있습니다.함수가 너무 많으면 역효과가 발생하여 코드의 유지보수가 어려워질 수 있습니다.
스택 기반 언어에서 기능적 구성은 훨씬 더 자연스럽다: 그것은 연결에 의해 수행되며, 보통 프로그램 설계의 주요 방법이다.위의 Fourth 예시는 다음과 같습니다.
g f
이 명령어는 이전에 스택에 있던 것을 모두 사용하여 g를 적용한 후 f를 적용하여 결과를 스택에 남깁니다.대응하는 수학적 표기법에 대해서는 포스트픽스 합성 표기법을 참조해 주세요.
함수의 구성 이름 지정
여기서 g()의 결과에서 f()를 호출하는 조합이 자주 도움이 된다고 가정하고 foo()를 함수로 사용하는 이름을 지정합니다.
대부분의 언어에서 우리는 작문에 의해 구현되는 새로운 기능을 정의할 수 있다.C의 예:
흘러가다 후우(흘러가다 x) { 돌아가다 f(g(x)); } (중간체가 있는 긴 형태도 좋습니다.)네 번째 예:
: foog f;
C와 같은 언어에서는 새로운 함수를 만드는 유일한 방법은 프로그램 소스에서 정의하는 것입니다. 즉, 실행 시 함수를 구성할 수 없습니다.그러나 사전 정의된 기능의 임의 구성을 평가할 수 있습니다.
#실패하다 <stdio.h> 유형화된 인트 FXN(인트); 인트 f(인트 x) { 돌아가다 x+1; } 인트 g(인트 x) { 돌아가다 x*2; } 인트 h(인트 x) { 돌아가다 x-3; } 인트 평가하다(FXN *fs[], 인트 크기, 인트 x) { 위해서 (인트 i=0; i< >크기; i++) x = (*fs[i])(x); 돌아가다 x; } 인트 주된() { // ((6+1)*2)-3 = 11 FXN *arr[] = {f,g,h}; 인쇄물(%d\n", 평가하다(arr, 3, 6)); // ((6-3)*2)+1 = 7 arr[2] = f; arr[0] = h; 인쇄물(%d\n", 평가하다(arr, 3, 6)); } 일급 구성
함수 프로그래밍 언어에서 함수 구성은 자연스럽게 고차 함수 또는 연산자로 표현될 수 있습니다.다른 프로그래밍 언어에서는 자체 메커니즘을 작성하여 함수 합성을 수행할 수 있습니다.
하스켈
Haskell에서, 위에 제시된 foo = f µg의 예는 다음과 같습니다.
foo = f.g
f로 구성된 g 또는 g 뒤에 f로 읽을 수 있는 내장 합성 연산자(.)를 사용한다.
합성 연산자 θ 자체는 람다 식을 사용하여 Haskell에서 정의할 수 있습니다.
(.) :: (b -> c) -> (a -> b) -> a -> c f . g = \x -> f (g x) 첫 번째 줄은 (.)의 유형을 설명합니다. 함수의 쌍인 f, g를 사용하고 함수(두 번째 줄의 람다 식)를 반환합니다.Haskell은 f와 g의 정확한 입력 및 출력 유형을 지정할 필요가 없습니다.a, b, c 및 x는 플레이스 홀더입니다.f, g의 관계만이 중요합니다(f는 g가 반환하는 것을 받아들일 필요가 있습니다).이것에 의해, (.)는 다형 연산자가 됩니다.
리스프
Lisp의 변형, 특히 Scheme, 함수의 처리와 함께 코드와 데이터의 교환성은 가변 구성 연산자의 재귀적 정의에 매우 잘 도움이 됩니다.
(정의하다(작곡하다 . fs) (한다면(특수 절차입니까?fs) (람다(x) x) 인수를 지정하지 않으면 ID 함수로 평가됩니다. (람다(x) ((차fs) ((적용합니다.작곡하다 (CDRfs)) x))))) ; 예 (정의하다(애드어방 스트레이트) (현악기스트레이트 "!")) (정의하다기브뱅 (작곡하다 string - > symbol string 애드어방 기호 -> 문자열)) (기브뱅 세트) ; ===> 세트! 어나니머스 작곡 ((작곡하다 sqrt 부정하다 광장) 5) ; ===> 0+5i APL
기호를 사용하여 함수 구성에 내장된 APL 기능의 많은 방언∘이 고차 함수는 함수 구성을 왼쪽 함수의 2진수 적용으로 확장하여 다음과 같이 합니다.A f∘g B이A f g B.
후우←f∘g 또한 다음과 같이 함수 구성을 정의할 수 있습니다.
o←{⍺⍺ ⍵⍵ ⍵} 중괄호를 사용한 인라인 정의를 지원하지 않는 방언에서는 다음과 같은 기존 정의를 사용할 수 있습니다.
∇ r←(f o g)x r←f g x ∇ 라쿠
Haskell과 같은 Raku는 함수 구성 연산자를 내장하고 있으며, 주요 차이점은 다음과 같습니다.∘또는o.
나의 &후우 = &f ∘ &g; 또한 Haskell과 마찬가지로 사용자가 직접 연산자를 정의할 수 있습니다.실제, Rakudo 실장에서의 Raku 코드의 정의는 다음과 같습니다.
# 이 구현에는 부정행위가 있기 때문에 약간 다른 행이 있습니다. 원형의 후보선수 혼재하다: <filength> (&?, &?)는 equiv(&[~])는 assoc <left> {*} 복수 후보선수 혼재하다: </FONT CHANGE:> () { *.자신 } # 에서는, 「@array」가 비어 있는 경우, 「[filename]@array」가 동작합니다. 복수 후보선수 혼재하다: </f> (&f) { &f } # 는, 「@array」에 1 개의 요소가 있는 경우에, 「[syslog] @array」가 동작하도록 합니다. 복수 후보선수 혼재하다: </f> (&f, &g --> 차단) { (&f).세어보세요 > 1 ?? -> args { f g args } !! -> args { f g args } } # '텍사스' 철자 (모든 것이 더 크고, 텍사스에서는 ASCII)로 명명됩니다. 나의 &inix:<o> := &inix:<blocks>; 파이썬
Python에서는 함수 그룹에 대한 구성을 정의하는 방법이 reduce 함수를 사용하는 것입니다(Python 3에서는 functools.reduce 사용).
# Python v2.6 이후 이용 가능 부터 기능하다 수입품 줄이자 방어하다 작곡하다(*기능) -> 인트: "함수군(f(g(h(...)")을 하나의 복합 함수로 구성합니다.""" 돌아가다 줄이자(람다 f, g: 람다 x: f(g(x)), 기능) # 예 f = 람다 x: x + 1 g = 람다 x: x * 2 h = 람다 x: x - 3 # 함수 x=10 : (x-3)*2)+1 = 15 를 호출한다. 인쇄물(작곡하다(f, g, h)(10)) 자바스크립트
JavaScript에서는 f와 g의 두 가지 함수를 취하여 함수를 생성하는 함수로 정의할 수 있습니다.
기능. o(f, g) { 돌아가다 기능.(x) { 돌아가다 f(g(x)); } } // 또는 ES2015에서 rest 연산자와 lamda 식 사용 컨스턴트 작곡하다 = (...fs) => (x) => fs.reduce 오른쪽((액세스, f) => f(액세스), x) C#
C#에서는 2개의 Funcs f와 g를 취하여 Func를 생성하는 Func로 정의할 수 있습니다.
// 호출 예시: // var c = 구성(f, g); // // Func <int, bool> g = _ = > ... // 펑크 <bool, string> f = _ = > ... 펑크< >T, T> 작성하다< >T>(파라미터 펑크< >T, T>[ ] xs) => xs.집약((축적하다, 아이템) => x => 축적하다(아이템(x))); 루비
Ruby와 같은 언어를 사용하면 바이너리 연산자를 직접 구성할 수 있습니다.
학급 프로세서 방어하다 작곡하다(other_fn) ->(*~하듯이) { other_fn.불러(불러(*~하듯이)) } 끝. alias_module :+, : 개요 끝. f = ->(x) { x * 2 } g = ->(x) { x ** 3 } (f + g).불러(12) # = > 13824 그러나 Ruby 2.[3]6에서는 네이티브 함수 구성 연산자가 도입되었습니다.
f = 프로세서{ x x + 2} g = 프로세서{ x x * 3} (f << > g).불러(3) # -> 11, f(g(3)와 동일) (f >> g).불러(3) # -> 15, g(f(3)와 동일) 조사 조사
구성성과 구성성의 원리를 포함한 구성의 개념은 너무 흔해서 수많은 연구 가닥들이 따로따로 진화해 왔다.다음은 구성 개념이 중심이 되는 연구의 표본입니다.
- 스틸(1994)은 해스켈 프로그래밍 언어로 '모나드'로 알려진 구성 블록의 조립에 함수 구성을 직접 적용했다.
- Meyer(1988)는 소프트웨어 재사용 문제를 구성성 측면에서 해결했다.
- Abadi & Lamport(1993)는 프로그램의 안전성과 생명을 보장하는 기능 구성에 대한 증명 규칙을 공식적으로 정의했다.
- Kracht(2001)는 기호학적 체계에 배치하여 컴퓨터 언어학에서 자주 발생하는 구조적 모호성 문제에 적용함으로써 강화된 형태의 구성을 확인했다.
- van Gelder & Port(1993)는 자연어 처리의 아날로그 측면에서 구성성의 역할을 조사했다.
- Gibbons(2002)의 리뷰에 따르면 컴포넌트의 정식 처리는 IBM의 Java 언어용 Visual Age와 같은 비주얼 프로그래밍 언어의 컴포넌트 어셈블리의 검증의 기초가 됩니다.
대규모 구성
프로그램 또는 시스템 전체를 함수로 취급할 수 있으며, 입력 및 출력이 잘 [4]정의되어 있으면 쉽게 구성할 수 있습니다.필터를 쉽게 구성할 수 있는 파이프라인이 매우 성공적이어서 운영 체제의 설계 패턴이 되었습니다.
부작용이 있는 필수 절차는 참조 투명성을 위반하므로 깔끔하게 구성할 수 없다.그러나 코드를 실행하기 전후의 '세계의 상태'를 입출력이라고 생각하면 깨끗한 함수를 얻을 수 있다.이러한 기능의 구성은 절차를 차례로 실행하는 것에 해당합니다.모나드 형식주의는 이 아이디어를 기능 언어에 부작용과 입출력(I/O)을 통합하기 위해 사용합니다.
「 」를 참조해 주세요.
메모들
- ^ Cox(1986), 15-17페이지
- ^ DeMarco & Lister(1995), 페이지 133–135.
- ^ "Ruby 2.6.0 Released". www.ruby-lang.org. Retrieved 2019-01-04.
- ^ 레이먼드(2003)
레퍼런스
- 를 클릭합니다Abadi, Martín; Lamport, Leslie (1993), "Composing specifications" (PDF), ACM Transactions on Programming Languages and Systems, 15 (1): 73–132, doi:10.1145/151646.151649.
- 를 클릭합니다Cox, Brad (1986), Object-oriented Programming, an Evolutionary Approach, Reading, MA: Addison-Wesley, ISBN 978-0-201-54834-1.
- 를 클릭합니다Daume, Hal, III, Yet Another Haskell Tutorial.
- 를 클릭합니다DeMarco, Tom; Lister, Tim (1995), "Software development: state of the art vs. state of the practice", in DeMarco, Tom (ed.), Why Does Software Cost So Much, and other puzzles of the Information Age, New York, NY: Dorset House, ISBN 0-932633-34-X.
- 를 클릭합니다van Gelder, Timothy; Port, Robert (1993), "Beyond symbolic: prolegomena to a Kama-Sutra of compositionality", in Honavar, Vasant; Uhr, Leonard (eds.), Symbol Processing and Connectionist Models in Artificial Intelligence and Cognition: Steps Toward Integration, Academic Press.
- 를 클릭합니다Gibbons, Jeremy (2002), Arbab, Farhad; Talcott, Carolyn (eds.), Proc. 5th International Conference on Coordination Models and Languages (PDF), Lecture Notes in Computer Science, vol. 2315, Springer-Verlag, pp. 339–350, doi:10.1007/3-540-46000-4\_18.
- 를 클릭합니다Korn, Henry; Liberi, Albert (1974), An Elementary Approach to Functions, New York, NY: McGraw-Hill, ISBN 0-07-035339-5.
- 를 클릭합니다Kracht, Marcus (2001), "Strict compositionality and literal movement grammars", Proc. 3rd International Conference on Logical Aspects of Computational Linguistics, Lecture Notes in Computer Science, vol. 2014, Springer-Verlag, pp. 126–143, doi:10.1007/3-540-45738-0_8.
- 를 클릭합니다Meyer, Bertrand (1988), Object-oriented Software Construction, New York, NY: Prentice Hall, pp. 13–15, ISBN 0-13-629049-3.
- 를 클릭합니다Miller, George A. (1956), "The magical number seven, plus or minus two: some limits on our capacity for processing information", Psychological Review, 63 (2): 81–97, doi:10.1037/h0043158, hdl:11858/00-001M-0000-002C-4646-B, PMID 13310704, archived from the original on 2010-06-19, retrieved 2010-05-02.
- 를 클릭합니다Pierce, Benjamin C.; Turner, David N. (2000), "Pict: A programming language based on the pi-calculus", Proof, Language, and Interaction: Essays in Honour of Robin Milner, Foundations Of Computing Series, Cambridge, MA: MIT Press, pp. 455–494, ISBN 0-262-16188-5.
- 를 클릭합니다Raymond, Eric S. (2003), "1.6.3 Rule of Composition: Design programs to be connected with other programs", The Art of Unix Programming, Addison-Wesley, pp. 15–16, ISBN 978-0-13-142901-7.
- 를 클릭합니다Steele, Guy L., Jr. (1994), "Building interpreters by composing monads", Proc. 21st ACM Symposium on Principles of Programming Languages, pp. 472–492, doi:10.1145/174675.178068.
