Live data from Hacker News

Functional Language Features: Iterators and Closures

doc.rust-lang.org

21–30 of 40 posts

Re: Functional Language Features: Iterators and Closures

#21
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…

I think variant records (aka 'enums' in Rust) were first popularized by Pascal. They were in ALGOL 68 even earlier, but that language wasn't widely used.

Re: Functional Language Features: Iterators and Closures

#22
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 }

This works out really nicely when combined with variadic template tricks. (Taken from CPP Reference)

  // Helper for creating anonymous visitor functions
  template struct overloaded : Ts... { using Ts::operator()...; };
  template overloaded(Ts...) -> overloaded;

  using var_t = std::variant;

  std::vector vec = {10, 15l, 1.5, "hello"};

  // Type matching visitor
  for (auto& v: vec) {
        std::visit(overloaded {
            [](auto arg) { std::cout 
Outputs: 10 15 1.500000 "hello"

Re: Functional Language Features: Iterators and Closures

#23
post #18

Earlier quoted context omitted.

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 imple…

Take a look at my reply above. Your right it isn't built into the language, but it does come with a helper method, std::visit, which does take into account that you've accounted for all possible variant types, and will throw a compile error if you didn't. You also aren't stuck with if, else-if style syntax.

Re: Functional Language Features: Iterators and Closures

#24
post #18

Earlier quoted context omitted.

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 }

This works out really nicely when combined with variadic template tricks. (Taken from CPP Reference) // Helper for creating anonymous visitor functions template struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded ; using var_t = std::variant ; std::vector vec = {10, 15l, 1.5, "hello"}; // Type matching visitor for (auto& v: vec) { std::visit(overloaded { [](auto arg) { std…

That does not give you destructuring though, so to distinguish different variants of the same type you are left with a classic `if` inside the lambda.

Also this has "language support" in the sense that it is (again) implemented via template meta programming, i.e. the compile time is impacted quite heavily.

See "std::visit is everything wrong with modern C++": https://bitbashing.io/std-visit.html

This standards proposal would add proper match (named, of course, inspect) support: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p009...

Re: Functional Language Features: Iterators and Closures

#25
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)

Ruby has pattern matching as an experimental feature: https://www.ruby-lang.org/en/news/2019/12/25/ruby-2-7-0-rele...

Re: Functional Language Features: Iterators and Closures

#26
post #18

Earlier quoted context omitted.

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 imple…

A language that I am working on has those things "built-in" (it still generates compilable C++ in the backend). I did recently add pattern matching (and not just on variants) where the above would be equivalent to:

  $v:|[:int, :bool, :double] = 5;

  $vi: = v.[:int];
  $holds_int: = v.?[:int];

  switch v {
    .[:int]$i { /std cout 
If a type repeats in the same variant, you would match by index to tell them apart:

  $v:|[:int, :int]
(I have some ideas to allow named labels instead of numerical indices but that is not yet implemented)

It is, in spirit, an implementation of the inspect proposal [1], but with a (subjectively) much simpler and more powerful syntax (the grammar of the entire language is fully LALR(1) without ambiguities).

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p137...

Re: Functional Language Features: Iterators and Closures

#27
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)

> Neither do Python/Ruby/JavaScript/PHP (although the need is somewhat reduced in dynamic languages)

I fully agree. Pattern matching is specifically useful for statically typed languages, where you can determine whether the patterns are exhaustive. Here pattern matching plays really nicely with the premise of having statically typed consistency guarantees.

In dynamically typed languages there is a use-case which makes sense: You want to conditionally extract nested values. But typically you have destructuring and a huge generic tool-set of predicates and transformation functions to do this. The advantage of being dynamically typed is how those things freely compose at the cost of having fewer run-time guarantees.

Re: Functional Language Features: Iterators and Closures

#29
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…

They make it much easier to do certain kinds of things as expressions (as opposed to, say, an if/else chain which in many languages is a statement and not an expression, or a switch statement which I don't think is ever an expression)

Re: Functional Language Features: Iterators and Closures

#30
post #18

Earlier quoted context omitted.

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 }

This works out really nicely when combined with variadic template tricks. (Taken from CPP Reference) // Helper for creating anonymous visitor functions template struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded ; using var_t = std::variant ; std::vector vec = {10, 15l, 1.5, "hello"}; // Type matching visitor for (auto& v: vec) { std::visit(overloaded { [](auto arg) { std…

What a ridiculous language C++ is.
Post reply on HN