2019년 8월 25일 일요일

[on lisp] 6.1 function as representation (Network)

Generally, data structures are used to represent.
자료구조는 표현을 하기 위해 사용된다.
An array could represent a geometric transformation;a tree could represent a hierarchy of command; a graph could represent a rail network.
배열은 기하학적 변화를, 트리는 명령 계층을, 그래프는 철도 네트워크를
In Lisp we can sometimes use closures as a representation.
리스프에서 우리는 때때로 무언가를 표현할 때, 클로저를 사용하기도 한다.
Within a closure, variable bindings can store information, and can also play the role that pointers play in constructing complex data structures.
클로저 안에서, 변수 바인딩은 정보를 저장할 수 있다, 그리고 복잡한 자료구조의 경우 포인터로 가지고 놀 수 있다.
By making a group of closures which share bindings, or can refer to one another, we can create hybrid objects which combine the advantages of data structures and programs.
바인딩을 공유, 서로를 참조 할 수 있다. 즉, 우리는 이걸 이용해서 프로그램과 자료구조의 장점을 합친 hybrid object를 만들 수 있다.

Beneath the surface, shared bindings are pointers.
깊게 들어가면, 바인딩 공유는 포인터이다.
Closures just bring us the convenience of dealing with them at a higher level of abstraction.
클로저는 그저 높은 추상화를 이용하여 이 포인터를 편하게 다룰 수 있도록 한 것이다.
By using closures to represent something we would otherwise represent with static data structures, we can often expect substantial improvements in elegance and efficiency.
정적데이터를 클로저로 표현하면, 우아함과 효율성을 향상 시킬 수 있다.

Network

Closures have three useful properties: they are active, they have local state, and we can make multiple instances of them.
클로저에 3가지 속성을 가진다: active(살아있고)하고 local state를 가지고, 여러개의 instance를 만드는 것이 가능하다.
Where could we use multiple copies of active objects with local state? In applications involving networks, among others.
이렇게 살아있는 객체의 여러 복사본을 어디에서 사용할까? 특히 네트워크 관련 응용프로그램에서.
In many cases we can represent nodes in a networkas closures.
대부분의 경우 네트워크를 클로저로 나타낼 수 있다.
As well as having its own local state, a closure can refer to another closure.
자기자신의 로컬 상태만 가질 수 있는 것이 아니라, 클로저는 다른 클로저도 참조할 수 있다.
Thus a closure representing a node in a network can know of several other nodes (closures) to which it must send its output.
하여 네트워크에 노드를 표현하는 클로저는 출력을 보내야 하는 여러 노드(클로저)를 알 수 있다.
This means that we may be able to translate some networks straight into code.
이 말은 네트워크를 코드로 바로 표현할 수 있는 것이다.
; Fig 6.1 : Session of twenty questions  
> (run-node ’people) 
Is the person a man? 
>> yes 
Is he living? 
>> no 
Was he American? 
>> yes 
Is he on a coin? 
>> yes 
Is the coin a penny? 
>> yes 
LINCOLN
In this section and the next we will look at two ways to traverse a network.
지금 이 섹션과 다음 섹션을 통해 네트워크를 순회하는 2가지 방법을 알아보자.
First we will follow the traditional approach, with nodes defined as structures, and separate code to traverse the network.
첫번째는 전통적인 방식을 따른다, 노드는 자료구조를 정의하고, 분리된 코드로 네트워크를 순회한다.
Then in the next section we’ll show how to build the same program from a single abstraction.
그리고 다음 섹션에서는 추상화된 한 곳에서 위 전통적 방식과 동한 프로그램을 작성하는 방법을 보자.

As an example, we will use about the simplest application possible: one of those programs that play twenty questions.
예를들어, 우리는 아주 간단한 앱을 사용할 것이다: 그중하나가 20개의 질의를 하는 프로그램이다.
Our network will be a binary tree.
우리의 네트워크는 이진트리가 될 거다.
Each non-leaf node will contain a yes/no question, and depending on the answer to the question, the traversal will continue down the left or right subtree.
리프가 아닌 각 노드는 yes/no 질문을 가지고 있다, 질문에 대한 답에 따라서, 트리의 순회는 왼쪽/오른쪽 서브트리로 내려간다.
Leaf nodes will contain return values. When the traversal reaches a leaf node, its value will be returned as the value of the traversal. A session with this program might look as in Figure 6.1.
리프 노는 리턴 값을 진다. 리프노드에 닿으면 그 값이 리턴된다. Fig 6.1를 보면 세션을 가진 프로그램을 보여준다.

The traditional way to begin would be to define some sort of data structure to represent nodes.
전통적인 방식은 노드를 나타내는 일종의 자료구조를 정의한다.
A node is going to have to know several things: whether it is a leaf; if so, which value to return, and if not, which question to ask; and where to go depending on the answer.
노드는 몇 가지 요소를 가져야 한다. 1. 리프인지 아닌지, 리프는 값을 리턴한다, 2. 아니면 리턴하지 않고 어떤 질문을 하는지. 3. 답에 따라 어디를 가나.
A sufficient data structure is defined in Figure 6.2. It is designed for minimal size.
Fig 6.2에 충분한 자료구조가 정의 되어있다. 최소한의 크기로 설계되어 있다.
; Fig 6.2 : Representation and definition of nodes.
(defstruct node contents yes no)

(defvar *nodes* (make-hash-table))

(defun defnode (name conts &optional yes no)
  (setf (gethash name *nodes*)
        (make-node :contents conts :yes yes :no no)))
The contents field will contain either a question or a return value.
내용 필드에는 질문 또는 리턴값이 있다.
If the node is not a leaf, the yes and no fields will tell where to go depending on the answer to the question;
노드가 리프가 아닌경우, yes/no 필드는 질문에 대한 답변에 따라 어디로 가야할지 알려준다.
if the node is a leaf, we will know it because these fields are empty.
리프라면 이 필드들은 비어있기 때문에, 리프 임을 알 수 있다.
The global *nodes* will be a hash-table in which nodes are indexed by name.
글로벌 *nodes* 변수는 이름별로 인덱싱 되는 해시테이블이다.
Finally, defnode makes a new node (of either type) and stores it in *nodes*.
마지막으로, defnode는 새로운 노드를 만들어서 *nodes*에 저장한다.
Using these materials we could define the first node of our tree:
이것들을 이용하여 트리의 첫번째 노드를 정의할 수 있다.
;;첫번째 노드 정의하기
(defnode ’people "Is the person a man?" ’male ’female)

이제 네트워크를 만들어자. (여기서 네트워크는 알다시피 IO가 아니라 연결을 자료구조를 말하는 것)
(defnode 'people "Is the person a man?" 'male 'female)
(defnode 'male "Is he living?" 'liveman 'deadman)
(defnode 'deadman "Was he American?" 'us 'them)
(defnode 'us "Is he on a coin?" 'coin 'cidence)
(defnode 'coin "Is the coin a penny?" 'penny 'coins)
(defnode 'penny 'lincoln)

; Figure 6.3: Sample network.
Figure 6.3 shows as much of the network as we need to produce the transcript in Figure 6.1.
Figure 6.3는 처음 시연을 보였던 Fig 6.1를 재연하는 정도의 네트워크를 만든다.

Now all we need to do is write a function to traverse this network, printing out the questions and following the indicated path.
이제 우리가해야 할 일은 이 네트워크를 통과하는 함수를 작성하여 질문을 출력하고 표시된 경로를 따르는 것.
This function, run-node, is shown in Figure 6.4. Given a name, we look up the corresponding node.
이와 같은 기능, run-node는 그림 6.4에 나와 있습니다. 이름이 주어지면 해당 노드를 찾음.
If it is not a leaf, the contents are asked as a question, and depending on the answer, we continue traversing at one of two possible destinations.
잎이 아닌 경우 내용은 질문으로 표시되며 답변에 따라 가능한 두 목적지 중 하나를 계속 탐색.
If the node is a leaf, run-node just returns its contents.
노드가 리프 인 경우 run-node는 내용을 반환.
With the network defined in Figure 6.3, this function produces the output shown in Figure 6.1.
그림 6.3에 정의 된 네트워크에서이 기능은 그림 6.1에 표시된 출력을 생성.
Figure 6.4: Function for traversing networks.

(defun run-node (name) 
  (let ((n (gethash name *nodes*))) 
    (cond ((node-yes n) 
           (format t "~A~%>> " (node-contents n)) 
           (case (read) 
             (yes (run-node (node-yes n))) 
             (t (run-node (node-no n))))) 
           (t (node-contents n)))))

Figure 6.5: A network compiled into closures.
(defvar *nodes* (make-hash-table))

(defun defnode (name conts &optional yes no) 
  (setf (gethash name *nodes*) 
  (if yes 
    #'(lambda () (format t "~A~%>> " conts) 
        (case (read) 
          (yes (funcall (gethash yes *nodes*))) 
          (t (funcall (gethash no *nodes*))))) 
    #'(lambda () conts))))
이렇게 전통적인 방법을 이용보앗다.
1. data structure 정의
2. 분리된 코드로 네트워크 순회

다음 섹션에서 클로저를 이용한 방법을 알아보자.

댓글 없음:

댓글 쓰기