Live data from Hacker News

Functional Language Features: Iterators and Closures

doc.rust-lang.org

11–20 of 40 posts

Re: Functional Language Features: Iterators and Closures

#11
post #2

> Programming in a functional style often includes using functions as values by passing them in arguments, returning them from other functions, assigning them to variables for later execution, and so forth. > ... > Other Rust features, such as pattern matching and enums, which we’ve covered in other chapters, are influenced by the functional style as well. What is it about pattern matching and enums that associates t…

> Is it just that pattern matching and enums were first popularized by certain functional languages?

Not only were Sum Types first popularised by functional languages, most imperative/OO languages still don't have them (although I'm not quite sure why not). E.g. none of Java/C#/C++ have them. Neither do Python/Ruby/JavaScript/PHP (although the need is somewhat reduced in dynamic languages)

Re: Functional Language Features: Iterators and Closures

#12
post #10
post #3

Earlier quoted context omitted.

I believe, on the pattern matching side, it has to do with the fact that it's a higher level feature that feels much more declarative. Inside of writing a sequence of instructions to check whether a list is 3 and the first two are equal, one writes the declarative syntax: (define (f x) (match x [`(,x ,x ,y) y] [_ #f]))

I'm sure it makes sense to someone well-versed in Rust syntax, but to an outsider like me that code looks like the kind of "line noise" that made me switch from perl to python. The procedural 'if x.len == 3 and x[0] == x[1]' seems a lot clearer as to what is actually being tested.

That code in the comment above isn't actually rust. It's a lisp, I believe.

In Rust, you'd write something more like:

  fn f(x: &[i32]) -> bool {
      match x {
          [x, y, _] if x == y => true,
          _ => false,
      }
  }

Re: Functional Language Features: Iterators and Closures

#13
post #2

> Programming in a functional style often includes using functions as values by passing them in arguments, returning them from other functions, assigning them to variables for later execution, and so forth. > ... > Other Rust features, such as pattern matching and enums, which we’ve covered in other chapters, are influenced by the functional style as well. What is it about pattern matching and enums that associates t…

pattern matching comes along with discriminated unions (enums). discriminated unions come along with functional programming, probably because they give you a more complete set of types mathematically (AND types as we are used to with structs/classes and OR types)

Re: Functional Language Features: Iterators and Closures

#14
post #6
post #2

> Programming in a functional style often includes using functions as values by passing them in arguments, returning them from other functions, assigning them to variables for later execution, and so forth. > ... > Other Rust features, such as pattern matching and enums, which we’ve covered in other chapters, are influenced by the functional style as well. What is it about pattern matching and enums that associates t…

> first popularized by certain functional languages Basically that. People associate all kinds of different thinks with the term functional programming. The only think in common is that it's focused on functions, including first class functions. For other thinks including things like (strict) immutability, lazy evaluation, syntax, algebraic data types, linear typing, etc. it is different from person to person weather…

A lot of those things are natural consequences of having functions without side effects though. Lazy evaluation for instance, can be bonkers if your functions have side effects.

Re: Functional Language Features: Iterators and Closures

#15
post #2

> Programming in a functional style often includes using functions as values by passing them in arguments, returning them from other functions, assigning them to variables for later execution, and so forth. > ... > Other Rust features, such as pattern matching and enums, which we’ve covered in other chapters, are influenced by the functional style as well. What is it about pattern matching and enums that associates t…

Functional programming is philosophically aligned with purity and immutability. When you have enforced immutability, many of the features of OO programming disappear, and you're left with having pointers to a bundle of values with various getter style methods. In order to recover the ability to make complex data structures, you need to encode variants. This can be done with Null and the bundle of values, or it can be done with Algebraic Data Types, aka Rust's fancy enums.

Re: Functional Language Features: Iterators and Closures

#16
post #10
post #3

Earlier quoted context omitted.

I believe, on the pattern matching side, it has to do with the fact that it's a higher level feature that feels much more declarative. Inside of writing a sequence of instructions to check whether a list is 3 and the first two are equal, one writes the declarative syntax: (define (f x) (match x [`(,x ,x ,y) y] [_ #f]))

I'm sure it makes sense to someone well-versed in Rust syntax, but to an outsider like me that code looks like the kind of "line noise" that made me switch from perl to python. The procedural 'if x.len == 3 and x[0] == x[1]' seems a lot clearer as to what is actually being tested.

A) this is in Racket, as that's the editor window I had up. B) your point is fair, one benefit of this is that it also binds names to things.

Re: Functional Language Features: Iterators and Closures

#18
post #2

> Programming in a functional style often includes using functions as values by passing them in arguments, returning them from other functions, assigning them to variables for later execution, and so forth. > ... > Other Rust features, such as pattern matching and enums, which we’ve covered in other chapters, are influenced by the functional style as well. What is it about pattern matching and enums that associates t…

> Is it just that pattern matching and enums were first popularized by certain functional languages? Not only were Sum Types first popularised by functional languages, most imperative/OO languages still don't have them (although I'm not quite sure why not). E.g. none of Java/C#/C++ have them. Neither do Python/Ruby/JavaScript/PHP (although the need is somewhat reduced in dynamic languages)

C++17 does - it's called std::variant.

  std::variant options;
  options = true;
  
  bool value = std::get(options);
  bool has_bool = std::holds_alternative(options);
  
  // or test which alternative is held
  if (auto i = std::get_if(&options)) {
    // do something with int
  } else if (auto b = std::get_if(&options)) {
    // do something with bool
  } else {
    // do something with double
  }

Re: Functional Language Features: Iterators and Closures

#19
I've tried to use iterators and closures in my code, but it's not as easy with error handling and lifetimes. Like I could figure out the magic incantation that lets me map over an iterator with a function that returns a result. Or I could write a for loop that pushes to a Vec.

Or I could chain an ok_or_else on an Option but ugh now Rust is complaining that I'm capturing a reference to self. Screw it, I'll rewrite it to be an if let with a return. Part of the problem there is that we know an ok_or_else with try! will execute the closure and return if the value is None, but Rust's borrow check doesn't know that.

None of this is Rust's fault. It's just that it's hard to combine ergonomic closures and borrow checking.

Re: Functional Language Features: Iterators and Closures

#20
post #18

Earlier quoted context omitted.

> Is it just that pattern matching and enums were first popularized by certain functional languages? Not only were Sum Types first popularised by functional languages, most imperative/OO languages still don't have them (although I'm not quite sure why not). E.g. none of Java/C#/C++ have them. Neither do Python/Ruby/JavaScript/PHP (although the need is somewhat reduced in dynamic languages)

C++17 does - it's called std::variant. std::variant options; options = true; bool value = std::get (options); bool has_bool = std::holds_alternative (options); // or test which alternative is held if (auto i = std::get_if (&options)) { // do something with int } else if (auto b = std::get_if (&options)) { // do something with bool } else { // do something with double }

That's not a language feature though, right? It's just a struct containing a union and a discriminant. That means:

- No pattern matching means your stuck with the awkward if-elseif-else

- It doesn't check that you've accounted for every possible variant.

- You can only hold one variant of each type: you can't have two variants that both contain a string.

- The specific instance isn't it's own type, so you can't implement methods on it.

Post reply on HN