core.logic 출력을 사용하여 들여쓰기된 S식

35118 단어 Clojurelisplogictech

들여쓰기된 S자 내보내기


Scheme에서 원하는 장면이 있어요.
  • 자체 제작 도구로 성형된 S식 출력
  • 매크로의 전개 결과를 축소한 상태에서 보고 싶다
  • 그리고 예쁘게 축소해야 할 뿐만 아니라 어느 정도 축소폭과 취향을 바꿀 수 있는 스타일, 사용자가 정의한 매크로를 잘 축소하고 출력할 수 있는 도구도 필요하다.

    적절한 들여쓰기 S-방식 내보내기


    규칙을 설정하고 조건에 맞는 것을 출력하면 원하는 것을 완성할 수 있다.
    예제
    ・ 1行は80行まで
    ・ let式のbinding部のインデントをそろえる
    ・ cond等のペアグループで空白をいれる(ペアグループのbody部が改行されている場合)
    
    조건에 맞는 패턴을 풀기 위해 Kanren 또는 logic programing 시스템의 DSL을 사용합니다.

    칸렌 가문


    미니 칸렌이라는 Schome은 logic proamming 언어(proolog와 유사)를 사용한다.
    'The Reasoned Scchemer'라는 장르로 쓰이고 미니 칸렌의 공식 홈페이지보면 다양한 언어로 이식됐다.
    이번에 처리한 코어는로직도 클로져가 이식한 칸렌 가족 중 한 명이다.
    또 마이크로칸렌이라는 최소 부분만으로 구성된 40줄 미만의 작은 S cheme 구현도 존재한다.

    core.logic의 간단한 예

  • x는 1이다.x의 값은?(당연1)
  • (run* [x] (== x 1)) ; → (1)
    
    run*는 주어진 제약을 만족시키는 변수 값을 되돌려준다.[x]는 되돌아오기를 희망하는 구속 변수다.(== x 1)는 x와 1이 같은 제약이다.
    결과 1은 목록에 둘러싸여 되돌아오는데 그 이유는 아래의 예에서 설명한다.
  • x와 y는 0, 1, 2 중의 하나이다.x와 y는 같지 않다.x와 y의 값은?
  • (run* [x y]
      (membero x [0 1 2]);xは0,1,2のどれか
      (membero y [0 1 2]);yは0,1,2のどれか
      (!= x y));xとyは等しくない
    ;→ ([0 1][1 0][0 2][2 0][1 2][2 1])
    
    결과를 보면 코어.logic는 제한을 만족시키는 모든 변수의 값을 열거했다.(이유는 앞의 예가 목록이다)

    core.logic은 Clojure와 함께 할 수 있습니다.


    core.logic로 기술한 부분의 변수는 코어입니다.logic clojure.core.logic.LVar 객체가 저장되어 있으므로(패턴 일치 등에 사용되는 경우) LVar 객체의 솔리드(Clojure 객체)를 제거하려면 project 구법을 사용해야 합니다.
    LVar 객체의 컨텐트는 Clojure 객체이므로 project Clojure에 전달되는 함수를 사용할 수 있습니다.
    (defne piyo [a res]
        ([[f . rests] _]
          ; fは <varf__6120> といったLVarオブジェクト
          (project [f] (== res (inc f)))))
         
    (run* [res]
      (piyo [1 2 3] res)) ; → (2)
    
    (이것은 예시를 위해 만든 것이다. 보통 잘 쓰지 않는 코드)

    이번에 할 일

  • 상수는 문자열과 수치가vector에서 쓴 S식만 대상으로 줄 바꾸기와 공백을 삽입합니다.
  • 또한 목표 S식 문법의 종류는 함수만 적용한다
  • 함수에 적용되는 문법이 할인되어 시험 제작으로 괜찮은 것 같다
  • 함수 적용 들여쓰기 모드 예
    ;改行なし
    (fn arg1 arg2 arg3)
    
    ;1つめの引数は改行なしで、以降の引数をそれにあわせる
    (fn arg1
        arg2
        arg3)
        
    ;全部改行
    (fn
      arg1
      arg2
      arg3)
      
    ;途中で1回改行
    (fn arg1 arg2 arg3 arg4
        arg5 arg6 arg7 arg8)
    

    이번에 못한 일.

  • 여러 조건 중 최적
    다음에 파이팅.
  • 주어진 규칙


    이거 코어 좀 해봐.logic로 쓰세요.
  • 1줄 80자 이내
  • 함수에 적용되는 매개 변수는 다음과 같다.
    1: 들여쓰기 폭 2 줄 바꿈
    2: 앞에 있는 매개변수와 동일하게 행 분리
    3: 줄 바꿈 안 함
  • 내부 표현


    줄 바꿈 및 공백 삽입 표현식
  • 해당 대상을 맵 대상과 연결시킨다.
  • 에 대응하는 모든 맵 대상은 newline과 색인 요소를 가지고 있습니다.
  • 출력된 경우 newline이 있는 경우 줄을 바꾸고 indent의 양의 공백만 삽입합니다.(이 외에 그대로 유지)
  • 대상이venctor인 상황에서body요소로서vector는 자요소의 내부표시를 가지게 한다.
  • 내부 표현의 한 예.(이번 시제품에서 나타나지 않는 모드)
    (fn arg1 arg2
        arg3
              arg4 arg5)
    
    ;;インデントや改行の表現
    {:newline false
     :body [{:newline false}
            {:newline false}
    	{:newline true :indent 4}
    	{:newline true :indent 9}
    	{:newline false}]}
    

    결실


    가장 적합한 것을 추가로 선택하는 기능이 필요하지만 기대한 결과를 낼 수 있다.
    ;;入力
    ["HELLO" "ARG1" "ARG2"]
    
    ;;結果
    ["HELLO" "ARG1" "ARG2"]
    ["HELLO"
       "ARG1" "ARG2"]
    ["HELLO" "ARG1"
             "ARG2"]
    ["HELLO"
       "ARG1"
       "ARG2"]
    ["HELLO" "ARG1"
       "ARG2"]
    
  • 긴 매개 변수를 건네준 후 80개의 문자 규칙 때문에 모든 줄을 바꾸는 모드만 되돌려준다
  • ;;入力
    ["HELLO" "LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG" "ARG2"]
    
    ;;結果
    ["HELLO"
       "LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOONG" 
       "ARG2"]
    
  • 깊게 중첩된 패턴
  • ;;入力
    ["HELLO" ["HELLO2" "ARG1" "ARG2"] ["HELLO3" "ARG4"]]
    
    ;; 結果は多すぎるので省略 (50個出てきた)
    (count (solve ["HELLO" ["HELLO2" "ARG1" "ARG2"] ["HELLO3" "ARG4"]]))
    ;;→ 50
    
    ;;結果の一例(変なの)
    ["HELLO" ["HELLO2" "ARG1"
                "ARG2"]
       ["HELLO3"
          "ARG4"]]
    

    끝맺다

  • 지금부터 여러 후보 중 가장 적합한 후보를 선정한다.
  • 들여쓰기 모드를 쉽게 변경할 수 있는 제품을 제공하고자 하니 주의하십시오.wrap을 logic DSL로 한 번 더 만들어볼까요?
  • 미니카렌으로 이걸 하면 슈미도 같은 일을 할 수 있다.
  • 소스 코드


    core.logic을 적으면서 썼기 때문에 별로 좋지 않아요.
    다음에 잘해.
    (use '[clojure.core.logic])
    
    (defne apply-funcall [expression index start prev-indents last-right res]
      ([[] _ _ _ _ _]
       (== res nil)
       (== last-right start))
      ([[f . rests] 0 _ _ _ _]
       (fresh [next-res current-res current-right inc-right]
              (apply-rule f start current-right false current-res)
              (project [current-right start]
                       (apply-funcall rests 1 (inc current-right)
                                      [(+ start 2)] last-right next-res))
              (project [current-res]
                       (== res (lcons (assoc current-res :first true)
                                      next-res)))))
    
      ([[f . rests] _ _ _ _ _]
       (project [index] (== (pos? index) true))
       (fresh [next-res current-res current-right inc-right]
              (or*
               [(fresh []
                       (apply-rule f start current-right false current-res)
                       (project [current-right index]
                                (== (< current-right 80) true))
                       (project [current-right index prev-indents]
                                (apply-funcall rests (inc index)
                                               (inc current-right)
                                               (cons start prev-indents)
                                               last-right next-res))
                       (== res (lcons current-res
                                      next-res)))
                (fresh [new-start]
                       (membero new-start prev-indents)
                       (apply-rule f new-start current-right true current-res)
                       (project [current-right] (== (< current-right 80) true))
                       (project [current-right index]
                                (apply-funcall rests
                                               (inc index)
                                               (inc current-right) prev-indents
                                               last-right next-res))
                       (== res (lcons current-res next-res)))]))))
    
    (defne apply-rule [expression start right newl res]
      ([[_ . _] _ _ _ _]
       (fresh [funcall-res last-right]
              (project [start]
                       (apply-funcall expression 0 (inc start)
                                      [] last-right funcall-res))
              (project [expression start]
                       (== right last-right))
              (== res {:body funcall-res
                       :right last-right
                       :indent start
                       :newline newl})))
      ([_ _ _ _ _]
       (project [expression]
                (== (number? expression) true))
       (project [expression start]
                (== right (+ start expression)))
       (project [expression start]
                (== res {:atom true
                         :indent start
                         :newline newl
                         :right (+ start expression)}))))
    
    (defn- serialisp->lencode [expression]
      (cond
        (vector? expression) (mapv serialisp->lencode expression)
        (string? expression) (+ (count expression) 2)
        (number? expression) (count (str expression))
        :else 0))
    
    (defn solve [expression]
      (run* [res]
            (fresh [_right]
                   (apply-rule (serialisp->lencode expression)
                               0
                               _right
                               false
                               res))))
    
    (defn- encode* [expression {:keys [newline indent body] :as info}]
      (let [res (if newline
                  (->> (iterate (fn [_] " ") " ")
                       (take indent)
                       (cons "\n")
                       vec)
                  [])]
        (cond
          (vector? expression)
          (concat res
                  ["["]
                  (mapcat #(concat (when-not  (or (:first %2) (:newline %2)) [" "])
                                   (encode* %1 %2)) expression body) ["]"])
    
          (string? expression) (conj res (str "\"" expression "\""))
          :else (conj res (str expression)))))
    
    (defn encodes [expression indent-info-list]
      (map #(apply str (encode* expression %))
           indent-info-list))
    
    (defn view [expression]
      (let [indent-info-list (solve expression)]
        (encodes expression indent-info-list)))
    
    ;実行方法
    ;(doseq [x (view ["HELLO" "ARG1" "ARG2"])] (print x) (newline) (newline))
    

    좋은 웹페이지 즐겨찾기