matz / streem

prototype of stream based programming language
MIT License
4.6k stars 236 forks source link

Conditional write for function objects #44

Closed halogenandtoast closed 9 years ago

halogenandtoast commented 9 years ago

This might be completely strange, but I feel like the fizzbuzz example could benefit from some kind of conditional write operator for function operators. The syntax would be something like:

cond_expr => expr

When cond_expr is true the function object will stream that value to the next receiver

For example:

seq(100) | {|x|            
  x % 15 == 0 => "FizzBuzz"
  x % 3 == 0 => "Fizz"
  x % 5 == 0 => "Buzz"
  true => x
} | STDOUT
alexispurslane commented 9 years ago

I like that idea. It is very useful. Maybe we could try something similar to lisp's COND. It seems to me that your suggested syntax is slightly unclear, and since language design walks a fine line between obscurity and expressiveness, maybe something like this might make more sense:

seq(100) | { |x|
  cond {
    x % 15 == 0 => "FizzBuzz"
    x % 3 == 0   => "Fizz"
    x % 5 == 0   => "Buzz"
    else              => x
  }
} | STDOUT

This syntax then could also be used outside of a function object (which, by the way, are called lambdas), giving it a much more general use case. But I'm still open to your syntax, especially since COND is sort of an obscure keyword for a modern language to use.

nickserv commented 9 years ago

So => is syntax sugar for if <condition> then return, right? If so, I like the idea behind this, but wouldn't it cause each line with => to be evaluated even if the first condition is true? If it breaks instead, I feel that's a bit too implicit. If it keeps going, then I'd prefer @christopherdumas's idea of having a COND operator. COND is really flexible, and takes care of stopping when a condition is true.

halogenandtoast commented 9 years ago

return is a form of breaking so no. It would be structurally similar to this in terms of ruby (not condoning this format because I find this to be terrible in ruby-land)

return "FizzBuzz" if x % 15 == 0
return "Fizz" if x % 3 == 0
return "Buzz" if x % 5 == 0
return x if true

The reason why I've hated it in ruby is the idea of trailing conditionals which is the wrong way to interpret things. An example someone used recently would be similar to a movie theater saying "Leave the theater immediately... if there's a fire" . This syntax brings the condition to the front. The inspiration for it is definitely cond from clojure or guards from Haskell and Erlang.

alexispurslane commented 9 years ago

cond is from the real lisps originally, not Clojure.

halogenandtoast commented 9 years ago

Ha tell me how you really feel. I actually meant cond came from my use of clojure since that's really the only lisp I've used aside from emacs lisp. Maybe one day I'll use a "real" lisp :p

On Dec 19, 2014, at 5:58 PM, Christopher Dumas notifications@github.com wrote:

cond is from the real lisps originally, not Clojure. Clojure is just a really awful, watered down version of Common Lisp, which is a really awful, bloated version of Scheme. But yes, I agree with what your saying, @halogenandtoast.

\ Reply to this email directly or view it on GitHub.

alexispurslane commented 9 years ago

Ok, sorry for the vehement reply. I just love Scheme, thats all. But yes, your idea is an interesting one! xD

matz commented 9 years ago

I am thinking of match statement:

match [n%3, n%5] {
  [0, 0] => "FizzBuzz"
  [0, _] => "Fizz"
  [_, 0] => "Buzz"
   _ => n
}
alexispurslane commented 9 years ago

Funny, because in rust, this is how I implemented fizzbuzz:

/*
 * Rust Fizzbuzz functional implementation
 */
fn fb (i: int) -> () {
  let mod5 = i % 5 == 0;
  let mod3 = i % 3 == 0;

  match [mod5, mod3] {
      [false, true] => println!("Fizz"),
      [true, false] => println!("Buzz"),
      [false, false] => println!("{}", i),
      [true, true] => println!("FizzBuzz")
  }
}

fn fizzbuzz (up_to: int) -> () {
  fb(up_to);
  if up_to > 0 { fizzbuzz(up_to - 1) }
}

fn main () {
  fizzbuzz(100)
}
nickserv commented 9 years ago

@matz That looks pretty cool, I like Rust's pattern matching a lot. Streem's match statement would return/stream the resulting value, instead of directly printing it to STDIN, right?

matz commented 9 years ago

@nicolasmccurdy right. A function return value or a value given to emit will be passed to the connecting stream.