일부 함수형 프로그래밍 언어는 함수 적용을위한 공간을 사용하는 이유는 무엇입니까?


34

함수형 프로그래밍을 위해 일부 언어를 살펴본 결과, 일부 fp 언어가 함수 응용 프로그램 (및 정의)을 위해 하나 이상의 공백 문자를 사용하는 이유가 항상 궁금한 반면 대부분의 명령형 / 개체 지향 언어는 괄호를 사용합니다. 더 수학적 방법입니다. 또한 후자의 스타일은 괄호가없는 것보다 훨씬 명확하고 읽기 쉽다고 생각합니다.

따라서 f (x) = x² 함수 가 있으면이를 호출하는 두 가지 대안이 있습니다.

  • FP : f x

    예 :

    • ML, 오캄, F #
    • 하스켈
    • LISP, Scheme (어떻게)
  • 비 FP : f(x)

    예 :

    • 거의 모든 명령형 언어 (알고 있습니다. 의견 / 답변 참조)
    • 에를 랑
    • 스칼라 (또한 단일 인수에 대해 "연산자 표기법"을 허용 함)

괄호를 "제거"하는 이유는 무엇입니까?


9
좀 더 혼란스럽게 만들려면 음, 나는 간결함을 의미했습니다 .
Den

11
@Den 당신이 haskell을 배우면, 구문은 가장 혼란스러운 것들 중 하나가 될 것입니다 : p
Simon Bergot

5
괄호를 사용하는 것이 더 수학적이며 지수 함수 를 예로 사용한다고 말하는 아이러니를 알고 있습니까?
Jörg W Mittag

12
@ 구문 때문에 언어를 거부함으로써 해를 끼치고 있습니다. 분명히 xml 또는 sql을 배우는 데 어려움이 없었습니다 (일반 언어는 아니지만 자체 구문을 정의합니다).
Simon Bergot

7
쉘 스크립트 (예 : bash)는 일반적으로 매개 변수를 사용하여 명령을 호출하지 않는다는 것을 지적하고 싶습니다. PowerShell은 일종의 함수가 괄호로 선언되고없이 호출된다는 점에서 두 세계 중 최악의 상황입니다.
Kris Harper

답변:


59

더 수학적 방법 인 것 같습니다

기능적 언어는 람다 미적분학에서 영감을 얻었습니다 . 이 필드에서 괄호는 기능 적용에 사용되지 않습니다.

또한 후자의 스타일은 괄호가없는 것보다 훨씬 명확하고 읽기 쉽다고 생각합니다.

가독성은 보는 사람의 눈에 있습니다. 당신은 그것을 읽는 데 익숙하지 않습니다. 수학 연산자와 조금 비슷합니다. 연관성을 이해하면 표현의 구조를 명확하게하기 위해 몇 개의 파렌 만 있으면됩니다. 종종 필요하지 않습니다.

카레 또한이 규칙을 사용하는 좋은 이유입니다. haskell에서 다음을 정의 할 수 있습니다.

add :: Int -> Int -> Int
add x y = x + y

x = add 5 6 -- x == 11
f = add 5
y = f 6 -- y == 11
z = ((add 5) 6) -- explicit parentheses; z == 11

Parens를 사용하면 (커리 f(5, 6)되지 않음) 또는 f(5)(6)(커리 됨)의 두 가지 규칙을 사용할 수 있습니다 . 하스켈 구문은 카레 개념에 익숙해지는 데 도움이됩니다. 아직 커리되지 않은 버전을 사용할 수 있지만 결합기와 함께 사용하는 것이 더 고통 스럽습니다.

add' :: (Int, Int) -> Int
add' (x, y) = x + y
u = add'(5, 6) -- just like other languages
l = [1, 2, 3]
l1 = map (add 5) l -- [6, 7, 8]
l2 = map (\x -> add'(5, x)) l -- like other languages

두 번째 버전에서 x를 변수로 등록하는 방법과 하위 표현식은 정수를 취하고 5를 더하는 함수라는 것을 주목하십시오. 카레 버전은 훨씬 가볍지 만 많은 사람들이 더 읽기 쉬운 것으로 간주합니다.

Haskell 프로그램은 추상화를 정의하고 구성하는 수단으로 부분 적용 및 결합기를 광범위하게 사용하므로 장난감 예제가 아닙니다. 좋은 기능 인터페이스는 매개 변수 순서가 친절한 카레 사용을 제공하는 인터페이스입니다.

또 다른 요점 : 매개 변수가없는 함수는로 호출해야합니다 f(). haskell에서는 불변의 게으른 평가 된 값만 조작하기 때문에을 쓰고 f값을 필요할 때 계산 해야하는 값으로 간주하면됩니다. 평가에는 부작용이 없으므로 매개 변수가없는 함수와 반환 값에 대해 다른 표기법을 사용하는 것은 의미가 없습니다.

함수 적용에 대한 다른 규칙도 있습니다.

  • Lisp : (fx)-외부 괄호 접두사
  • 넷째 : xf-접미사

7
작은 nitpick : 용어는 "currification"및 "currified"가 아닌 "currying"및 "curried"입니다.
Doval

"비 카레"하스켈의 비 카레 기능은 무엇입니까?
Ven

3
@ user1737909 튜플을 인수로 취하는 함수입니다.
Doval

1
@Doval 실제로 "schönfinkeling"과 "schönfinkeled"여야합니다. 그러나 역사는 항상 승자를 회고 적으로 정의합니다.
Profpatsch

괄호 태닝 구문, 같은 뭔가에 대해 생각 f(a, ,b)하거나 add(a, )또는 것은 add(, b)기본적으로 더 유연한 것 같다.
phresnel

25

기본 아이디어는 가장 중요한 작업 (함수 응용 프로그램)을 가장 읽기 쉽고 쓰기 좋게 만드는 것입니다. 공백은 읽기에 방해가되지 않으며 입력하기가 매우 쉽습니다.

이 기능 언어는 기능적 언어, 예를 들어 스몰 토크 (Smalltalk) 에서 영감을받은 최초의 OO 언어 및 언어 ( Self , Newspeak , Objective-C) 중 하나 인 Io와 그 언어에서 영감을 얻은 언어 (Ioke, Seph), 공백은 메소드 호출에 사용됩니다.

스몰 토크 스타일 :

anArray sort
anArray add: 2
aString replace: "a" with: "b"

후자의 경우 메서드 이름은입니다 replace:with:.

이오 스타일 :

anArray sort
anArray add(2)
aString replace("a", "b")

스칼라는 메소드 호출에 공백을 허용합니다.

foo bar(baz)

인수가 하나 뿐인 경우 괄호를 생략하십시오.

foo bar baz

루비를 사용하면 괄호를 생략 할 수 있습니다.

an_array.sort
an_array.add 2
a_string.replace "a", "b"

더 수학적 방법 인 괄호 사용

실제로는 아닙니다.

f(x)
sin x
x²
|x|
x!
x + y
xy
½

수학 표기법은 오랫동안 일관되지 않은 방식으로 발전해 왔습니다.

기능 함수 언어는 함수 응용 프로그램이 공백을 사용하여 작성된 λ- 미적분에서 영감을 얻습니다.


3
편집의 경제성에 대한 주장도 있습니다. 특히, 기능적 언어는 일반적으로 구성을 직접 지원합니다. 인수 대신 함수를 괄호로 묶는 것이 좋습니다. e (f (g (x)))와 반대로 "한 번": (e. f. g) x 만하면됩니다. 또한 Haskell은 적어도 f x 대신 f (x)를 수행하지 못하게합니다. 관용적이지 않습니다.
nomen

18

함수 적용을위한 괄호는 오일러가 우리에게 남긴 많은 안장 중 하나 일뿐입니다. 다른 어떤 것과 마찬가지로 수학에는 여러 가지 방법이있을 때 규칙이 필요합니다. 수학 교육이 대학에서 수학과 관련이없는 주제까지만 확장된다면, 이러한 넌센스 괄호 (예 : Differential Geometry, Abstract Algebra)없이 함수 적용이 행복하게 이루어지는 많은 분야에 익숙하지 않을 것입니다. 그리고 당신은 접두사 (거의 모든 언어), 규범을 취하는 것과 같은 "접두사", 또는 도식적으로 (Befunge, Algebraic Topology) 함수를 언급하지 않습니다.

그래서 대답하자면 광범위한 수학 교육을받은 기능 프로그래머와 언어 디자이너가 훨씬 많기 때문입니다. Von Neumann은 "젊은이, 수학에서는 사물을 이해하지 못합니다. 당신은 단지 그것들에 익숙해집니다."라고 분명히 말하고 있습니다.


7
심지어 나에 시작하지 마십시오 f(x)sin x|x|x!x + yxy½대 요약 대 핵심 대 ...
요 르그 W MITTAG

2
폰 노이만 인용문 +1 나머지 답변은 +1이지만 +2는 줄 수 없습니다. :(
pvorb

2
나는 여기서 엘리트주의의 힌트를 얻는다. 나는 "함수 프로그래밍 언어 설계자들이 더 잘 교육 받았다"는 중립성을 논박한다 .
CaptainCodeman

7
@CaptainCodeman 그는 수학에 대해 더 많은 교육을 받았다고 말합니다. 적어도 Haskell에 관해서는 두 개념이 본질적으로 더 수학적이며 커뮤니티가 더 수학적으로 기울어 져 있음을 알 수 있습니다. 그들은 더 지능적이지 않고 수학에 더 잘 교육됩니다.
Paul

5
@CaptainCodeman 아니요, 그는 일반적으로 더 많은 교육을 받았음을 암시하지 않았기 때문에 수학에서 더 많은 교육을 받았습니다. "정확한 수학 교육"이라고 그가 말했습니다. :)
Paul

8

Simon의 대답에는 많은 진실이 있지만, 훨씬 더 실용적인 이유가 있다고 생각합니다. 함수형 프로그래밍의 특성은 함수 체인과 구성으로 인해 명령형 프로그래밍보다 훨씬 많은 괄호를 생성하는 경향이 있습니다. 이러한 연결 및 구성 패턴은 일반적으로 괄호 없이도 명확하게 표현 될 수 있습니다.

결론은 모든 괄호가 읽고 추적하기가 성가신다는 것입니다. LISP가 더 인기가없는 가장 큰 이유 일 것입니다. 따라서 괄호를 과도하게 사용하지 않고도 함수형 프로그래밍의 힘을 얻을 수 있다면 언어 디자이너가 그렇게하는 경향이 있다고 생각합니다. 결국 언어 디자이너는 언어 사용자이기도합니다.

스칼라조차도 프로그래머가 특정 상황에서 괄호를 생략하도록 허용합니다. 기능적 스타일로 프로그래밍 할 때 상당히 자주 발생하므로 두 가지 이점을 모두 누릴 수 있습니다. 예를 들면 다음과 같습니다.

val message = line split "," map (_.toByte)

끝 부분의 파렌은 연관성을 위해 필요하고 다른 것들은 (점뿐만 아니라) 잘리지 않습니다. 이 방법으로 작성하면 수행중인 작업의 체인 특성이 강조됩니다. 명령형 프로그래머에게는 익숙하지 않을 수도 있지만 함수형 프로그래머에게는 프로그램에 의미가없는 구문을 중지하고 삽입 할 필요가 없지만 컴파일러를 행복하게하기 위해이 방법을 작성하는 것이 매우 자연스럽고 흐릅니다. .


2
"결론은 모든 괄호가 읽고 추적하기가 성가신 것입니다. 아마 LISP가 인기가없는 가장 큰 이유 일 것입니다." 그것들은 특히 읽기가 어렵고, 다른 언어들은 훨씬 더 어색한 구문을 가지고 있습니다.
Giorgio

2
LISP 구문은 초고도의 직교성으로 성가신 괄호를 대체합니다. 그것은 단지 사용 가능한 다른 구속 기능을 가지고 있다는 것을 의미합니다. Parens가 성가신 것이 아닙니다. 모든 사람들이 그렇게 느끼는 것은 아니지만, 내가 만난 대다수의 프로그래머들은 그렇게 생각합니다.
Karl Bielefeldt

"Lost In Stupid Parentheses" 는 내가 가장 좋아하는 LISP 백두 리입니다. 컴퓨터는 또한 인간적인 방법을 사용하여 Wisp 와 같은 언어에서와 같이 코드 블록을 지정하고 중복성을 제거 할 수 있습니다 .
Cees Timmerman

4

두 건물 모두 잘못되었습니다.

  • 이 기능 언어 기능 적용을위한 공간을 사용 하지 않습니다 . 그들이하는 일은 단순히 함수 다음에 오는 표현식을 인수로 파싱하는 것입니다.

    GHCi> f 3
    4
    GHCi> f (3)
    4
    GHCi> (f)
    34

    물론 공백이나 괄호를 사용 하지 않으면 표현식이 제대로 토큰 화되지 않기 때문에 정상적으로 작동하지 않습니다.

    GHCi> f3

    <‌interactive> : 7 : 1 :
        범위에 속하지 않음 : 'f3'
        아마도 'f'를 의미했을 것입니다 (2 행).

    그러나 이러한 언어가 1 자 변수 이름으로 제한되면 작동합니다.

  • 수학 규칙은 일반적으로 함수 적용을 위해 괄호를 요구하지 않습니다. 수학자들은 종종 sin x를 쓸뿐만 아니라 선형 함수 (일반적으로 선형 연산자라고 함)의 경우, 함수형 프로그래밍에서 다른 함수와 마찬가지로 선형 함수는 종종 직접 공급하지 않고 처리되기 때문에 parens없이 인수를 작성하는 것이 매우 일반적입니다. 논쟁.

따라서 실제로 귀하의 질문은 다음과 같이 요약됩니다. 왜 일부 언어에는 함수 적용을 위해 괄호가 필요합니까? 글쎄, 당신과 같은 일부 사람들은 이것을 더 읽기 쉬운 것으로 간주합니다. 나는 이것에 강력하게 동의하지 않습니다 : 한 쌍의 parens는 훌륭하지만, 둘 이상의 중첩이 생기면 혼란스러워지기 시작합니다. Lisp 코드는 이것을 가장 잘 보여 주며, 모든 기능이 필요하다면 거의 모든 기능 언어가 비슷하게 어수선 해 보일 것입니다. 이것은 명령형 언어에서는 그다지 일어나지 않지만 주로 이러한 언어가 간결하고 명확한 한 줄짜리를 작성하기에 충분히 표현 적이 지 않기 때문입니다.


질문은 완벽하지 않습니다. :) 따라서 결론은 "고등학교는 규모가 없습니다."입니다.
pvorb

2
괄호를 요구 하는 만장일치의 비 기능 언어도 아닙니다 . 몇 가지 예를 들어, Smalltalk은 object method: args, Objective C는 [object method: args], Ruby 및 Perl은 함수 및 메소드 호출에서 괄호를 생략 할 수 있으며 모호성을 해결하기 만하면됩니다.
hobbs

1

작은 역사적 설명 : 수학의 원래 표기법은 괄호없었습니다 !

x 의 임의의 함수에 대한 fx 표기법 은 Johann Bernoulli에 의해 Leibniz가 함수에 대해 이야기하기 시작한 직후 인 1700 년에 도입되었습니다 (실제로 Bernoulli는 ϕ x 라고 썼습니다 ). 그러나 이미 많은 사람들은 괄호없이 x의 특정 기능에 대해 sin x 또는 lx ( x 의 로그) 와 같은 표기법을 이미 사용 하고 있습니다. 나는 이것이 오늘날 많은 사람들이 여전히 sin (x) 대신 sin x 를 쓰는 이유라고 생각합니다 .

Bernoulli의 학생 인 Euler는 Bernoulli의 ϕ x를 채택 하고 그리스어를 라틴 문자로 바꾸어 fx를 썼습니다 . 나중에 그는 "수량"으로 f 를 혼동하기 쉽고 fx 가 제품 이라고 믿기 때문에 f : x를 작성하기 시작했습니다 . 따라서 표기 f (x) 는 오일러 때문이 아닙니다. 물론 오일러는 함수 프로그래밍 언어에서 괄호가 필요한 것과 같은 이유로 괄호가 필요했습니다. 예를 들어 (fx) + yf (x + y) 를 구별하려면 . Euler 이후 사람들은 주로 Euler가 f (ax + b) 와 같은 복합 표현식을 쓰는 것을 보았 기 때문에 괄호를 기본값으로 채택한 것으로 보입니다.. 그는 거의 fx를 거의 쓰지 않았습니다 .

더이 페이지의 포어는 : 괄호와 오일러 적 쓰기 F (X)를 했습니까? .

함수형 프로그래밍 언어의 디자이너 나 람다 미적분학의 발명가들이 그 표기법의 역사적 근본을 알고 있었는지 나는 모른다. 개인적으로 나는 괄호가없는 표기법이 더 자연 스럽다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.