2017-12-09 9 views
1

예로 들어 다음 프로그램을 보자Clojure의 에코 프로그램을 지연 무한 시퀀스로 빌드 할 수 있습니까?

(defn echo-ints [] 
    (doseq [i (->> (BufferedReader. *in*) 
       (line-seq) 
       (map read-string) 
       (take-while integer?))] 
    (println i))) 

아이디어는 사용자에게 입력하라는 메시지를 표시하고 정수의 경우 다음 다시 반향하는 것입니다. 그러나이 특정 프로그램에서는 매 두 번째 입력이 즉시 반향되지 않습니다. 대신 프로그램은 2 개의 입력을 동시에 처리하기 전에 추가 입력을 기다립니다.
아마도 이것은 약간의 성능 조정이 뒤에서 일어난 결과 일 것입니다. 그러나이 경우에는 즉각적인 피드백 루프를 갖고 싶습니다. 이 작업을 수행하는 쉬운 방법이 있습니까? 아니면 프로그램의 논리를 크게 변경해야합니까?
(주된 동기는 지연된 시퀀스를 다른 지연 시퀀스로 변환하는 다른 함수 f에 무한 시퀀스의 사용자 입력을 전달하는 것입니다. 어떤 종류의 while 루프를 작성하면 f을 사용할 수 없습니다.)

+1

이도 (읽기 선)''로 일어나고있다? –

답변

1

대부분의 시퀀스 기능에는 기능상 올바르지 만 의도하지 않은 영향을주는 최적화가 내장되어 있기 때문에 일반적으로 부작용 (이 경우 인쇄)을 혼합하는 것은 좋지 않습니다. https://stuartsierra.com/2015/08/25/clojure-donts-lazy-effects

당신이 할하려는 것은 core.async 채널에 적합한 것 같아 : 최대

여기 좋은 기록이다. 나는 '사용자 입력의 무한 시퀀스'대신 '사용자 입력 스트림'으로 문제를 생각하고 '느린 시퀀스를 지연 시퀀스로 변환'f '스트림을 다른 스트림으로 변환'이 될 것입니다. 이렇게하면 임의로 작성할 수있는 트랜스 듀서로 f를 쓸 수 있습니다.

-2

다음과 같이 작성합니다. 일부 결과를 표시하려면 spyxspyxxfrom the Tupelo library을 사용합니다.

(ns tst.demo.core 
    (:use tupelo.test) 
    (:require 
    [tupelo.core :as t]) 
    (:import [java.io BufferedReader StringReader])) 
(t/refer-tupelo) 

(def user-input 
"hello 
    there 
    and 
    a 
    1 
    and-a 
    2 
    and 
    a 
    3.14159 
    and-a 
    4 
    bye") 

(defn echo-ints 
    [str] 
    (let [lines (line-seq (BufferedReader. (StringReader. str))) 
     data (map read-string lines) 
     nums (filter integer? data) ] 
    (doseq [it data] 
     (spyxx it)) 
    (spyx nums))) 
(newline) 
(echo-ints user-input) 

이 우리에게 결과를 제공합니다 :

첫째, 통조림 테스트 데이터와 간단한 버전을 쓰기

it => <#clojure.lang.Symbol hello> 
it => <#clojure.lang.Symbol there> 
it => <#clojure.lang.Symbol and> 
it => <#clojure.lang.Symbol a> 
it => <#java.lang.Long 1> 
it => <#clojure.lang.Symbol and-a> 
it => <#java.lang.Long 2> 
it => <#clojure.lang.Symbol and> 
it => <#clojure.lang.Symbol a> 
it => <#java.lang.Double 3.14159> 
it => <#clojure.lang.Symbol and-a> 
it => <#java.lang.Long 4> 
it => <#clojure.lang.Symbol bye> 

nums => (1 2 4) 

그래서, 우리는 그것이 작동하고 우리에게 우리가 원하는 숫자를주는 것을 알 수있다.

다음으로 루핑 버전을 작성하십시오. 우리는 테스트 데이터가 부족할 때 정상적으로 종료되도록합니다.

(defn echo-ints-loop 
    [str] 
    (loop [lines (line-seq (BufferedReader. (StringReader. str)))] 
    (let [line  (first lines) 
      remaining (rest lines) 
      data  (read-string line)] 
     (when (integer? data) 
     (println "found:" data)) 
     (when (not-empty? remaining) 
     (recur remaining))))) 
(newline) 
(echo-ints-loop user-input) 

found: 1 
found: 2 
found: 4 

다음으로 무한 루프를 작성하여 키보드를 읽습니다. 당신은 키보드에서 CRTL-C이 일 종료해야합니다

(ns demo.core 
    (:require [tupelo.core :as t]) 
    (:import [java.io BufferedReader StringReader])) 
(t/refer-tupelo) 


(defn echo-ints-inf 
    [] 
    (loop [lines (line-seq (BufferedReader. *in*))] 
    (let [line  (first lines) 
      remaining (rest lines) 
      data  (read-string line)] 
     (when (integer? data) 
     (println "found:" data)) 
     (when (not-empty? remaining) 
     (recur remaining))))) 

(defn -main [] 
    (println "main - enter") 
    (newline) 
    (echo-ints-inf)) 

을 그리고 우리는 수동으로 실행 :

~/clj > lein run 
main - enter 
hello 
there 
1 

found: 1 
and 
a 
2 
found: 2 
and-a 
3 
found: 3 
further more 
4 
found: 4 
^C 
                                             ~/clj > 
~/clj >