News for hackers. Stuff that matters.
Re:Rust vs. Go by iopq on Wednesday January 18, 2017 @04:58PM (#13430697)
Not THAT easy

    fn apply<A, B, C, F, G>(mut f: F, a: A) 
    -> impl FnMut(&B) -> C // must still be `for<'r> impl FnMut(&'r B) -> C`, because that’s what filter requires
             where F: FnMut(B) -> G, // must not be `for<'r> FnMut(&'r B) -> G`, because regular functions do not implement it
                   G: FnMut(A) -> C,
                   B: Copy, // for dereferencing
                   A: Clone {
    
        move |b| f(*b)(a.clone()) // this must do any bridging necessary to satisfy the requirements
    }
this function signature must be EXACTLY like what I wrote or it won't work
Re:Rust vs. Go by CalChris on Wednesday January 18, 2017 @05:02PM (#13430735)
No, not that easy especially when you get to the functional programming stuff. But I find FP hard to understand since I don't use it much.

> this function signature must be EXACTLY like what I wrote or it won't work

This can be seen as a feature in the sense that you can't program by luck: well, this incantation seems about right and the compiler nods its head that it understands and that means something, so it must be right.

Re:Rust vs. Go by iopq on Wednesday January 18, 2017 @05:07PM (#13430800)
Joke's on you: it took me a month of asking around why my program won't compile to figure out I really CAN'T do it without dereferencing inside the function. This is because of higher ranked lifetime bounds... there's no way to express the correct lifetime bound in this case (in Rust, maybe in Haskell it's possible), so you just have to deref first.
Re:Rust vs. Go by openasocket on Wednesday January 18, 2017 @07:29PM (#13431865)
> This is because of higher ranked lifetime bounds...

No, it's because the function you're returning is of type FnMut(&B) -> C, but your F function is of type FnMut(B) -> G. It expects an owned value of B, but you only have a borrowed reference to a B. Just make F of type FnMut(&B) -> G and you no longer have to dereference and no longer need the restriction that B: Copy. Higher-ranked lifetime values don't have anything to do with it.

Here's the new version:

  fn apply<A, B, C, F, G>(mut f: F, a: A) 
    -> impl FnMut(&B) -> C
             where F: FnMut(&B) -> G,
                   G: FnMut(A) -> C,
                   A: Clone {
    
        move |b| f(b)(a.clone())
    }
Re:Rust vs. Go by iopq on Thursday January 19, 2017 @01:27AM (#13433568)
You think I didn't try that one before? It doesn't work in MY case:

    error[E0281]: type mismatch: the type `fn(_) -> _ {tool::second::<_>}` implements the trait `std::ops::FnMut<(_,)>`, but the trait `for<'r> std::ops::FnMut<(&'r _,)>` is required (expected concrete lifetime, found bound lifetime parameter

      --> src\lib.rs:50:17
       |
    50 |         .filter(apply(second, i))
       |                 ^^^^^
       |
        = note: required by `apply`

    error[E0271]: type mismatch resolving `for<'r> <fn(_) -> _ {tool::second::<_>} as std::ops::FnOnce<(&'r _,)>>::Output == _`
      --> src\lib.rs:50:17
       |
    50 |         .filter(apply(second, i))
       |                 ^^^^^ expected bound lifetime parameter , found concrete lifetime
       |
       = note: concrete lifetime that was found is lifetime '_#11r
       = note: required by `apply`

    error: aborting due to 2 previous errors

    error: Could not compile `fizzbuzz`.
Re:Rust vs. Go by CalChris on Wednesday January 18, 2017 @05:20PM (#13430903)
You probably have a simpler, clearer way of solving that problem than by torturing the language.
Re:Rust vs. Go by iopq on Wednesday January 18, 2017 @05:27PM (#13430973)
I do, but the problem is FizzBuzz. What's the point of solving FizzBuzz in a SIMPLE way? The whole point of FizzBuzz is to torture the language.
Re:Rust vs. Go by lisivka on Wednesday January 18, 2017 @05:59PM (#13431284)

    fn main() {
      for i in 1..101 {
        if i % 15 == 0 {
            println!("FizzBuzz");
        } else if i % 3 == 0 {
            println!("Fizz");
        } else if i % 5 == 0 {
            println!("Buzz");
        } else {
            println!("{}", i);
        }
      }
    }
Re:Rust vs. Go by flukus on Wednesday January 18, 2017 @06:30PM (#13431508)
I don't know why people over complicate things. I was searching for other solutions and found this abomination:

https://bitbucket.org/iopq/fizzbuzz-in-rust/src/bf4968973d73...

I hope their production code isn't like this.

Re:Rust vs. Go by Ygg2 on Wednesday January 18, 2017 @07:45PM (#13431948)
Wut? It's about as representative of Rust as writing FizzBuzz using Monads. In Java.

If you want production code look at Rust and Servo.

Re:Rust vs. Go by iopq on Wednesday January 18, 2017 @10:45PM (#13432818)
I wrote this as an exercise. This is specifically written to be point-free code without any if or match expressions.

    .unwrap_or_else(|| i.to_string().into())
this is the only one that was too ugly to make point-free
Re:Rust vs. Go by flukus on Wednesday January 18, 2017 @06:27PM (#13431494)
If the problem is FizzBuzz then it's you that's made it too complicated. Here is a simple version:

https://github.com/the-guitarman/rust_fizzbuzz/blob/master/s...

Re:Rust vs. Go by iopq on Saturday January 21, 2017 @12:38AM (#13448993)
It doesn't do the same exact thing as mine does. For one thing, mine does FizzBuzzBazz (factors of 3, 5, 7) or even FizzBuzzBazzQuux if you want (actually arbitrary strings and arbitrary conditions)
Re:Rust vs. Go by gpderetta on Wednesday January 18, 2017 @06:19PM (#13431432)
Equivalent [1] C++14 for comparison:

   template<class F, class A>
   auto apply(F f, A a) {
      return [f=std::move(f), a=std::move(a)](auto&& b) {
        return f(std::forward<dectlype(b)>(b))(a);
      }
   }
The forward<decltype> is an abomination and is really in need of a language based solution, but otherwise is fairly straightforward.

[1] No type checking of the definition of course, only of instantiations. On the plus side, the returned function is polymorphic and can be called for all Bs that f can be called.

Re:Rust vs. Go by eximius on Wednesday January 18, 2017 @06:19PM (#13431438)
Not sure what you're talking about:

https://is.gd/Xnu0YJ

Re:Rust vs. Go by iopq on Thursday January 19, 2017 @01:30AM (#13433579)
it doesn't work in my program:

https://bitbucket.org/iopq/fizzbuzz-in-rust/src/bf4968973d73...

it gives an error when I use a generic `second` method from tool.rs

Re:Rust vs. Go by ytugiuyghvk on Wednesday January 18, 2017 @06:20PM (#13431442)
Why ask that B: Copy instead of B: Clone?
Re:Rust vs. Go by iopq on Thursday January 19, 2017 @01:30AM (#13433586)
To deref it
Re:Rust vs. Go by ytugiuyghvk on Thursday January 19, 2017 @09:53AM (#13436210)
b.clone(), of course, derefs b as well.
Re:Rust vs. Go by lisivka on Wednesday January 18, 2017 @05:32PM (#13431013)
I don't know Rust, but code looks readable. Function apply receives two arguments and returns function of one argument (address of b) which returns value of type C. I assume function apply() creates closure, so a.clone() is necessary to create fresh copy of a every time when closure is called. b is passed by reference, so code is generic. Not bad.