Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streem examples #46

Open
tbodt opened this issue Dec 20, 2014 · 26 comments
Open

Streem examples #46

tbodt opened this issue Dec 20, 2014 · 26 comments

Comments

@tbodt
Copy link

tbodt commented Dec 20, 2014

So far, it seems that the only thing anybody knows how to write with Streem is the FizzBuzz and cat programs. Obviously, a language can't be that useful if it can only do FizzBuzz and cat.

Please comment on this issue with your examples of more useful things you can do with Streem. I still need to be convinced that there are any.

@nickserv
Copy link
Contributor

Keep in mind that Streem is in its really early phase of development. As far as I'm aware, not much is implemented yet besides parsing source files. There's still a bit of design discussion going on. That being said, Streem already has a few pretty cool conceptual ideas, like functional programming concepts and sending one stream to multiple consumers.

@alexispurslane
Copy link

Heres an idea though:

// Get all usernames from a stream of input data. Assumes my seggestions of currying and prototypal are accepted, as well as my alternative syntax for lambdas.

['username': '', 'age': 0, 'init': (u, a) -> { this.u = u; this.a = a; }] -> User

def ith (n, thing) {
  thing[n]
} // Possible shorthand for: `def ith (n, thing) = thing[n]`, anyone?

ith(0, _) -> get_user

STDIN | split(',', _) | User.init(_, int(_)) | get_user | STDOUT
// The input format could be: Christopher Dumas,22

@s-aida
Copy link

s-aida commented Dec 20, 2014

If it's premature to add a real-world example, what else?
Fibonacci? Prime Numbers? Or even Hello World?

@nickserv
Copy link
Contributor

Hello World

["Hello, world!"] | STDOUT

@nickserv
Copy link
Contributor

Fibonacci

def fib (n) {
  if n == 0 {
    0
  } else if n == 1 {
    1
  } else {
    fib(n-1) + fib(n-2)
  }
}

seq(10) | fib | STDOUT

This is a fairly naive example in terms of performance, but it should work (hopefully).

Edit: Whoops, this seems to be broken with the current streem parser. Any ideas as to what's wrong?

@shuichiro-makigaki
Copy link
Contributor

Currently, I think you can't write fib (n) {. Instead, fib (n) | {. But, this isn't what you'd like to do...

@ghost
Copy link

ghost commented Dec 20, 2014

Is it seq(10) | fib | STDOUT. Or

seq(10) | { |x|
  fib(x)
} | STDOUT

and how do you give functions names. More examples, please.
Is it like in Haskell?

f x y = x * 2 + y * 2
g = f 2
h = g 3
h == 10

@nickserv
Copy link
Contributor

@blkdev Those should both work, Streem should have first class functions.

@matz
Copy link
Owner

matz commented Dec 21, 2014

I added some examples in 2dce6a4. More to come.

@tbodt
Copy link
Author

tbodt commented Dec 22, 2014

@matz They are great examples. Until now, I didn't think of Streem as a language that could do TCP connections. 😎

@nickserv
Copy link
Contributor

@matz Cool! Out of curiousity, does "Hello World" | STDOUT work, or does the left side have to be a list?

@matz
Copy link
Owner

matz commented Dec 22, 2014

@nicolasmccurdy it should be a list. I'd like to reserve | for bitwise or.

@nickserv
Copy link
Contributor

So is | going away for pipes?

@alexispurslane
Copy link

Maybe we could use '>>' for pipes, and '%' for splitting them.

@Krysl
Copy link

Krysl commented Dec 22, 2014

This example "05chat.strm" makes me confused:

broadcast = chan()
tcp_server(8008) | {|s|
  broadcast | s   # connect to broadcast channel
  s | broadcast   # broadcast incoming message
}

I'm not sure "broadcast | s" means data came from "s" to "broadcast" or came from "broadcast" to "s".

@matz
Copy link
Owner

matz commented Dec 22, 2014

@Krysl s is a connection to a client. broadcast | s means data from broadcast will be sent to the client, and s | broadcast means data from the client will be sent to broadcast channel, then all clients connected.

@matz
Copy link
Owner

matz commented Dec 22, 2014

@nicolasmccurdy I might confused you. I meant I wanted to reserve | (for scalar values, e.g. numbers and strings) for bitwise-or operation.

@jaxrtech
Copy link

Another alternative is using the pipeline operator found in F# that being |> for pipes. I think the just adding the > sign in itself would make it much clearer in which direction things are being piped. So for example 05chat.strm would look like (with s renamed to client for clarity sake):

broadcast = chan()
tcp_server(8008) |> {|client|
  broadcast |> client   # connect to broadcast channel
  client |> broadcast   # broadcast incoming message
}

Or your could pipe it backwards too. I think this looks kinda confusing though:

broadcast = chan()
tcp_server(8008) |> {|client|
  broadcast |> client   # connect to broadcast channel
  broadcast <| client   # broadcast incoming message
}

Though I think as more on an architectural side note, I think this example could be confusing at first glance since its not explicitly clear how the broadcast |> client pipeline is to be executed whether it be:

  • Synchronously (block to completion) - Wait for broadcast to be completely exhausted before moving to the next line.
    In this case, the program would be stuck waiting for broadcast to completely finish piping everything to client. Since we would never know when broadcast would be completely finished in order to move to the next line, the program would be dead locked waiting when no data is going to be sent in the first place.
  • Asynchronously (run in the background aka "fire and forget") - Don't wait for the pipes to finish but continue running them in the background (the intended behavior)
    In this case, in the background, when we would get data from broadcast, we would pipe it to client and then we would get data from client, we would pipe it to broadcast. This would be the intended behavior since we essentially want to setup a background listener on either end.

I think its important to explicitly distinguish that we would rather always run pipelines in an asynchronous manner since it would lend to a concurrent design and you would not have to worry about a pipeline blocking another one especially if ran in an event loop or thread pool.

For example, the order of which the numbers in this example would get printed out is nondeterministic since both pipelines would be running concurrently (unless we added like a join or something between them before sending it to STDOUT):

seq(100) |> STDOUT
seq(100) |> { |x| x * 2 } |> STDOUT

Of course, individual pipes in a single pipeline would always run in a blocking fashion since you have to wait for input to work with (ex: in a |> b, b waits to execute until a sends something)

I think these are important concepts to think about going down the road either way.

@alexispurslane
Copy link

👍 for |> and <|

@naturalethic
Copy link

Please see #18 (comment)

@jaxrtech
Copy link

See #18 comment for FizzBuzz in F# too for example.

@Krysl
Copy link

Krysl commented Dec 27, 2014

How about named pipe?

mkfifo("/tmp/fifo", S_IFIFO|0666)
fifo_in = open("/tmp/fifo", O_WRONLY)
fifo_out = open("/tmp/fifo", O_RDONLY)
STDIN | fifo_in
seq(100) | fifo_in
fifo_out | STDOUT

And make it more simple, may like this

STDIN | [fifo] | STDOUT
seq(100) | fifo

And if a function can be bind to the named pipe, like a filter. 05chat.strm may look like this:

[broadcast] = chan()
[client] = tcp_server(8008)
broadcast | client | broadcast

[FIFO] may looks strange, we may need better symbols.
I'm a newbie, I wish this can be helpful.

@nickserv
Copy link
Contributor

@ChristopherDumas Agreed. That seems very clear to me, and it also looks kinda nice.

@alexispurslane
Copy link

"It looks very cool in my opinion!" |> GITHUB

@ghost
Copy link

ghost commented Jul 3, 2017

What would be nice is if there would be "cookbook examples" for streem too. Like we have fizzbuzz but what about other popular redirections? File stuff; also perhaps binary ... video, audio ... these things.

One could also do this via named pipes I suppose; just assign special functions to these pipes to act as filters (a bit similar how gstreamer handles source/sinks).

But matz also said that streem is experimental and it probably has lower priority than e. g. mruby so I guess this is stuff that may all happen "at a later time". :)

@linbirg
Copy link

linbirg commented Dec 26, 2019

fibonacci

def fib (n) {
if (n == 0) {
0
} else if (n == 1) {
1
} else {
fib(n-1) + fib(n-2)
}
}

seq(10) | fib | stdout

Fibonacci

def fib (n) {
  if n == 0 {
    0
  } else if n == 1 {
    1
  } else {
    fib(n-1) + fib(n-2)
  }
}

seq(10) | fib | STDOUT

This is a fairly naive example in terms of performance, but it should work (hopefully).

Edit: Whoops, this seems to be broken with the current streem parser. Any ideas as to what's wrong?

fibonacci

def fib (n) {
if (n == 0) {
0
} else if (n == 1) {
1
} else {
fib(n-1) + fib(n-2)
}
}

seq(10) | fib | stdout

if add () is ok for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants