대부분의 언어에서 바인딩이 기본 기능이 아닌 이유는 무엇입니까?


11

변수를 다른 변수 나 표현식에 바인딩하는 IMHO는 수학에서 매우 일반적인 시나리오입니다. 사실, 많은 학생들은 처음에 할당 연산자 (=)가 일종의 구속력이 있다고 생각합니다. 그러나 대부분의 언어에서 바인딩은 기본 기능으로 지원되지 않습니다. C #과 같은 일부 언어에서는 일부 조건이 충족되는 경우 바인딩이 지원됩니다.

그러나 IMHO를 이것을 기본 기능으로 구현하는 것은 다음 코드를 변경하는 것만 큼 간단했습니다.

int a,b,sum;
sum := a + b;
a = 10;
b = 20;
a++;

이에-

int a,b,sum;
a = 10;
sum = a + b;
b = 20;
sum = a + b;
a++;
sum = a + b;

모든 명령어가 오른쪽에있는 표현식에 포함 된 변수의 값을 변경 한 후 바인딩 명령어를 할당으로 배치하는 것을 의미합니다. 그런 다음 중복 명령어 트리밍 (또는 컴파일 후 어셈블리 최적화)이 수행됩니다.

따라서 대부분의 언어에서 기본적으로 지원되지 않는 이유는 무엇입니까? 특히 C 언어 군에서?

최신 정보:

다른 의견으로는이 제안 된 "바인딩"을보다 정확하게 정의해야한다고 생각합니다.

  • 이것은 단방향 바인딩입니다. 합계 만 a + b에 바인딩되며 그 반대도 마찬가지입니다.
  • 바인딩 범위는 로컬입니다.
  • 바인딩이 설정되면 변경할 수 없습니다. 즉, 일단 합이 a + b에 바인딩되면 합은 항상 a + b가됩니다.

아이디어가 더 명확 해지기를 바랍니다.

업데이트 2 :

방금 이 P # 기능을했습니다 . 앞으로있을 수 있기를 바랍니다.


14
이 기능을 C에 추가하려고 시도한 컴파일러 개발자가 찾아서 쏘 였기 때문일 수 있습니다.
피트 윌슨

나는 양방향이 아닌 단방향 (오른쪽에서 왼쪽으로) 바인딩에 대해 이야기하고 있습니다. 바인딩은 항상 하나의 변수에만 영향을 미칩니다.
Gulshan

2
가치가있는 것에 대해 이런 종류의 프로그래밍 관점은 반응 형 프로그래밍입니다. 당신이 설명하는 것은 본질적으로 스테로이드에 대한 데이터 바인딩 (또는 반응성 프로그래밍) 인 Excel과 같은 스프레드 시트 프로그램으로 구체화됩니다.
Mike Rosenblum

11
그것은 "가장"프로그래밍 언어의 기능하지 않을 수 있습니다, 그러나 그것은 이다 의 기능 에서 가장 인기있는 프로그래밍 언어 : 엑셀.
Jörg W Mittag

2
표현식 트리 덕분에 C #에서 이미 가능합니다. 나는 어제 그것에 대해 블로그를 작성했다 : happynomad121.blogspot.com/2013/01/…
HappyNomad

답변:


9

프로그래밍과 수학을 혼동하고 있습니다. 함수형 프로그래밍조차도 많은 아이디어를 빌려서 프로그래밍하고 실행하기 위해 사용할 수있는 것으로 바꾸더라도 완전히 수학적인 것은 아닙니다. 명령형 프로그래밍 (대부분의 C에서 영감을 얻은 언어, JavaScript 및 예외적 인 C #에 대한 예외는 예외)은 수학과 거의 관련이 없으므로 왜 이러한 변수가 수학의 변수처럼 동작해야합니까?

이것이 항상 원하는 것은 아니라는 점을 고려해야합니다. 많은 사람들이 루프에서 생성 된 클로저에 물린 경우가 있습니다. 클로저는 변수가 특정 시점에 값의 사본이 아니라 변수를 유지하기 때문 입니다. 즉, for (i = 0; i < 10; i++) { var f = function() { return i; }; /* store f */ }10 개의 클로저가 생성 9됩니다. 따라서 두 가지 방법을 모두 지원해야합니다. 즉 "복잡성 예산"에 비해 두 배의 비용과 또 다른 운영자가 필요합니다. 타입 시스템이 충분히 정교하지 않다면 (이를 더 복잡하게하지 않는 한) 이것을 사용하는 코드와 이것을 사용하지 않는 코드 사이의 비 호환성 일 수도 있습니다.

또한 이것을 효율적으로 구현하는 것은 매우 어렵습니다. 순진한 구현은 모든 과제에 일정한 오버 헤드를 추가하여 명령형 프로그램에 빠르게 추가 될 수 있습니다. 다른 구현에서는 변수를 읽을 때까지 업데이트가 지연 될 수 있지만, 변수를 다시 읽지 않아도 훨씬 더 복잡하고 여전히 오버 헤드가 있습니다. 똑똑한 컴파일러는 두 가지 모두를 최적화 할 수 있지만, 똑똑한 컴파일러는 드물고 작성하기 위해 많은 노력을 기울입니다 (특히 변수가 광범위하고 멀티 스레딩이 작동하는 경우 예제 에서처럼 간단하지는 않습니다).

참고 있다는 반응 프로그래밍 (지금까지 내가 말할 수있는) 이것에 대해 기본적으로, 그래서 존재 않습니다. 전통적인 프로그래밍 언어에서는 그렇게 일반적이지 않습니다. 그리고 이전 단락에 나열된 구현 문제 중 일부가 해결되었습니다.


나는 당신이 3 점을 가지고 있다고 생각합니다-1) 필수 스타일 프로그래밍이 아닙니다. 요즘 대부분의 언어는 일부 패러다임에 국한되지 않습니다. 나는 이것이이 패러다임 스타일에서 벗어나는 것이 좋은 논리라고 생각하지 않습니다. 2) 복잡성. 더 복잡한 것들이 이미 지원되고 있음을 보여주었습니다. 왜 이러지 않습니까? 거의 사용하지 않는 연산자가 지원되고 있음을 알고 있습니다. 그리고 이것은 완전히 새로운 기능입니다. 어떻게 호환성 문제가 생길 수 있습니까? 나는 무언가를 바꾸거나 지우지 않습니다. 3) 어려운 구현. 현재 컴파일러는 이미 이것을 최적화 할 수있는 능력을 가지고 있다고 생각합니다.
Gulshan

1
@Gulshan : (1) 프로그래밍 패러다임은 수학이 아닙니다 . FP는 가깝지만 FP는 비교적 드물며 가변 변수가있는 불순한 FP 언어는 이러한 변수를 수학에서 온 것처럼 취급하지 않습니다. 이것이 존재하는 하나의 패러다임은 반응성 프로그래밍이지만, 반응성 프로그래밍은 알려져 있지 않거나 널리 사용되지 않습니다 (전통적인 프로그래밍 언어에서). (2) 모든 것은 다소 복잡한 비용과 가치가 있습니다. 이 때문에 내가 추가하려는 첫 번째 것은 아니다, 몇 도메인을 제외하고 다소 높은 비용과 이럴 상대적으로 작은 값을 갖는 는 특별히 이러한 도메인을 대상으로하지 않는 언어입니다.

상자에 도구가 하나 더없는 이유는 무엇입니까? 도구가 있으면 사람들이 도구를 사용합니다. 질문. C 또는 C ++와 같은 언어가이 기능을 구현하고 의견을 요청하려면 "주지 마십시오. 너무 어려워 사람들이 엉망이 될 것입니다."라고 말 하시겠습니까?
굴샨

@Gulshan : (3)에 관하여 : 예제 에서처럼 항상 쉬운 것은 아닙니다. 글로벌 범위에 넣으면 갑자기 링크 타임 최적화가 필요합니다. 그런 다음 동적 연결을 추가하면 컴파일 타임에 아무것도 할 수 없습니다 . JIT를 포함 하여 매우 똑똑한 컴파일러 매우 영리한 런타임이 필요합니다. 또한 모든 사소한 프로그램에서 할당량을 고려하십시오. 당신도 나도 이러한 구성 요소를 쓸 수 없습니다. 이 주제에 관심이 있고 관심이있는 사람은 최대 몇 명입니다. 그리고 그들은 더 좋은 일을 할 수 있습니다.

@ Gulshan : C ++에 이미 복잡한 짐승에 기능을 추가하지 말라고 요청하거나 시스템 프로그래밍 이외의 항목에 C를 사용하지 말라고 요청했습니다 (이것은 매우 유용한 도메인 중 하나가 아닙니다) ). 그 외에도, 나는 새로운 기능을 흥미롭게 여기고 있지만 복잡한 예산이 충분하지 않은 경우 (많은 언어는 항상 소진되었습니다)이 기능은 언어가 의도 한 바에 유용합니다-이전에 말했듯이 이것이 유용한 몇 개의 도메인 일뿐입니다.

3

대부분의 프로그래밍 모델에는 적합하지 않습니다. 그것은 완전히 통제되지 않은 일종의 거리에서 행동을 나타내며, 단일 할당을 통해 수백 또는 수천 개의 변수와 객체 필드의 값을 파괴 할 수 있습니다.


그런 다음 바인딩 된 변수, 즉 왼쪽이 다른 방법으로 변경되지 않는다는 규칙을 제안하는 것이 좋습니다. 그리고 내가 말하는 것은 양방향이 아닌 단방향 바인딩입니다. 내 질문을 따르면, 당신은 볼 수 있습니다. 따라서 다른 변수는 영향을받지 않습니다.
굴샨

그것은 중요하지 않습니다. 당신이 쓸 때마다 a또는 b, 당신은 모든 단일 장소에 영향을 고려할 필요가 sum사용되며, 당신이 읽을 것을 모든 장소 sum당신이 무엇을 고려해야 a하고 b일을합니다. 사소한 경우, 특히 실제 표현식이 sum런타임에 변경 될 수있는 경우에는 복잡해질 수 있습니다.
jprete

바인딩이 완료되면 바인딩 표현식을 변경할 수 없다는 규칙을 권장합니다. 할당조차 불가능합니다. 식에 바인딩되면 반 상수와 같습니다. 즉, 합계가 a + b에 바인딩되면 프로그램의 나머지 부분에서는 항상 a + b가됩니다.
Gulshan

3

나중에 알다시피, Web2.0 환경에서 반응 프로그래밍이 시원 할 수 있다고 생각합니다. 느낌이 왜? 글쎄, 나는 테이블 셀 onClick 이벤트에 대한 응답으로 항상 변경되는 테이블 인이 페이지를 가지고있다. 셀 클릭은 종종 열 또는 행에서 모든 셀의 클래스를 변경하는 것을 의미합니다. 이는 다른 관련 셀을 찾기 위해 getRefToDiv () 등의 무한 루프를 의미합니다.

IOW, 내가 작성한 ~ 3000 줄의 많은 JavaScript는 객체를 찾는 것 외에는 아무것도하지 않습니다. 반응 형 프로그래밍은 적은 비용으로 모든 것을 할 수 있습니다. 코드 줄이 크게 줄었습니다.

당신은 그것에 대해 어떻게 생각하십니까? 예, 테이블에 스프레드 시트와 유사한 기능이 많이 있습니다.


3

나는 당신이 묘사하는 것을 스프레드 시트라고 생각합니다.

A1=5
B1=A1+1
A1=6

... B1반품 평가 7.

편집하다

C 언어를 "휴대용 어셈블리"라고도합니다. 스프레드 시트 등은 선언적인 언어 인 반면 필수 언어입니다. 변경시 재평가를 말하고 B1=A1+1기대 B1하는 A1것은 분명히 선언적입니다. 기능적 언어가 하위 집합 인 선언적 언어는 일반적으로 하드웨어 작동 방식과는 거리가 멀기 때문에 상위 언어로 간주됩니다.

관련 메모에서, 래더 로직과 같은 자동화 언어는 일반적으로 선언적입니다. 당신이 말하는 논리의 렁 작성하는 경우 output A = input B OR input C는 것 지속적으로 그 문을 재-평가하고, A언제든지 변경할 수 있습니다 B또는 C변경. 기능 블록 다이어그램 (Simlink를 사용한 경우 익숙 할 수있는)과 같은 다른 자동화 언어도 선언적이며 지속적으로 실행됩니다.

일부 (임베디드) 자동화 장비는 C로 프로그래밍되며, 실시간 시스템 인 경우 래더 로직이 실행되는 방식과 유사하게 로직을 반복해서 다시 실행하는 무한 루프가있을 수 있습니다. 이 경우 메인 루프 내에서 다음을 작성할 수 있습니다.

A = B || C;

... 항상 실행되므로 선언적입니다. A지속적으로 재평가됩니다.


3

C, C ++, 오브젝티브 -C :

블록 은 원하는 바인딩 기능을 제공합니다.

귀하의 예에서 :

합 : = a + b;

당신은 설정하는 sum식으로 a + b어디 맥락에서 ab변수를 기존 있습니다. C, C ++ 또는 Objective-C의 "블록"(일명 클로저, 일명 람다 식)을 사용하여 Apple 확장 (pdf) 을 사용하여 정확하게 수행 할 수 있습니다 .

__block int a = 0, b = 0;           // declare a and b
int (^sum)(void);                   // declare sum
sum = ^(void){return a + b;};       // sum := a + b

이것은 suma와 b의 합을 반환하는 블록으로 설정 됩니다. __block스토리지 클래스 지정자는 것을 나타냅니다 ab변경 될 수 있습니다. 위의 내용을 감안할 때 다음 코드를 실행할 수 있습니다.

printf("a=%d\t b=%d\t sum=%d\n", a, b, sum());
a = 10;
printf("a=%d\t b=%d\t sum=%d\n", a, b, sum());
b = 32;
printf("a=%d\t b=%d\t sum=%d\n", a, b, sum());
a++;
printf("a=%d\t b=%d\t sum=%d\n", a, b, sum());

출력을 얻으십시오.

a=0      b=0     sum=0
a=10     b=0     sum=10
a=10     b=32    sum=42
a=11     b=32    sum=43

블록을 사용하는 것과 제안하는 "바인딩"의 유일한 차이점은의 빈 괄호 쌍입니다 sum(). 차이 sumsum()표현 및 그 표현의 결과 사이의 차이이다. 함수와 마찬가지로 괄호는 비워 둘 필요가 없습니다. 블록은 함수와 마찬가지로 매개 변수를 사용할 수 있습니다.


2

C ++

일반으로 업데이트되었습니다. 리턴 및 입력 유형에서 매개 변수화되었습니다. 매개 변수화 된 유형을 만족하는 모든 이진 연산을 제공 할 수 있습니다. 코드는 요청시 결과를 계산합니다. 결과를 얻을 수 있으면 결과를 다시 계산하지 않습니다. 이것이 바람직하지 않은 경우이 문제를 해결하십시오 (부작용으로 인해 포함 된 물체가 크기 때문에 무엇이든).

#include <iostream>

template <class R, class A, class B>
class Binding {
public:
    typedef R (*BinOp)(A, B);
    Binding (A &x, B &y, BinOp op)
        : op(op)
        , rx(x)
        , ry(y)
        , useCache(false)
    {}
    R value () const {
        if (useCache && x == rx && y == ry) {
            return cache;
        }
        x = rx;
        y = ry;
        cache = op(x, y);
        useCache = true;
        return cache;
    }
    operator R () const {
        return value();
    }
private:
    BinOp op;
    A &rx;
    B &ry;
    mutable A x;
    mutable B y;
    mutable R cache;
    mutable bool useCache;
};

int add (int x, int y) {
    return x + y;
}

int main () {
    int x = 1;
    int y = 2;
    Binding<int, int, int> z(x, y, add);
    x += 55;
    y *= x;
    std::cout << (int)z;
    return 0;
}

질문에 대한 답변은 아니지만 귀하가 제시 한 아이디어가 마음에 듭니다. 보다 일반적인 버전이있을 수 있습니까?
굴샨

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