Phase 6: slurp, spit, read-line, range 3-arg, repeat/cycle/iterate, interleave
Phase 6 Clojure Core Library now complete (except meta): - T6.3: slurp (alias for file/read) - T6.4: spit (alias for file/write) - T6.5: read-line (stdin input) - T6.6: range with 3 args (start, end, step) - T6.7: repeat, cycle, iterate (eager implementations) - T6.9: interleave - Updated TASKS.md and ROADMAP.md
This commit is contained in:
@@ -1054,6 +1054,80 @@ proc cljRange*(start, finish: CljVal): CljVal =
|
||||
items.add(cljInt(i))
|
||||
cljList(items)
|
||||
|
||||
proc cljRange3*(start, finish, step: CljVal): CljVal =
|
||||
if start.kind != ckInt or finish.kind != ckInt or step.kind != ckInt:
|
||||
raise newException(CatchableError, "range requires integers")
|
||||
if step.intVal == 0: raise newException(CatchableError, "range step cannot be zero")
|
||||
var items: seq[CljVal] = @[]
|
||||
if step.intVal > 0:
|
||||
var i = start.intVal
|
||||
while i < finish.intVal:
|
||||
items.add(cljInt(i))
|
||||
i += step.intVal
|
||||
else:
|
||||
var i = start.intVal
|
||||
while i > finish.intVal:
|
||||
items.add(cljInt(i))
|
||||
i += step.intVal
|
||||
cljList(items)
|
||||
|
||||
proc cljRepeat*(n: CljVal, x: CljVal): CljVal =
|
||||
if n.kind != ckInt: raise newException(CatchableError, "repeat requires an integer count")
|
||||
var items: seq[CljVal] = @[]
|
||||
for i in 0..<n.intVal:
|
||||
items.add(x)
|
||||
cljList(items)
|
||||
|
||||
proc cljCycle*(n: CljVal, coll: CljVal): CljVal =
|
||||
if n.kind != ckInt: raise newException(CatchableError, "cycle requires an integer count")
|
||||
var srcItems: seq[CljVal] = @[]
|
||||
case coll.kind
|
||||
of ckList: srcItems = coll.listItems
|
||||
of ckVector: srcItems = toSeq(coll.vecData)
|
||||
else: return cljList(@[])
|
||||
if srcItems.len == 0: return cljList(@[])
|
||||
var items: seq[CljVal] = @[]
|
||||
for i in 0..<n.intVal:
|
||||
items.add(srcItems[i mod srcItems.len])
|
||||
cljList(items)
|
||||
|
||||
proc cljIterate*(n: CljVal, f: CljVal, x: CljVal): CljVal =
|
||||
if n.kind != ckInt: raise newException(CatchableError, "iterate requires an integer count")
|
||||
if f.kind != ckFn: raise newException(CatchableError, "iterate requires a function")
|
||||
var items: seq[CljVal] = @[x]
|
||||
var current = x
|
||||
for i in 1..<n.intVal:
|
||||
current = f.fnProc(@[current])
|
||||
items.add(current)
|
||||
cljList(items)
|
||||
|
||||
proc cljInterleave*(args: seq[CljVal]): CljVal =
|
||||
if args.len < 2: raise newException(CatchableError, "interleave requires at least 2 arguments")
|
||||
var seqs: seq[seq[CljVal]] = @[]
|
||||
for a in args:
|
||||
case a.kind
|
||||
of ckList: seqs.add(a.listItems)
|
||||
of ckVector: seqs.add(toSeq(a.vecData))
|
||||
else: seqs.add(@[])
|
||||
var minLen = seqs[0].len
|
||||
for s in seqs:
|
||||
if s.len < minLen: minLen = s.len
|
||||
var items: seq[CljVal] = @[]
|
||||
for i in 0..<minLen:
|
||||
for s in seqs:
|
||||
items.add(s[i])
|
||||
cljList(items)
|
||||
|
||||
proc cljReadLine*(): CljVal =
|
||||
try:
|
||||
var line = ""
|
||||
if readLine(stdin, line):
|
||||
cljString(line)
|
||||
else:
|
||||
cljNil()
|
||||
except EOFError:
|
||||
cljNil()
|
||||
|
||||
# ---- File Operations ----
|
||||
|
||||
proc cljFileRead*(path: CljVal): CljVal =
|
||||
|
||||
Reference in New Issue
Block a user