traverseNode -> context.visit -> context.visitMultiple/context.visitSingle -> context.visitQueue -> path.visit -> traverseNode
Why not breadth-first traverse? Is it to easily manipulate AST node, and to save more space?
Is it possible to have concurrent subscribers using cyclops-react library?
For example, if a run the following code:
ReactiveSeq<Integer> initialStream = ReactiveSeq.of(1, 2, 3, 4, 5, 6);
ReactiveSubscriber<Integer> sub1 = Spouts.reactiveSubscriber();
ReactiveSubscriber<Integer> sub2 = Spouts.reactiveSubscriber();
FutureStream<Integer> futureStream = FutureStream.builder().fromStream(initialStream)
.map(v -> v -1);
futureStream.subscribe(sub1);
futureStream.subscribe(sub2);
CompletableFuture future1 = CompletableFuture.runAsync(() -> sub1.reactiveStream().forEach(v -> System.out.println("1 -> " + v)));
CompletableFuture future2 = CompletableFuture.runAsync(() -> sub2.reactiveStream().forEach(v -> System.out.println("2 -> " + v)));
try {
future1.get();
future2.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
I get the following result:
1 -> 0
2 -> 0
2 -> 1
1 -> 0
1 -> 1
1 -> 1
2 -> 2
2 -> 3
2 -> 4
2 -> 5
1 -> 2
1 -> 2
1 -> 3
1 -> 4
1 -> 5
1 -> 3
1 -> 4
1 -> 5
I'm getting repeated values on the subscribers streams. Thank's in advance for any help.
cyclops-react only supports single subscribers. I think the behaviour here should be changed to ignore the second subscription attempt rather than allow it to mess up both (I will log a bug - thank you!).
You may be able to use Topics to the same effect however. We can rewrite your example using Topics
ReactiveSeq<Integer> initialStream = ReactiveSeq.of(1,2,3,4,5,6);
FutureStream<Integer> futureStream = FutureStream.builder()
.fromStream(initialStream)
.map(v -> v -1);
Queue<Integer> queue= QueueFactories.<Integer>boundedNonBlockingQueue(1000).build();
Topic<Integer> topic = new Topic<Integer>(queue,QueueFactories.<Integer>boundedNonBlockingQueue(1000));
ReactiveSeq<Integer> s2 = topic.stream();
ReactiveSeq<Integer> s1 = topic.stream();
Thread t = new Thread(()->{
topic.fromStream(futureStream);
topic.close();
});
t.start();
CompletableFuture future1 = CompletableFuture.runAsync(() -> s1.forEach(v -> System.out.println("1 -> " + v)));
CompletableFuture future2 = CompletableFuture.runAsync(() -> s2.forEach(v -> System.out.println("2 -> " + v)));
try {
future1.get();
future2.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
And the output is more inline with what we might expect
2 -> 0
1 -> 0
2 -> 1
1 -> 1
2 -> 2
1 -> 2
2 -> 3
1 -> 3
2 -> 4
1 -> 4
2 -> 5
1 -> 5
Given the Ord Type Class:
Prelude> :i Ord
class Eq a => Ord a where
compare :: a -> a -> Ordering
(<) :: a -> a -> Bool
(<=) :: a -> a -> Bool
(>) :: a -> a -> Bool
(>=) :: a -> a -> Bool
max :: a -> a -> a
min :: a -> a -> a
Is there a type class that provides a min : a field/function for a given type?
Example:
min :: Int would output the minimum Int value.
You're looking for Bounded, which contains minBound.
Any hints how to draw branching schema in spirit of attached image is welcomed.
Note that I would like to do it in graphviz for fast editing and future changes.
I made an attempt to imitate the famous git branching strategy from http://nvie.com/posts/a-successful-git-branching-model/ using GraphViz.
This is the original picture:
And this is the result:
The code:
strict digraph g{
rankdir="TB";
nodesep=0.5;
ranksep=0.25;
splines=line;
forcelabels=false;
// general
node [style=filled, color="black",
fontcolor="black", font="Consolas", fontsize="8pt" ];
edge [arrowhead=vee, color="black", penwidth=2];
// branch names
node [fixedsize=false, penwidth=0, fillcolor=none, shape=none, width=0, height=0, margin="0.05"];
subgraph {
rank=sink;
me [label="master", group="master"];
}
subgraph {
rank=sink;
de [label="develop", group="develop"];
}
// tags
node [shape=cds, fixedsize=false, fillcolor="#C6C6C6", penwidth=1, margin="0.11,0.055"]
t1 [label="0.1"]
t2 [label="0.2"]
t3 [label="1.0"]
// graph
node [width=0.2, height=0.2, fixedsize=true, label="", margin="0.11,0.055", shape=circle, penwidth=2, fillcolor="#FF0000"]
// branches
node [group="master", fillcolor="#27E4F9"];
m1;
m2;
m3;
m4;
subgraph {
rank=source;
ms [label="", width=0, height=0, penwidth=0];
}
m1 -> m2 -> m3 -> m4;
ms -> m1 [color="#b0b0b0", style=dashed, arrowhead=none ];
m4 -> me [color="#b0b0b0", style=dashed, arrowhead=none ];
node [group="hotfixes", fillcolor="#FD5965"];
h1;
node [group="release", fillcolor="#52C322"];
r1;
r2;
r3;
r4;
r5;
r1 -> r2 -> r3 -> r4;
node [group="develop", fillcolor="#FFE333"];
d1;
d2;
d3;
d4;
d5;
d6;
d7;
d8;
d9;
d10;
d1 -> d2 -> d3 -> d4 -> d5 -> d6 -> d7 -> d8 -> d9 -> d10;
d10 -> de [color="#b0b0b0", style=dashed, arrowhead=none ];
node [group="feature 1", fillcolor="#FB3DB5"];
fa1;
fa2;
fa3;
fa4;
fa5;
fa6;
subgraph fas1 {
fa1 -> fa2 -> fa3;
}
subgraph fas2 {
fa4 -> fa5 -> fa6;
}
node [group="feature 2", fillcolor="#FB3DB5"];
fb1;
fb2;
fb3;
fb4;
subgraph{ rank=same; fa6; fb4; } // hack
subgraph{ rank=same; fa1; fb1; } // hack
fb1 -> fb2 -> fb3 -> fb4;
// nodes
m1 -> d1;
m1 -> h1;
h1 -> m2;
h1 -> d5;
d3 -> fa1;
fa3 -> d6;
d6 -> r1;
r2 -> d7;
r4 -> d8;
r4 -> m3;
d9 -> r5;
r5 -> m4;
r5 -> d10;
d7 -> fa4;
fa6 -> d9;
d3 -> fb1;
fb4 -> d9;
// tags connections
edge [color="#b0b0b0", style=dotted, len=0.3, arrowhead=none, penwidth=1];
subgraph {
rank="same";
m1 -> t1;
}
subgraph {
rank="same";
m2 -> t2 ;
}
subgraph {
rank="same";
m3 -> t3;
}
}
Hope this helps someone.
This particular diagram was made with inkscape, therefore it will be difficult to match it with graphviz's output.
Here's how you may match some of it with graphviz:
Use a different group attribute for each branch in order to get straight lines for each branch (here's another example of using group, and one using weight)
Define the branches in the right order to have them appear from top to bottom
Use shape, style, width and height have some nodes stand out, and hide others
Use some \n newline cheating to have labels on top of the nodes (you may also try labelloc="t", or using xlabel instead of label)
digraph g{
rankdir="LR";
pad=0.5;
nodesep=0.6;
ranksep=0.5;
forcelabels=true;
node [width=0.12, height=0.12, fixedsize=true,
shape=circle, style=filled, color="#909090",
fontcolor="deepskyblue", font="Arial bold", fontsize="14pt" ];
edge [arrowhead=none, color="#909090", penwidth=3];
node [group="release3"];
s3 [label="release 3\n\n", width=0.03, height=0.03, shape=box];
r30 [label=" R3.0\n\n\n"];
e3 [label="", width=0.03, height=0.03, shape=box];
e3f [label="", width=0.03, height=0.03, shape=circle, color="#b0b0b0"];
s3 -> r30 -> e3;
e3 -> e3f [color="#b0b0b0", style=dashed];
node [group="release2"];
s2 [label="release 2\n\n", width=0.03, height=0.03, shape=box];
b2 [label="", width=0.03, height=0.03, shape=box];
r20 [label=" R2.0\n\n\n"];
e2 [label="", width=0.03, height=0.03, shape=box];
e2f [label="", width=0.03, height=0.03, shape=circle, color="#b0b0b0"];
s2 -> b2 -> r20 -> e2;
e2 -> e2f [color="#b0b0b0", style=dashed];
node [group="release1"];
s1 [label="release 1\n\n", width=0.03, height=0.03, shape=box];
ttest [label=" test\n\n\n"];
b1 [label="", width=0.03, height=0.03, shape=box];
r10 [label=" R1.0\n\n\n"];
r11 [label=" R1.1\n\n\n"];
e1 [label="", width=0.03, height=0.03, shape=box];
e1f [label="", width=0.03, height=0.03, shape=circle, color="#b0b0b0"];
s1 -> ttest -> b1 -> r10 -> r11 -> e1;
e1 -> e1f [color="#b0b0b0", style=dashed];
b1 -> s2;
b2 -> s3;
}
I see that the SML/NJ includes a queue structure. I can't figure out how to use it. How do I use the additional libraries provided by SML/NJ?
The Queue structure is not specified by SML '97, but it is present in SML/NJ's top-level environment.
$ sml
Standard ML of New Jersey v110.69 [built: Fri Mar 13 16:02:47 2009]
- Queue.mkQueue ();
[autoloading]
[library $SMLNJ-LIB/Util/smlnj-lib.cm is stable]
[autoloading done]
stdIn:1.1-1.17 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val it = - : ?.X1 Queue.queue
-
You can open a structure. This lets you avoid typing Queue. in front of everything. It's discouraged to do this at the top-level, though, because it pollutes the environment and makes it much less obvious what you're depending on. (Within another structure I'd say it might be acceptable in some situations.)
$ sml
Standard ML of New Jersey v110.69 [built: Fri Mar 13 16:02:47 2009]
- open Queue;
[autoloading]
[library $SMLNJ-LIB/Util/smlnj-lib.cm is stable]
[autoloading done]
opening Queue
type 'a queue
exception Dequeue
val mkQueue : unit -> 'a queue
val clear : 'a queue -> unit
val isEmpty : 'a queue -> bool
val enqueue : 'a queue * 'a -> unit
val dequeue : 'a queue -> 'a
val next : 'a queue -> 'a option
val delete : 'a queue * ('a -> bool) -> unit
val head : 'a queue -> 'a
val peek : 'a queue -> 'a option
val length : 'a queue -> int
val contents : 'a queue -> 'a list
val app : ('a -> unit) -> 'a queue -> unit
val map : ('a -> 'b) -> 'a queue -> 'b queue
val foldl : ('a * 'b -> 'b) -> 'b -> 'a queue -> 'b
val foldr : ('a * 'b -> 'b) -> 'b -> 'a queue -> 'b
- mkQueue ();
stdIn:3.1-3.11 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val it = - : ?.X1 queue
-
I don't have a complete answer for you but I could point you in the right direction. You should look up using the compilation manager (CM) which is built in to SML/NJ. You can think of it as Make for SML.
To use a library from the SML/NJ library you then add smlnj-lib.cm to the CM description file of your application. Then you can use the declarations such as Queue from that library.
The smlnj website has some documentation about the compilation manager.
Hope this at least points you in the right direction.
If you want to create an integer Queue, use the following code. Replace 'int' with the datatype you want.
val que = Queue.mkqueue(): int Queue.queue
Everything else can be found here.