core.logic 출력을 사용하여 들여쓰기된 S식
들여쓰기된 S자 내보내기
Scheme에서 원하는 장면이 있어요.
적절한 들여쓰기 S-방식 내보내기
규칙을 설정하고 조건에 맞는 것을 출력하면 원하는 것을 완성할 수 있다.
예제
・ 1行は80行まで
・ let式のbinding部のインデントをそろえる
・ cond等のペアグループで空白をいれる(ペアグループのbody部が改行されている場合)
조건에 맞는 패턴을 풀기 위해 Kanren 또는 logic programing 시스템의 DSL을 사용합니다.칸렌 가문
미니 칸렌이라는 Schome은 logic proamming 언어(proolog와 유사)를 사용한다.
'The Reasoned Scchemer'라는 장르로 쓰이고 미니 칸렌의 공식 홈페이지보면 다양한 언어로 이식됐다.
이번에 처리한 코어는로직도 클로져가 이식한 칸렌 가족 중 한 명이다.
또 마이크로칸렌이라는 최소 부분만으로 구성된 40줄 미만의 작은 S cheme 구현도 존재한다.
core.logic의 간단한 예
(run* [x] (== x 1)) ; → (1)
run*
는 주어진 제약을 만족시키는 변수 값을 되돌려준다.[x]
는 되돌아오기를 희망하는 구속 변수다.(== x 1)
는 x와 1이 같은 제약이다.결과 1은 목록에 둘러싸여 되돌아오는데 그 이유는 아래의 예에서 설명한다.
(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)
(이것은 예시를 위해 만든 것이다. 보통 잘 쓰지 않는 코드)이번에 할 일
;改行なし
(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: 들여쓰기 폭 2 줄 바꿈
2: 앞에 있는 매개변수와 동일하게 행 분리
3: 줄 바꿈 안 함
내부 표현
줄 바꿈 및 공백 삽입 표현식
(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"]
;;入力
["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"]]
끝맺다
소스 코드
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))
Reference
이 문제에 관하여(core.logic 출력을 사용하여 들여쓰기된 S식), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/niyarin/articles/e00257db78fe1982a04e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)