함수에 전달되는 인수의 양을 제한하는 언어


16

이 아이디어는 +,-, % 등과 같은 연산자가 하나 또는 두 개의 인수가 전달되고 부작용이없는 함수로 볼 수 있다는 사실에서 영감을 얻었습니다. I 또는 다른 사람이 두 개 이상의 인수가 전달되는 것을 막고 반환 값을 통해서만 작동하는 언어를 작성한다고 가정합니다.

a) 그러한 언어는 코드를 이해하기 쉽게 만들어 줄 것입니까?

b) 코드의 흐름이 더 명확합니까? (잠재적으로 적은 상호 작용이 '숨겨 짐'으로 더 많은 단계로 진행

c) 제한으로 인해 더 복잡한 프로그램의 경우 언어가 지나치게 커질 수 있습니다.

d) (보너스) 찬반 양론에 대한 다른 의견

노트 :

두 가지 결정은 여전히 ​​이루어져야합니다. 첫 번째는 main () 외부에서 사용자 입력을 허용 할 것인지 또는 이와 동등한 것을 허용하는지 여부와 배열 / 구조를 전달할 때 발생하는 규칙에 대한 규칙입니다. 예를 들어, 누군가 하나의 함수로 여러 값을 추가하려는 경우 배열에 묶어서 제한을 해결할 수 있습니다. 이것은 배열이나 구조체가 자신과 상호 작용하지 못하게함으로써 중지 될 수 있습니다. 예를 들어 각 위치를 위치에 따라 다른 양으로 나눌 수 있습니다.


4
안녕하세요. 찬반 양론의 목록은 나쁜 대답을하는 경향이 있습니다. 필요한 정보를 다른 형식으로 얻기 위해 질문을 다시 바꿀 수있는 방법이 있습니까?
MetaFight

22
당신의 추론조차도 이해가되지 않습니다. 일부 함수에는 인수가 거의 없으므로 모든 함수를 제한하겠습니다. 일반적으로 임의의 제한을 제안 할 때 얻을 수있는 이유가 있습니다. 이것이 당신을 얻을 수있는 것을 볼 수 없습니다.

2
'what if'질문에는 본질적으로 잘못된 것이 없다는 것이 아니라 (@MetaFight가 말한대로 대답하기 어려운 경우도 있지만), 생각을하고 질문을하기에 충분히 신경을 쓴 당신조차도 혜택, 그렇다면 나는 "무엇을 하시겠습니까?"라는 나의 초기 반응이 정확하다는 것을 확신합니다.

6
함수 당 하나의 인수 만 허용하는 언어는 상당히 많습니다. 람다 미적분학을 기반으로하는 언어가 있습니다. 결과는 일반적으로 단일 목록 인수를 취하는 함수이거나 모든 인수가 처리 될 때까지 다음 인수를 취하는 함수를 반환하는 함수입니다 result = f(a)(b)…(z). Haskell과 같은 ML 언어 제품군의 경우와 마찬가지로 개념적으로 Lisp, JavaScript 또는 Perl과 같은 다른 언어에서도 마찬가지입니다.
amon

3
@Orangesandlemons : 좋아, 곱셈과 덧셈 (인코딩)과 나누기와 뺄셈 (디코딩)을 사용하여 단일 정수 내에서 임의의 수의 정수를 인코딩 할 수 있습니다. 따라서 정수 또는 곱셈, 덧셈, 뺄셈 및 빼기를 허용하지 않아야합니다. (프로그래밍의 힘의 한 가지 결과는 거의 모든 것을 사용하여 거의 모든 것을 인코딩 할 수 있기 때문에 제한하는 것은 실제로 매우 어렵습니다. 일반적으로 제한은 실제로 아무것도 "제한"하지 않고 프로그래머를 성가 시게합니다.)
Jörg W Mittag

답변:


40

Robert C. Martin은 자신의 저서 "Clean Code"에서 최대 0, 1 또는 2 개의 매개 변수를 가진 함수를 많이 사용할 것을 권장하므로 적어도이 스타일을 사용하여 코드가 더 깨끗해 졌다고 생각하는 숙련 된 저술가가 있습니다. 확실히 여기에 궁극의 권위가 없으며 그의 의견은 논쟁의 여지가 있습니다).

Bob Martin이 IMHO에서 올바른 위치는 다음과 같습니다. 3 개 이상의 매개 변수를 가진 함수는 종종 코드 냄새를 나타냅니다. 많은 경우에, 매개 변수는 함께 그룹화되어 결합 된 데이터 유형을 형성 할 수 있으며, 다른 경우에는 단순히 너무 많은 기능을 수행하는 지표가 될 수 있습니다.

그러나 나는 이것을 위해 새로운 언어를 발명하는 것이 좋은 생각이라고 생각하지 않습니다.

  • 코드 전체에서 이러한 규칙을 적용하려면 기존 언어에 대한 코드 분석 도구가 필요하며 완전히 새로운 언어를 발명 할 필요가 없습니다 (예 : 'fxcop'와 같은 C #의 경우 아마도 ).

  • 때로는 매개 변수를 새로운 유형으로 결합하는 것이 번거롭지 않은 것처럼 보이거나 순수한 인공 조합이 될 수 있습니다. 예를 들어 .Net 프레임 워크 에서이 File.Open메소드 를 참조하십시오 . 4 개의 매개 변수가 필요하며 API 디자이너가 의도적 으로이 작업을 수행했다고 확신합니다. 왜냐하면 그것이 매개 변수를 함수에 제공하는 가장 실용적인 방법이라고 생각했기 때문입니다.

  • 기술적 인 이유로 2 개 이상의 매개 변수를 사용하여 실제 상황을 단순화하는 실제 시나리오가있을 수 있습니다 (예 : 간단한 데이터 유형의 사용에 바인딩되어 있고 서로 결합 할 수없는 기존 API에 1 : 1 맵핑이 필요한 경우) 하나의 사용자 정의 개체로 매개 변수)


16
여러 매개 변수가있는 냄새는 종종 다른 매개 변수가 실제로 함께 속해 있습니다. 체질량 지수, BMI의 계산을 예로 들어 보겠습니다. 그것은 사람의 키와 몸무게의 함수입니다. f (길이, 무게),하지만이 두 매개 변수는 실제로 한 사람의 키와 다른 사람의 키로이 계산을 수행하기 때문에 함께 속해 있습니까? 따라서 더 잘 표현하기 위해 사람이 무게, 길이 인터페이스를 가질 수있는 f (person)을 얻을 수 있습니다.
Pieter B

@PieterB : 물론 내 편집 내용을 참조하십시오.
Doc Brown

5
작은, 작은 언어 nitpick : "코드 냄새를 나타낼 수는"당신이 궁극적으로 코드를 변경하지 않는 경우에도, 당신이 뭔가를 재고해야한다는 단지 표시의 정의에 의한 코드 냄새 아닌가요? 따라서 코드 냄새는 "표시되지 않습니다". 특정 측면에 문제의 가능성을 나타내는 경우 입니다 코드 냄새. 아니?
jpmc26 2016 년

6
@ jpmc26 : 다른 관점에서 코드 냄새는 하나의 표시가 아닌 가능한 문제입니다. ;-) 코드 냄새의 정확한 정의에 달려 있습니다. ?)
hoffmale 2016 년

3
@PieterB 실제로이 작업을 수행하는 사람이 있습니까? 이제 두 개의 임의의 값으로 BMI를 계산할 때마다 새 Person 인스턴스를 작성해야합니다. 물론 응용 프로그램에서 Persons를 사용하여 시작하고 f (person.length, person.height)와 같은 일을 자주하는 경우 약간 정리할 수 있지만 그룹 매개 변수를 위해 특별히 새 객체를 만드는 것은 지나친 것처럼 보입니다.
Lawyerson

47

Haskell과 같이 이미 이런 식으로 작동하는 많은 언어가 있습니다. Haskell에서 모든 함수는 정확히 하나의 인수를 사용하고 정확히 하나의 값을 반환합니다.

n 개의 인수를받는 함수를 n-1 개의 인수를 취하는 함수로 대체하고 궁극적 인 인수를 취하는 함수를 반환 할 수 있습니다. 이것을 재귀 적으로 적용하면, 임의의 수의 인수를 취하는 함수를 정확히 하나의 인수를 취하는 함수로 대체 할 수 있습니다. 이 변환은 알고리즘에 의해 기계적으로 수행 될 수 있습니다.

이것을 1950 년대에 광범위하게 연구 한 Haskell Curry, 1924 년에 그것을 설명했던 Moses Schönfinkel, 1893 년에 그것을 예고 한 Gottlob Frege에 이어 Frege-Schönfinkeling, Schönfinkeling, Schönfinkel-Currying 또는 Currying이라고합니다.

다시 말해, 인수의 수를 제한하면 영향이 거의 없습니다.


2
물론 함수가 반환되도록 허용하는 경우입니다. 그렇지 않더라도 메인 프로그램에서 다음 함수를 호출하기 만하면됩니다. 즉, 1 + 1 + 1을 가질 수 있습니다. 첫 번째 추가는 추가 추가를위한 함수를 반환하는 함수이거나 단순히 두 번 호출 할 수 있습니다. 후자의 스타일은 이론적으로 더 깔끔하거나 내가 틀렸을 까?

5
"정확한 영향이 없습니다"-OP의 질문은 코드의 준비가 증가 또는 감소하는지에 대한 것이 었습니다. 언어에 대한 이러한 디자인 결정이 그에 영향을 미치지 않는다고 주장하지 않습니까?
Doc Brown

3
@DocBrown 적절한 힘과 연산자 오버로드로 카레 언어를 사용하여 커리되지 않은 언어처럼 보이게 할 수 있습니다. 예 : 체인을 시작하고 체인 을 확장 하기 위해 f *(call_with: a,b,c,d,e) 과부하 call_with :가 걸리고 LHS 에서 체인의 각 내용을 한 번에 하나씩 전달 하여 호출 하십시오. 충분히 약한 연산자 오버로드 시스템은 구문을 성가 시게하지만 이는 무엇보다도 연산자 오버로드 시스템의 결함입니다. ,*f
Yakk

실제로 Haskell의 카레는 n 개의 인수가있는 함수를 n 개의 인수가있는 다른 함수를 반환하는 하나의 인수가있는 함수로 줄입니다.
Ryan Reich

2
@RyanReich 당신은 타입 시그니처에서 Haskell 함수의 "인수 개수"의 "고스트"를 볼 수 있습니다. 일반적으로 당신이 서명의 마지막 유형의 변수인지 여부를 알 수있는 방법이 없기 때문에 그것은 유령이 아닌 진정한 서명입니다 또한 기능 유형을. 어쨌든이 유령은 Haskell에서 모든 함수가 1 인수를 사용하고 함수가 아닌 값 또는 1 인수를 취하는 다른 함수를 반환한다는 사실을 무효화하지 않습니다. 이것은-> : a-> b-> c is a-> (b-> c)의 연관성에 내장되어 있습니다. 그래서 당신은 대부분 여기 잘못입니다.
Ian

7

나는 지난 몇 주 동안 J 컴퓨터 언어를 배우려고 노력하는 데 시간을 보냈습니다. J에서는 거의 모든 것이 연산자이므로 "monads"(한 개의 인수 만있는 함수)와 "dyads"(두 개의 인수가있는 함수) 만 얻을 수 있습니다. 더 많은 인수가 필요한 경우 배열로 제공하거나 "상자"로 제공해야합니다.

J는 매우 간결 할 수 있지만 이전의 APL과 마찬가지로 매우 암호가 될 수 있습니다. 그러나 이는 대부분 수학 간결성을 모방하려는 제작자의 목표의 결과입니다. 문자 대신 이름을 사용하여 연산자를 작성하여 J 프로그램을 더 읽기 쉽게 만들 수 있습니다.


아, 배열이 자신과 상호 작용할 수 있습니다.

5

개발자를 제한하는 방법에 기반한 언어는 언어 개발자가 프로그래머가 자신의 요구를 이해하는 것보다 각 프로그래머의 요구를 더 잘 이해한다는 가정에 달려 있습니다. 이것이 실제로 유효한 경우가 있습니다. 예를 들어, 뮤텍스와 세마포어를 사용한 동기화가 필요한 멀티 스레드 프로그래밍에 대한 제약은 많은 프로그래머들이 "좋은"것으로 간주합니다. 대부분의 프로그래머는 이러한 제약이 그들에게 숨겨져있는 근본적인 기계 별 복잡성을 완전히 인식하지 못하기 때문입니다. 마찬가지로, 멀티 스레드 가비지 수집 알고리즘의 뉘앙스를 완전히 파악하고 싶은 사람은 거의 없습니다. 프로그래머가 너무 많은 뉘앙스를 인식하게 만드는 것보다 GC 알고리즘을 깨뜨리지 않는 언어가 선호됩니다.

언어 개발자로서 자신의 언어를 사용하는 프로그래머보다 인수 전달이 훨씬 우수하여 해로운 것으로 간주되는 일을 방해하는 데 가치가있는 이유에 대해 올바른 주장을해야합니다. 나는 그것이 어려운 주장이라고 생각합니다.

또한 프로그래머 제약 조건 을 해결할 수 있음을 알아야합니다 . 3 개 이상의 인수가 필요한 경우 카레와 같은 기술을 사용하여 인수를 적은 인수 호출로 변환합니다. 그러나 이것은 종종 가독성을 향상시키기보다는 가독성을 희생 시킵니다.

내가 이런 종류의 규칙으로 알고있는 대부분의 언어는 제한된 기능 세트로 실제로 작동 할 수 있음을 보여주기 위해 설계된 언어 인 esolang입니다. 특히, 모든 문자가 opcode 인 esolang은 opcode 목록을 짧게 유지해야하기 때문에 인수 수를 제한하는 경향이 있습니다.


이것이 가장 좋은 대답입니다.
Jared Smith

1

두 가지가 필요합니다.

  • 폐쇄
  • 복합 데이터 유형

Jörg W Mittag가 작성한 답변 을 설명하기 위해 수학적 예제를 추가하겠습니다 .

가우스 함수를 고려하십시오 .

가우스 함수에는 모양에 대한 두 가지 매개 변수, 즉 평균 (곡선의 중심 위치)과 분산 (곡선의 펄스 폭과 관련)이 있습니다. 두 개의 매개 변수 외에, x평가하기 위해 자유 변수의 값을 제공해야 합니다.

첫 번째 단계에서는 세 가지 매개 변수, 즉 평균, 분산 및 자유 변수를 모두 사용하는 가우스 함수를 설계합니다.

두 번째 단계에서는 평균과 분산을 하나로 결합하는 복합 데이터 형식을 만듭니다.

세 번째 단계에서는 두 번째 단계에서 만든 복합 데이터 형식에 바인딩 된 가우스 함수를 만들어 가우시안 함수의 매개 변수화를 만듭니다.

마지막으로, 자유 변수의 값을 전달하여 세 번째 단계에서 생성 된 클로저를 평가 x합니다.

따라서 구조는 다음과 같습니다.

  • 평가 (계산)
    • 매개 변수화 된 가우시안 (클로저 : 수식 및 일부 바운드 변수)
      • GaussianParameters (복합 데이터 유형)
        • 평균 (값)
        • 분산 (값)
    • X (자유 변수의 값)

1
  1. 거의 모든 프로그래밍 언어에서 일부 유형의 목록, 배열, 튜플, 레코드 또는 객체를 유일한 인수로 전달할 수 있습니다. 유일한 목적은 다른 아이템을 개별적으로 함수에 전달하는 대신 보유하는 것입니다. 일부 Java IDE에는 " Extract Parameter Object "기능이 있습니다. 내부적으로 Java는 배열을 만들고 전달하여 가변 개수의 인수를 구현합니다.

  2. 가장 순수한 형태로 이야기하고 싶은 것을하고 싶다면 람다 미적분학을 봐야합니다. 정확히 당신이 설명하는 것입니다. 웹을 검색 할 수 있지만 나에게 맞는 설명은 유형 및 프로그래밍 언어에 있습니다.

  3. HaskellML 프로그래밍 언어를 살펴보십시오 (ML이 더 간단합니다). 그것들은 람다 미적분학을 기반으로하며 개념적으로 기능 당 하나의 매개 변수 만 가지고 있습니다 (조금 찡그린 경우).

  4. Josh Bloch의 항목 2는 "많은 생성자 매개 변수에 직면 할 때 빌더를 고려하십시오." 이것이 얼마나 장황한 지 알 수 있지만 이런 식으로 작성된 API로 작업하는 것은 기쁘게 생각합니다.

  5. 일부 언어에는 매개 변수의 이름이 지정되어 있는데, 이는 거대한 메소드 서명을 훨씬 쉽게 탐색 할 수있는 또 다른 방법입니다. Kotlin은 예를 들어 인수명명했습니다 .

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