Back to list
Sep 6 2017
CX

CX 개요

CX 소개

CX는 어포던스 이론에 기반하여 새로운 프로그래밍 패러다임을 수용하도록 설계된 지침 및 프로그래밍 언어입니다. 어포던스는 프로그램이 어떤 어떤 작업을 할 수 있는지, 없는지를 알려줍니다. 예를 들면, 우리는 프로그램에 어떤 인수를 함수에 보낼 수 있는지를 물어볼 수 있으며, 프로그램은 가능한 실행 목록을 반환합니다. 목록에서 어떤 작업이 적절할 지 결정 후, 우리는 옵션 중 하나를 선택할 수 있고, 프로그램은 선택한 작업을 적용할 것입니다. CX의 어포던스 시스템은 유전 프로그래밍 알고리즘이 구축되었으며 기본 함수로 제공되고, 이것은 런타임 도중 프로그램의 구조를 최적화 하는데 이용될 수 있습니다.

CX 사양은 컴파일러와 인터프리터 모두 프로그래머가 액세스 할 수 있어야 한다고 명시합니다. 인터프리터는 읽기-평가-출력(read-eval-print) 루프를 통해 접근할 수 있으며, 어디서든지 프로그래머가 요소를 대화식으로 추가 또는 제거할 수 있습니다. 일단 프로그램이 끝나면, 성능을 높이기 위해 그것을 컴파일 할 수 있습니다.

CX의 타이핑 시스템은 매우 엄격합니다. 유일한 “암시적 형변환"은 파서가 무엇이 integer, float, boolean, string, 또는 배열(array)형인지 결정할 때 발생된다. 만약 함수가 64비트 integer형을 필요로 하는 경우, 예를 들면, 명시적으로 요구 타입으로 변환하기 위해 형변환 함수를 사용해야 합니다.

마지막으로, CX 프로그램은 실행 상태와 구조를 유지하면서 바이트 배열로 완전히 직렬화 될 수 있습니다. 이 직렬화 된 버전의 프로그램은 나중에 비 직렬화 될 수 있으며, CX 인터프리터/컴파일러가 있는 모든 장치에서 해당 프로그램의 실행을 계속할 수 있습니다.

다음 섹션에서는, 위 단락에서 설명한 CX 기능에 대해 자세히 설명합니다.

프로젝트 레파지토리

프로젝트 소스코드는 Github 레파지토리에서 다운로드할 수 있습니다.: https://github.com/skycoin/cx. 이 레파지토리에는 명세 파일, 문서, 예제 및 소스코드 자체가 포함됩니다.

문법

소개에서 언급했듯이 CX는 명세 및 프로그래밍 언어입니다. CX 명세는 문법을 강요하지는 않지만, CX로 간주되기 위해서는 CX 전용언어를 통해 반드시 구조와 프로세스가 실행되어야 한다. 결과적으로 이것은 두 가지의 CX 전용언어를 사용할 수 있습니다. 하나는 Lisp과 유사한 문법이며, 다른 하나는 C와 유사한 문법입니다. 이 기반 언어는 CX 기반 또는 “기본언어"라고 합니다. 이 문서에서, 구현은 사양을 보여주기 위해 사용되지만, 이것의 목적은 학술도구만으로 사용되는 것이 아니라, 일반적인 목적으로 사용될 수 있는 완성된 언어가 되는 것입니다.

이 문서에서 사용된 CX는 가능한 한 Go 문법과 유사한 문법을 사용하는 목표를 가지고 있습니다.

어포던스

프로그래머는 프로그램을 구성하는 동안 많은 결정을 내려야 합니다. 예를 들면, 함수가 얼마나 많은 매개변수를 받아야 하는지, 얼마나 많은 파라미터가 반드시 반환되야 하는지, 원하는 기능을 얻기 위해 어떤 명령문을 하용해야 하며, 무엇을 통해야 하는지 등이 말입니다. CX 내 어포던스 시스템을 쿼리하여 요소에 적용할 수 있는 가능한 작업 목록을 얻을 수 있습니다. 이 구문에서, 요소의 예는 함수, 구조, 모듈 그리고 표현식이 있습니다.

프로그램의 논리와 목적이 무엇이 되어야 하는지를 규정하는 일련의 규칙과 사실이 없어도 최소한 프로그램의 의미 상 정확성을 보장하는 몇 가지 기본 제한을 결정할 수 있습니다. 어포던스 시스템은 첫 번째 필터링 레이어와 같은 제한사항을 제공하며 아래에서 설명하겠습니다.

제한 사항

CX의 표현식은 여러 값을 반환할 수 있습니다. 이는 표현식의 출력 인수를 받는 변수의 수는 표현식의 연산자에 의해 정의된 출력의 수와 일치해야 하기 때문에 어포던스 시스템에 대한 문제점을 발생시킵니다.

out1, out2, ..., outN := op(inp1, inp2, ..., inpM)

만약 위의 예제가 올바르다면, opN 인수를 출력해야 합니다. 이 문제는 더욱 큰 문제가 될 수 있는데, 만약 우리가 알고 있는 op의 정의가 어포던스 시스템 자체나 사용자에 의해 나중에 바뀔 수 있고 : op의 정의가 바뀌자마자, 새로운 어포던스는 오퍼레이터로써 op를 사용하여 어떤 구문이라도 접근할 수 있습니다. 왜냐하면 op의 출력 인수를 받은 많은 수의 변수는 이제 일치하지 않기 때문입니다.

이전 논리는 또한 수식 변수의 개수와 수식 연산자의 출력 매개 변수 개수가 일치하면, 더 이상 새로운 수식 변수를 추가하는 작업을 수행할 수 없다는 것을 의미합니다.

Arity 제한은 표현식의 입력 인수에도 적용됩니다. 예를 들어, 함수 호출에 이미 입력 인수가 모두 정의되어 있는 경우, 어포던스 시스템은 가능한 행위에 대한 다른 인수를 리스트에 추가하지 않아야 합니다. 마찬가지로, 표현식이 필요한 것보다 적은 수의 인수로 연산자를 호출하려고하는 경우, 어포던스 시스템은 조회할 때, 함수 호출에 새로운 인수를 추가할 수 있다는 것을 프로그래머에게 알려야합니다.

예제:

공지 : 문자열 연결은 아직 구현되지 않았습니다. 또한 출력 함수는 항상 출력 중인 문자열의 끝에 새로운 행을 추가합니다. 이 문서에 제시된 CX 구현의 향후 버전에서는 이러한 문제를 해결할 것입니다..

var age i32 = 18
var steps i32 = 23

func advance (direction str, numberSteps i32) () {
    printStr("Advancing:")
    printStr(direction)
    printStr("Number of steps:")
    printI32(numberSteps)
}

func main () () {
    advance("North")
}

위 예제에서, main기능의 advance를 호출하는 것은 하나의 인자가 누락되었습니다. 만약 어포던스 시스템에 질문을 던지면, 그 시스템은 다른 것들과 마찬가지로 다음과 유사한 행동을 취해야만 합니다.:

...
(k)       AddArgument advance age
(k+1)     AddArgument advance steps
...

여기서 k는 임의의 색인을 나타냅니다. 위에서 볼 수 있듯이, 어포던스 시스템은 프로그래머에게 두 가지 동작이 가능하다는 것을 알려주는데, 이전 기능에 다른 인수를 추가할 수 있고, 전역 정의 “age"와 “steps"는 인수로 작용하는 옵션 중 하나로 동작할 수 있습니다.

어포던스는 항상 열거되어야 한다는 것은 주목할 만한 일이며, 그들의 요청은 어포던스 시스템으로 여러차례 호출을 보냅니다. 그 이유는 프로그래머가 쿼리 결과를 검토한 후에 어떤 어포던스가 적용될 것인지를 시스템에 알려주어야 하기 때문입니다.

타입 제한

프로그래밍 언어의 일반적인 동작은 프로그래머가 예기치 않은 유형의 인수를 함수 호출로 보내는 것을 제한하는 입력 시스템을 가지는 것입니다. 취약한 타입의 프로그래밍 언어에서조차도 true / "hello world" 의 경우에 에러를 발생시킬 것입니다. (물론 난해한 언어,가 아닌경우). CX는 매우 엄격한 타이핑 시스템, 을 따르고 예상되는 유형과 정확히 일치하지 않는 인수는 어포던스의 동작 후보군으로 간주될 수 없습니다. (해결책은 어포던스로 표시되기 전에 변환함수 내의 인수들을 묶는 것이지만)

이미 존재하는 변수에 새로운 값을 할당할 때는 타입 제한을 고려해야합니다. CX에서 특정 유형으로 선언된 변수는 모든 수명주기 기간동안 반드시 그 타입으로 남아있어야 합니다. (메타프로그래밍 명령/함수를 통해 제거되거나 새로 작성된 경우를 제외하고) 따라서 32 비트 정수(integer)를 보유하도록 선언된 변수는, 64 비트 부동 소수점 출력 인수(float)를 받을 수 없습니다.

존재 제한

이러한 유형의 제한은 처음에는 사소한 것처럼 보일 수 있습니다.: 요소가 존재하지 않는다면 요소가 포함 된 어포던스도 마찬가지로 존재해서는 안됩니다. 그럼에도 불구하고 이 제한은 우리가 함수의 이름을 변경하는 것을 고려하는 상황이 될 때 문제가 됩니다. 이 함수는 이미 프로그램 전체에서 표현식의 연산자로 사용되었습니다. 프로그램이 소스 코드 형식인 경우, 이 문제는 간단한 “검색 및 바꾸기"프로세스로 축소되지만, 런타임 중이라면, 어포던스 시스템이 매우 유용해집니다.: 어포던스는 이 연산자에 바인딩 된 식별자를 변경할 수 있습니다.

요소의 이름을 변경하지 않는다고 할지라도, 요소가 존재하는지 여부를 알아내는 것은 간단하지 않습니다. 어포던스에서 사용할 요소는 호출 스택의 현재 범위, 전역 범위 및 다른 모듈의 전역 범위에서 검색해야합니다.

식별자 제한 사항

새롭게 명명된 요소를 추가하는 것은 일반적으로 어포던스에 대한 예비 작업입니다. 이러한 유형의 어포던스를 적용하려고 할 때 발생하는 제한은 재 정의를 피하기 위해, 새 요소에 대한 고유한 식별자를 보장하는 것입니다. 어포던스 시스템은 요소의 범위에서 고유 식별자를 생성하거나, 프로그래머에게 적합한 식별자를 제공하도록 요청할 수 있습니다.

경계 제한

CX는 배열 요소에 접근 및 수정할 수 있는 기본 함수를 제공합니다. 배열 판독기와 배열 작성기의 예는 다음과 같습니다.:

readI32([]i32{0, 10, 20, 30}, 3)
writeF32([]f32{0.0, 10.10, 20.20}, 1, 5.5)

첫 번째 표현식에서는, 4 개의 32 비트 정수 배열은 인덱스 3에 접근할 수 있으며, 배열의 마지막 요소를 반환합니다. 두 번째 표현식에서는, 3 개의 32 비트 부동 소수점(floats) 배열의 두 번째 요소가 5.5로 변경되었습니다. 이러한 배열 중 하나라도 음수 인덱스나 배열의 길이를 초과하는 인덱스를 사용하여 접근한 경우 “허용치 초과"오류가 발생합니다.

단지 타입제한에 따라서, 어포던스 시스템은 프로그래머에게 모든 32비트 정수(integer)인수가 어떤 배열이라도 접근할 수 있음을 알립니다. 이러한 프로그램이 컴파일 되더라도, 프로그래머가 적용 대상으로 선택된 것에 대해 특별한 주의를 기울이지 않으면, 경계 오류가 발생할 가능성이 매우 높습니다.

어포던스 시스템은 다음 기준에 따라 어포던스를 필터링해야 합니다.: 음수 32비트 정수를 버리고, 배열 판독기 및 작성기로 보내지는 배열의 길이를 초과하는 32비트 정수를 버립니다.

사용자 정의 제한사항

공지 : 사용자 정의 제한 시스템은 아직 실험 단계에 있습니다.

위에서 설명한 기본 제한 사항은 프로그램이 런타임 오류가 발생하지 않도록 최소한 보장되어야 합니다. 이러한 제약은 CX 고유의 진화 알고리즘과 같은 흥미로운 시스템을 구축하기에 충분해야합니다.

진화 알고리즘. 그럼에도 불구하고 어떤 경우에는 보다 견고한 시스템이 필요합니다. 이 목적을 위해, 절, 쿼리 및 객체를 사용하여 모듈의 환경을 설명합니다. 이러한 요소는 통합된 Prolog 인터프리터와, CX 고유 함수 setClauses , setQueryaddObject를 사용하여 정의됩니다.

이 제한 시스템의 가장 일반적인 설명은 프로그래머가 추가된 각 오브젝트에 대해 정의된 Prolog 구문(사실 및 규칙)이 정의된 Prolog 쿼리를 사용하여 조회될 것이라는 것입니다. 이것을 처음 읽는 사람은 이것이 거의 이해되지 않을 것입니다. 하나의 예제를 통해 개념과 프로세스를 좀 더 명확히 할 필요가 있습니다.:

setClauses("move(robot, north, X, R) :- X = northWall, R = false.")

setQuery("move(robot, %s, %s, R).")

이 예제에서는, 하나의 규칙만 정의됩니다. 이 규칙은 대략 다음과 같이 해석할 수 있는데, “만약 로봇이 북쪽으로 이동하기를 원한다면, X가 무엇인지 요청해야 합니다. 만약 X가 북쪽 벽에 있다면 그것은 움직일 수 없습니다.” 그 쿼리는 단지 형식적인 문자열로써 move 행동을 위한 쿼리에 사용되고, 2개 이상의 인자를 받는 robot인자를 위해 사용됩니다. : 방향, 그리고 객체

addObject 함수를 사용하여 객체를 정의할 수 있습니다.

addObject("southWall")
addObject("northWall")

제한 시스템은 모듈의 각 객체에 대해 시스템에 질의를 던집니다. 이 예제에서, 시스템은 먼저 “move (robot, north, southWall)“쿼리를 수행하고, 시스템은 “nil"이라고 응답합니다. 즉,이 상황을 처리하기 위해 정의된 규칙이 없으며, 기본 동작은 그 어포던스를 버리지 않습니다. 두 번째 쿼리는 “move (robot, north, northWall)“이며 시스템은 “false"로 응답합니다. 이 경우, 어포던스는 테스트를 통과하지 못하고 버려집니다.

위의 예제는 이러한 규칙이 조건을 사용하여 어포던스를 무효화 할 수있는 방법을 보여줍니다. 그러나 규칙은 이전 규칙에 의해 무효화 된 후에도 어포던스를 받아들이기 위해 사용될 수 있습니다.

setClauses("move(robot, north, X, R) :- X = northWall, R = false.
    move(robot, north, X, R) :- X = northWormhole, R = true.")

setQuery("move(robot, %s, %s, R).")

위의 코드에서 추가된 규칙은 시스템에 웜홀이 있을 경우 북쪽을 향한 로봇 움직임을 허용하도록 지시합니다. 객체 배열이 이전에 정의된 대로 유지되면 이동 어포던스는 여전히 삭제되지만, addObject("northWormhole")가 평가되는 경우, “northWormhole"이 추가될 것이며, 로봇이 웜홀을 사용하여 벽을 통과할 수 있습니다.

엄격한 타이핑 시스템

소개에서 언급했듯이 CX에는 암시적 형변환이 없습니다. 이 때문에, 각 기본 유형에 대한 여러 버전이 코어 모듈에 정의됩니다. 예를 들면, 4가지의 기본 함수가 있습니다.: addI32, addI64, addF32 및 addF64

파서는 소스 코드에서 찾은 데이터에 기본 유형을 첨부합니다.: 만약 정수를 읽으면, 그것의 기본 타입은 i32 또는 32 비트 정수입니다. ; 그리고 float를 읽는 경우, 기본 타입은 f32 또는 32 비트 부동소수점 입니다. 파서로부터 읽히는 다른 데이터 간 모호성이 없습니다. truefalse 항상 부울(booleans)입니다.; 큰 따옴표로 묶인 일련의 문자는 항상 문자열입니다.; 그리고 배열은 요소의 목록 앞에 타입을 표시해야 합니다. 예, []i64{1, 2, 3}.

프로그래머가 한 타입의 값을 다른 타입으로 명시적으로 변환해야 하는 경우, 코어 모듈은 원시 타입을 사용하기 위해 여러 가지 변환 함수를 제공합니다. 예를 들어, byteAToStr 바이트 배열을 문자열로 변환하고, i32ToF3232 비트 정수를 32 비트 부동 소수로 형변환합니다.

컴파일 및 해석

CX 사양은 개발자에게 인터프리터와 컴파일러를 제공하기 위해 CX 전용 언어 사용을 강조합니다. 해석된 프로그램은 컴파일된 프로그램보다 훨씬 느리지만, 보다 융통성 있는 프로그램을 허용합니다. 이러한 융통성은 메타 프로그래밍 기능과, 런타임 동안 프로그램의 구조를 수정할 수 있는 어포던스에서 비롯됩니다.

컴파일된 프로그램은 해석된 프로그램보다 더 엄격한 구조를 필요로 합니다. 많은 최적화가 이 엄격함을 활용하기 때문입니다. 결과적으로, 어포던스 시스템 및 프로그램 구조를 통해 작동하는 모든 기능은 컴파일 된 프로그램의 기능이 제한됩니다.

프로그래머가 CX 기능에서 제공하는 모든 융통성을 필요로 할 때, 프로그램이 해석되는 동안 성능이 가장 큰 문제일 경우, 컴파일러를 사용해야합니다. 다음 소단원에서는, 이러한 기능 중 일부가 예제 없이, 단순한 소개로 제시됩니다.

읽기 - 평가 - 출력 루프

읽기 - 평가 - 출력 루프(REPL)는 프로그래머가 새로운 프로그램 요소를 입력하고 평가할 수 있는 대화형 도구입니다. 새로운 REPL 세션을 시작하면 콘솔에 다음 메시지가 출력됩니다.:

CX REPL
More information about CX is available at https://github.com/skycoin/cx

*

이 “*“는 REPL이 새로운 코드 행을 수신할 준비가 되었음을 프로그래머에게 알려줍니다. REPL은 사용자가 세미콜론과 새로운 줄의 문자를 입력하는 동안 읽을 입력값을 준비합니다.

REPL에 처음 로드된 프로그램이 없으면, CX는 빈 프로그램으로 시작합니다. 이것은 :dProgram true; 메타 프로그래밍 명령이 입력된 것으로 볼 수 있습니다.:

* :dProgram true;
Program

*

REPL은 “Program"이라는 단어만을 출력한 후 빈 줄을 출력합니다. 첫 번째 단계로, 새 모듈과 함수를 선언할 수 있습니다.:

첫 번째 단계로서 새로운 main 모듈과 새로운 main 기능을 선언해야합니다.:

* package main;
Program
0.- Module: main

* func main () () {};
Program
0.- Module: main
	Functions
		0.- Function: main () ()

*

여기서 볼 수 있듯이, 새로운 요소가 프로그램에 추가될 때마다 프로그램 구조가 출력됩니다.

메타 프로그래밍 명령

:dProgram은 위의 하위 섹션에서 사용되었습니다. 명령 카테고리의 일부가 콜론(:)으로 시작하는 구문은 “메타-프로그래밍 명령"으로 알려져 있습니다.

REPL에서 요소를 선언하면 CX가 프로그램의 구조에 요소를 추가하도록 지시합니다. 그러나 ,다른 많은 프로그래밍 언어에서와 마찬가지로 이러한 선언은 추가되는 것이 제한적이며, 대부분 다시 정의됩니다.

그러나, REPL을 제공하는 다른 많은 프로그래밍 언어에서와 마찬가지로 프로그래머는 프로그램에 새 요소를 추가하고, 대부분의 요소를 재정의하는 것이 제한됩니다. 메타-프로그래밍-명령은 프로그래머가 프로그램의 구조를 어떻게 변경할 것인가를 좀 더 통제할 수 있도록 허용해줍니다.

:dProgram, :dState 그리고 :dStack는 프로그램 구조의 출력, 최근 호출된 구문, 사용자에게 전체 호출되는 스택에 의해 단지 디버깅 목적으로만 사용됩니다. step은 인터프리터에게 전/후 이동 실행을 지시합니다. :package, :func 그리고 :struct, 알려진 selectors, 이것들은 프로그램의 범위를 변경하기 위해 사용됩니다. :rem은 프로그래머가 removers에 접근할 수 있게 해 주며, 이것은 프로그램 구조의 선택된 요소를 제거하는데 사용될 수 있습니다. :aff는 CX의 어포던스 시스템에 접근하기 위해 사용됩니다.; 이 메타 프로그래밍 명령은 프로그램의 다른 요소에 대한 비용을 쿼리하고 적용하는데 사용됩니다. 사용자 정의 제한 시스템; 마지막으로, :clauses는 프로그램에 의해 모듈의 구문을 설정하는데 사용됩니다. :object:objects는 각각의 개체를 추가 및 출력하기 위해 사용됩니다.; 그리고 마지막 두 개의 메타 프로그래밍 명령 :query는 모듈의 쿼리를 설정하는데 사용되며, 그리고 :dQuery는 사용자 정의 제한을 디버깅하는 도우미입니다.

스테핑

REPL 모드에서 시작된 프로그램은 소스 파일에 정의된 프로그램 구조로 초기화 될 수 있습니다. 예 : 현재 디렉토리

$ ./cx --load examples/looping.cx

looping.cx는 예제 디렉토리에서 로드됩니다. (예제의 전체 목록은 레파지토리에서 찾을 수 있습니다.). Even though a (예제의 전체 목록은 프로젝트의 레파지토리에서 찾을 수 있습니다.) 프로그램이 로드되었지만, 아직 실행되지 않았습니다. REPL에서 프로그램을 실행하려면, step 메타 프로그래밍 명령을 사용해야 합니다: 끝날 때까지 프로그램을 실행하려면, :step 0; 명령을 사용해야 합니다. 그러나 :step은 다른 정수를 인수로 사용할 수 있기 때문에 흥미롭습니다 (심지어 음수). 예 :

CX REPL
More information about CX is available at https://github.com/skycoin/cx

* :dStack false;

* :step 5;
0

* :step 5;
1

* :step 5;
2

*

examples/looping.cx 프로그램은 한 번에 5 단계를 실행하고 있습니다. 우리는 프로그램이 while조건을 재-평가하고, 카운터 출력, 그리고 카운터에 1을 추가하기 위해서 5 단계가 필요한 것을 알수 있습니다.

마찬가지로 우리는 “제 시간에 끝내야” 합니다. 만약 REPL이 다음을 나타낸다면 :step -5.

...

* :step 5;
2

* :step -5;

* :step 5;
2

*

CX가 5 단계를 다시 진행하도록 지시하면, 2가 다시 콘솔에 출력됩니다. 카운터에는 다른 값이 지정되어 있지 않다는 것이 알려져야 합니다. 무슨 일이 일어나고 있는가 하면, 호출 스택이 이전 상태로 돌아가고 있습니다.

대화식 디버깅

CX 프로그램은 오류가 발견되면 REPL 모드로 들어갑니다. 이 동작을 통해 프로그래머는 실행을 다시 시작하기 전에 프로그램을 디버깅 할 수 있습니다.

아래 예제에서는, 0으로 나누기 오류가 발생되고, REPL은 프로그래머에게 오류에 대해 경고, 호출 스택의 마지막 호출을 덤프하며, REPL은 해당 실행을 계속합니다.

CX REPL
More information about CX is available at https://github.com/skycoin/cx

* package main;

* func main () () {};

* :func main;
main
:func main {...
	* foo := divI32(5, 3);
main
:func main {...
	* bar := divI32(10, 0);
main
:func main {...
	* :step 0;
fn:main ln:0, 	locals:
>> 1
fn:main ln:1, 	locals: foo: 1

Call's State:
foo:		1

divI32() Arguments:
0: 10
1: 0

0: divI32: Division by 0
main
:func main {...
	*

마찬가지로, REPL을 호출하지 않고, CX 인터프리터에 입력하기 위해 프로그램이 제공되지만, 오류가 발생되며, REPL은 프로그램의 디버그를 위해 프로그래머와 시스템 관리자를 위해 호출될 것입니다.:

$ ./cx examples/program-halt.cx
1

Call's State:
nonAssign_0:		1
nonAssign_1:		1

divI32() Arguments:
0: 5
1: 0

5: divI32: Division by 0
CX REPL
More information about CX is available at https://github.com/skycoin/cx

*

통합 진화 알고리즘

CX의 어포던스 시스템 및 메타 프로그래밍 기능을 통해 통제 방식으로 프로그램 구조를 유연하게 변경할 수 있습니다. 그러나, 적용할 어포던스의 지수를 선택하는 기능을 가지고 있으면, 여전히 어포던스를 자동화 할 수 있습니다.

evolve는 임의의 어포던스를 사용하여, 사용자 정의 함수를 구성하는 기본 함수입니다. 반복적인 프로세스가 테스트에 사용됩니다.

evolve는 진화론적 계산의 원리를 따릅니다. 특히, evolve는 유전 프로그래밍이라는 기술을 사용합니다. 유전 프로그래밍은 문제를 해결할 수있는 연산자와 인수의 조합을 찾으려고 시도합니다. 예를 들어, evolve는 10을 인수로 보내면 20을 반환하는 연산자 조합을 찾을 수 있습니다. 이것은 간단한 것처럼 들릴 수도 있겠지만, 유전 프로그래밍 및 기타 진화 알고리즘은 매우 복잡한 문제를 해결할 수 있습니다.

레파지토리의 examples 디렉토리에서, 다음의 예제를 찾을 수 있으며, (examples/evolving-a-function.cx) 이것은 커브-피팅 함수의 진화 프로세스를 설명합니다.

직렬화

CX의 프로그램은 부분적으로 또는 전체적으로 바이트 배열로 직렬화 될 수 있습니다. 이 직렬화 기능을 사용하면 프로그램이 프로그램 이미지 (시스템 이미지와 유사), 를 작성할 수 있으며, 프로그램이 직렬화된 완벽한 상태가 유지됩니다. 즉, 직렬화된 프로그램을 직렬화 해제하여 나중에 실행을 재개할 수 있습니다. 직렬화를 사용하여 백업을 만들 수도 있습니다.

CX 프로그램은 통합 기능을 활용하여 흥미로운 시나리오를 만들 수 있습니다. 예를 들어, 프로그램을 직렬화하여 자체 백업을 작성하고 해당 기능 중 하나에서 진화 알고리즘 을 시작할 수 있습니다. 진화 알고리즘이 이전 정의보다 우수한 성능을 찾으면 이 새로운 버전의 프로그램을 유지할 수 있습니다. 그러나 진화 알고리즘이 잘못 수행되면 프로그램을 저장된 백업으로 복원 할 수 있습니다. 이러한 모든 작업을 자동화 할 수 있습니다.