Skip to content

Commit

Permalink
std/stream: add Extent() and tweak Drain() (#173)
Browse files Browse the repository at this point in the history
* std/stream: make `Drain()` return the last value instead of the stream

Closes #172.

* std/stream: Add `Extent()`.

* wdte: Update some dependencies.
  • Loading branch information
DeedleFake committed Dec 6, 2018
1 parent 5c1e229 commit ce93760
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 7 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ module github.com/DeedleFake/wdte
require (
github.com/peterh/liner v1.1.0
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a // indirect
golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e // indirect
)
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ github.com/peterh/liner v1.1.0 h1:f+aAedNJA6uk7+6rXsYBnhdo4Xux7ESLe+kcuVUF5os=
github.com/peterh/liner v1.1.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a h1:1n5lsVfiQW3yfsRGu98756EH1YthsFqr/5mxHduZW2A=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e h1:njOxP/wVblhCLIUhjHXf6X+dzTt5OQ3vMQo9mkOIKIo=
golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
72 changes: 71 additions & 1 deletion std/stream/end.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package stream

import (
"sort"

"github.com/DeedleFake/wdte"
"github.com/DeedleFake/wdte/auto"
)
Expand Down Expand Up @@ -79,14 +81,18 @@ func Drain(frame wdte.Frame, args ...wdte.Func) wdte.Func {
}

s := args[0].Call(frame).(Stream)

last := End()
for {
n, ok := s.Next(frame)
if !ok {
return s
return last
}
if _, ok := n.(error); ok {
return n
}

last = n
}
}

Expand Down Expand Up @@ -158,6 +164,70 @@ func Fold(frame wdte.Frame, args ...wdte.Func) wdte.Func {
return Reduce(frame, s, cur, r)
}

// Extent is a WDTE function with the following signatures:
//
// extent s n less
// (extent n less) s
// (extent less) s n
// ((extent less) n) s
//
// It drains the Stream s, building up a list of up to n elements
// yielded for which less returns true compared to other elements in
// the list, sorted such that the first element of the list is the
// most less of them. In other words, it returns the n most minimum
// elements using less to perform the compartison. For example,
//
// range 10 -> extent 3 >
//
// will return [9; 8; 7].
func Extent(frame wdte.Frame, args ...wdte.Func) wdte.Func {
frame = frame.Sub("extent")

if len(args) < 3 {
return auto.SaveArgsReverse(wdte.GoFunc(Extent), args...)
}

s := args[0].Call(frame).(Stream)
length := args[1].Call(frame).(wdte.Number)
less := args[2].Call(frame)

var c func(wdte.Array, int, wdte.Func) wdte.Array
c = func(extent wdte.Array, i int, f wdte.Func) wdte.Array {
extent = append(extent[:i], append(wdte.Array{f}, extent[i:len(extent)-1]...)...)

if len(extent) == int(length) {
c = func(extent wdte.Array, i int, f wdte.Func) wdte.Array {
copy(extent[i:], extent[i+1:])
extent[i] = f
return extent
}
}

return extent
}

extent := make(wdte.Array, 0, int(length))
for {
n, ok := s.Next(frame)
if !ok {
return extent
}
n = n.Call(frame)

i := sort.Search(len(extent), func(i int) bool {
return less.Call(frame, n, extent[i]) == wdte.Bool(true)
})
if i < len(extent) {
extent = c(extent, i, n)
continue
}

if len(extent) < int(length) {
extent = append(extent, n)
}
}
}

// TODO: Implement this. It should be able to essentially insert its
// own output into another chain, so that
//
Expand Down
1 change: 1 addition & 0 deletions std/stream/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ var Scope = wdte.S().Map(map[wdte.ID]wdte.Func{
"drain": wdte.GoFunc(Drain),
"reduce": wdte.GoFunc(Reduce),
"fold": wdte.GoFunc(Fold),
"extent": wdte.GoFunc(Extent),
//"chain": wdte.GoFunc(Chain),
"any": wdte.GoFunc(Any),
"all": wdte.GoFunc(All),
Expand Down
25 changes: 22 additions & 3 deletions wdte_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,9 +534,18 @@ func TestStream(t *testing.T) {
},
},
{
name: "Drain",
script: `let s => import 'stream'; let io => import 'io'; let main => s.range 5 -> s.map (io.writeln io.stdout) -> s.drain;`,
out: "0\n1\n2\n3\n4\n",
name: "Drain",
script: `
let s => import 'stream';
let io => import 'io';
let main =>
s.range 5
-> s.map (@ p v => io.writeln io.stdout v; v)
-> s.drain
;
`,
ret: wdte.Number(4),
out: "0\n1\n2\n3\n4\n",
},
{
name: "Reduce",
Expand All @@ -548,6 +557,16 @@ func TestStream(t *testing.T) {
script: `let s => import 'stream'; s.range 5 -> s.fold +;`,
ret: wdte.Number(10),
},
{
name: "Extent/Min",
script: `let s => import 'stream'; let a => import 'arrays'; a.stream [5; 3; 6; 2; 7; 1] -> s.extent 3 <;`,
ret: wdte.Array{wdte.Number(1), wdte.Number(2), wdte.Number(3)},
},
{
name: "Extent/Max",
script: `let s => import 'stream'; let a => import 'arrays'; a.stream [5; 3; 6; 2; 7; 1] -> s.extent 3 >;`,
ret: wdte.Array{wdte.Number(7), wdte.Number(6), wdte.Number(5)},
},
{
name: "Any/True",
script: `let s => import 'stream'; let main => s.range 5 -> s.any (== 3);`,
Expand Down

0 comments on commit ce93760

Please sign in to comment.