2016-08-09 2 views
0

아래는 JavaScript와 유사한 구문으로 설명하고 싶은 의사 코드입니다.변수에 액세스 할 때 평가되는 프로그래밍 언어가 있습니까?

const func1 = (x => x * x); // JavaScript Arrow Function syntax. 
const func2 = (x => {log("I'm func2!"); return x + 1;}); 

var a; 
var b <= func1(a); // `<=` is a *Binding* operator. 
var c <= func2(b); 

a = 1; 
log(c); // Logs "I'm func2!", and then logs 2, which is ((a * a) + 1). 
log(b); // Logs 1, which is (a * a). 

a = 2; 
log(c); // Logs "I'm func2!", and then logs 5, which is ((a * a) + 1). 
log(b); // Logs 4, which is (a * a). 

// When b or c is accessed, the function for it is called and make the value. 

위에서 설명한 개념을 가진 프로그래밍 언어가 있습니까?

+1

하스켈 ('순수한'기능 언어 중 하나 인)과 같은 기능 언어를 살펴볼 수 있습니다. – DAXaholic

+2

지연 평가? https://en.wikipedia.org/wiki/Lazy_evaluation – Wickramaranga

+1

엑셀 스프레드 시트는 이런 종류의 작업을합니다. – svick

답변

0

프로그래밍 언어의 주요 평가 전략은 게으른 (예를 들어, 통화로 이름)과 엄격한 (예를 들어, 통화로 값). 게으른 언어는 필요할 때만 표현식을 평가합니다. 엄격한 언어는 표현을 열정적으로 평가합니다. 구체적으로 차이는 일반적으로 함수 호출에서 발생합니다. 지연된 언어는 인수를 평가되지 않은 함수에 전달하고 엄격한 언어는 인수를 평가 한 다음 함수를 호출합니다. 읽을 수있는 많은 상충 관계가 있습니다 (예 : https://en.wikipedia.org/wiki/Evaluation_strategy.

그러나 코드 예제에서는 b에 대한 바인딩이 어떻게 작동합니까? 언어가 엄격하거나 게으른 지 여부에 관계없이 아직 묶지 않은 a의 값을 사용하려고하기 때문에 문제가 발생합니다. 이는 프로그래밍 언어 디자인에서 두 번째 매개 변수 인 정적 및 동적 범위를 가져옵니다. 정적 범위 언어에서 변수의 범위는 정적으로 결정됩니다. 즉, func1에 전달 된 "a"는 func1이 호출 될 때 범위에있는 것입니다. 동적 범위 언어에서 변수의 범위는 런타임에 결정되므로 func1 (a)가 느리게 평가되는 경우를 상상할 수 있습니다.이 경우 해당 시점의 범위는 a에 대한 할당 이후의 범위입니다.

그러나 정적 범위와 동적 범위의 문제는 대부분 해결 된 것입니다. 정적 범위는 거의 항상 올바른 대답입니다. 일부 언어는 동적 범위 (예 : 이전 LISP)를 사용하려고했지만 사람들이 혼란 스러울 정도로 정적 범위로 전환했습니다.

요약하면, 나는 당신이 묘사하는 방식으로 작동하는 언어를 상상할 수 있지만, 대부분의 사람들은 사용하기가 매우 어려울 것 같을 것입니다.

+0

그렇게 나쁘지는 않습니다 - 비록 적어도 대부분의 리스프에서 어휘 스코프를 가지고 있더라도 최상위 정의는 동적으로 바인딩됩니다 (그렇지 않으면 repl에서 재정의 할 수없고 letrec과 같은 것을 사용해야 할 것입니다) 또는 Y 결합자를 사용하여 재귀 정의를 작성할 수 있음). – dercz

0

나는 그런 언어를 모른다. 그러나 나는 그것에 대한 다른 전략을 알고있다 : 당신은 람다 객체에서 다시 호출을 감쌀 수있다. 그것은 당신이 묘사 한 것과 같은 효과를 가질 것입니다. 예 : Lisp에서는 다음을 할 수 있습니다 :

(defun some-func (x) (* x x)) 
(defvar *a* (lambda() (some-func 4))) 
*a* ;; => returns the function 
(*a*) ;; => returns 16 

거의 모든 오늘날의 언어에서 가능합니다. C조차도 그렇지만, 꽤 어려워지고 있습니다.

+0

이렇게하면 가치 평가를 할 수는 있지만 값을 변경할 수 있습니까? – dercz

+0

사용 된 람다를 "변경"하는 것으로 바꾸면 다음과 같이 할 수 있습니다 :'(setf * a * (lambda() (some-func 10))' –

0

정말 재미있는 우연의 일치! 나는 월요일부터 존재하는이 특성을 가진 하나의 언어를 알고있을 것입니다. 여기에 : https://github.com/drcz/ZJEB

이것은 부분적으로 농담이고 부분적으로는 표현력이 있어야합니다. 여기 예와 REPL 세션입니다 :

(-- ALGORITHMIC LANGUAGE ZJEB v0.1 --) 
copyleft 2016/08/08 by Scislav Dercz 
type (halt) to quit 

READY. 
>(def func1 (bind (x) (* x x))) 
(new shorthand func1 memoized) 
>(def func2 (bind (x) (+ x 1))) 
(new shorthand func2 memoized) 
>(def a 1) 
(new shorthand a memoized) 
>(def b (func1 a)) 
(new shorthand b memoized) 
>(def c (func2 b)) 
(new shorthand c memoized) 
>c 
2 
>b 
1 
>(def a 2) 
(new shorthand a memoized) 
>c 
5 
>b 
4 

는 여기에 간단한 하나

>(def x 5) 
(new shorthand x memoized) 
>(def y (* x x)) 
(new shorthand y memoized) 
>y 
25 
>(def x 3) 
(new shorthand x memoized) 
>y 
9 

것은이 제도는 달리, 인 (또는 내가 아는 다른 혀짤배기)는이 "DEF"형태는 않습니다 두 번째 피연산자를 평가하지 않습니다 - 주어진 표현식에 대한 구문 상 "속기 (shorthand)"를 만듭니다. 따라서 평가자가 심볼을 발견 할 때마다, 환경에서 그것을 찾는다. (즉, "bind"형식으로 만들어진 가변 값 바인딩 - lisp의 "lambda"형식의 다중 케이스 패턴 일치 변형) , 실패하면 정의 목록도 검사합니다. 성공하면 즉시 대응하는 표현식을 평가합니다.

언어가 순전히 기능적이기 때문에 설명하는 것을하기위한 것이 아니며 일반적으로 유용하지는 않습니다. 현재 구현에서 평가자에게 조금 더 많은 작업을 수행하도록 강요합니다. 속기를 다시 정의하는 유일한 이유는 repl로 작업하는 편의를위한 것입니다. 실제로 무한한 표현 다나 스콧의 "흐름 다이어그램의 격자"의 정신에

(bind (0) 1 
     (n) (* n ((bind (0) 1 
         (n) (* n ...)) (- n 1))) 

을 의미하는

(def fact (bind (0) 1 
       (n) (* n (fact (- n 1))))) 

같은 재귀 적 정의에 대해 생각하고 싶었 기 때문에이 "기능"에있다. 당신이 그들을 평가하려고 할 때 아마뿐만 아니라 [부분적으로-게으른 평가 또는 무언가에 의해] 그들이 합법적해야하지만 무한 데이터 구조

(def evil `(ha ,evil)) 

같은 인터프리터를 중단 할

주 ..

질문으로 돌아가서, 적어도 특정 데이터 유형에 대해 요구되는 행동을 제공하는 다양한 Functional Reactive Programming 언어/프레임 워크를 살펴보십시오.

Svik의 의견도 매우 훌륭합니다. 스프레드 시트 수식은 이런 식으로 작동합니다 (일부 사람들은 FRP 언어라고 주장합니다).

(게으른 평가 대상은 내가 알지 못하는 "게으른"언어의 변수 범위가 어휘 적이기 때문에 - 게으름 + 동적 범위 지정은 위의 mcoblenz처럼 너무 혼란 스러울 수 있습니다.)

0

지연 평가는 하스켈 프로그램을 평가하는 방법입니다. 표현식은 변수에 바인딩 될 때 평가되지 않지만 다른 계산에 의해 결과가 필요할 때까지 평가가 연기된다는 것을 의미합니다. https://wiki.haskell.org/Lazy_evaluation

0

당신이 필요로하는 것은 이름 별 및 변경 가능한 변수입니다. 이름이 부름 (선택 사항) 인 가장 초기 언어 중 하나는 Algol 60입니다.

(선택 사항) call-by-name이있는 최신 언어는 Scala입니다. b: => Int 같은 선언

def log(a: Any) = println(a) 

def func1(x: => Int) = x * x 
def func2(x: => Int) = { 
    log("I'm func2!") 
    x + 1 
} 

var a = 0 

def rest1(b: => Int) = { 
    def rest2(c: => Int) = { 
    a = 1 
    log(c); // Logs "I'm func2!", and then logs 2, which is ((a * a) + 1). 
    log(b); // Logs 1, which is (a * a). 

    a = 2; 
    log(c); // Logs "I'm func2!", and then logs 5, which is ((a * a) + 1). 
    log(b); // Logs 4, which is (a * a). 
    } 
    rest2(func2(b)) 
} 
rest1(func1(a)) 

매개 변수 호출 별 이름 (b: Int 전화별로 값이 될 수있는 반면)입니다 : 여기 스칼라 포트 샘플 코드입니다.

관련 문제