I got a book on Haskell at half price books.
Functional Programming
Literally exactly same lol.
This is just an anecdote and not how I began doing FP, but still fun. I was in college. For whatever reason I felt like I had to use methods (Java). So when the teacher had us do a FizzBuzz as a benchmark early in the semester (just to see where everyone was) I thought good programming used a lot of methods so I did something like String fizz() { return "3"; } String buzz() { return "5"; }
and one of the professors asked me "Do you have a background in functional programming?" and I had never heard that before, so I thought, yeah, of course my programs function! So I said yes I did have a background in functional programming lol.
A few years ago I volunteered to do mock interviews for a bunch of students who were getting ready to graduate from a bootcamp. I didn't know much about the bootcamp curriculum and I was surprised to see that all of the resumes listed functional programming as one of the key skills. I was curious, and asked the first few interviewees about their experience with FP and they made up some nonsensical answers with varying degrees of confidence. I finally asked one of them to just tell me what functional programming was, and was and they said "oh, you know, writing a program that functions!".
I made it a point of telling the students that it's a lot better to admit you don't know something rather than making something up in an interview, and reached out to the founder of the bootcamp to express my disappointment that they were sending people into interviews with blatantly false experience on their resume. I'm not sure if anything ever came of it, and from time to time I wonder how many graduates from that bootcamp are still going out into interviews with no idea that "functional programming" means anything other than writing programs that function.
I was learning Java 6 in highschool. One day my brain wrinkled and I asked the teacher a big question:
"Why can't methods be more like variables? I want to try, like, making an array of methods out of it"
My teacher, bless his heart, replied:
"I'm just a P.E. teacher filling in electives because the county can't afford to hire anyone with a computer science degree, but go ahead and install whatever you want if you feel like experimenting"
So I stumbled around Google for a while playing with phrases like "passing methods without anonymous inner classes" and "public final methods" until I eventually stumbled across a bunch of blog posts by this guy called Martin Odersky. That led me directly into dropping Java and picking up Scala, the JVM language he designed.
Scala basically blew my world open. I discovered the beauty of first-class functions, immutability, currying, and pattern matching. Unfortunately, Scala was sort of peaking at the the time, so I eventually had to pack up and learn other languages. I experimented with Haskel (too hardcore for me!), Elixir (good but tiny ecosystem), and Groovy (cool, but unfocused). I always ended up returning to lame languages like JS (meh...), Python (ugh...), and Lua (ugh!!) because that's where the projects that most interested me were happening.
These days I mostly work in JS professionally. It's not ideal (hungrily eyes tc39/proposal-pattern-matching & tc39/proposal-pipeline-operator)... but my FP background still has a lot of applicability in JS-land. I frequently receive compliments on my code and I attribute a large part of that to the lessons and discipline which FP has taught me.
Quick little followup question to my own comment: I'm considering picking up Rust because I'm a big fan of what they're doing with immutables and pattern matching. Are there any Rustaceans on this community? What do you think of it as far as the FP experience goes?
Rust is not a FP language. It's an imperative language with restricted state and a few FP constructs included.
To me what makes a language FP is the mindset and that boils down to deciding to fold
instead of loop and you lean to closure captures instead of declaring variables. Both sides of these are basically equivalent but having a function as the big hammer you use to nail everything together is what makes it functional programming instead of X programming with some functional ideas carried over.
When people structure a request like this they're generally after a way to really get into the ideas and the best way to do that is to use a language that's built around FP ideas. I personally recommend Clojure and OCaml. If you'd like to do Scheme via the Wizard book then that's fine as well. I don't really like the pure functional languages (Haskell and friends) because I think that state is a useful thing in small doses and don't like jumping through the extra hoops to get at it.
Rust is not a purely FP language, indeed, but I think it's absolutely fine to program almost only FP in it, then you have almost no issues with the borrow-checker. Though since it's a multiparadigm, I obviously decide for each problem the best approach which is not always FP... Often it's just simpler to read imperative code. But I almost always default to fold
in Rust anyways.
Though e.g. currying and the likes is certainly more fun in real FP languages (like Haskell).
The more experience I get in all these languages the more I think Rust has found the "perfect" balance of paradigms and readability (well at least to date). But this is obviously also a matter of personal preference... I'm really looking forward that all the boilerplate is reduced when programming with a lot of generic trait-bounds (i.e. more inference where it makes sense), I think this is still an area where Rust could improve (also compile times, like incremental trait solving).
As someone who's been toying with Rust for a few years but hasn't written anything substantial in it yet, I really like the functional features it has. I find the pattern matching to be an incredibly clean way of managing temporary scopes that are only needed to define a single variable.
Likewise I find the restrictions imposed by the compiler to be useful for writing extremely clean, explicit code. One of the bigger issues I find with reading other people's Scala code (for instance) is that syntactic sugar of the language leads to a lot of implicitness, which can lead to a much longer period of parsing the code before it could otherwise be safely modified. With Rust it feels much more like WYSIWYG, and if there's any doubt if you can do something safely in the language, you can just mash compile till you're safely inside the guard rails.
That said, I do agree with the other commenter that it's not primarily an FP language. It is however, a highly productive language to write code in once you get past the initial learning curve, IMO.
I consider myself a relatively experienced Rust programmer (5+ years experience, 2-3 years professional).
I think it excels in most aspects, but advanced "type-meta-programming" and currying. But I think even this may be a good thing, because often higher-kinded types and lazy-evaluation is either mental overhead or leads to unpredictable performance (looking at you Haskell), so that the programmer doesn't get the idea to get too fancy, when the issue at hand is much more simple. Also often the syntax is a little bit boilerplaty compared to something like Haskell, but also this could be seen as a good thing, as everything is "documented" within it, IMHO it feels easier to read that way (as long not, something isn't hidden behind a crazy (proc-)macro (which still can be a good thing, but should be used carefully)).
Non the less I think it could improve with more advanced type-metaprogramming (and inference), because often you have like 5 lines of trait-bounds that are not really interesting for the end-user and should IMHO be inferenced (and communicated by the compiler otherwise). But I think after reading a few articles of compiler devs (like https://smallcultfollowing.com/babysteps/blog/2022/09/22/rust-2024-the-year-of-everywhere/) I think this will indeed improve soon, and it did already considerably over the time I'm programming in Rust.
@cercerilla I got my first taste of programming at uni, by doing some scientific computing and then taking a couple CS electives. One day not long after that, while was wikiwandering through articles on programming languages, the notion of functional programming caught my eye. I played a bit with the interpreter at tryhaskell.org, and soon enough was working my way through the Haskell Wikibook, amazed at the clarity of expression afforded by language and paradigm. Having fun with FP ever since :)
I originally got into FP through university. We used HUGS (haskell variant) and the things that really drew me in were the concepts of laziness, and non-shared state. At the time I only had experience with imperative languages, but could see the benefits in terms of scalability (network computing) through the immutable data structures, and having a "pull" style mechanism for consuming sequences, delaying computation until it was actually required.
I dropped FP after that course, and for around next 10 years only did imperative programming. Then Clojure came on my radar via Overtone, and I've been into FP again ever since. Wanting to make music with code really drove me to learn clojure.
Peter Norvig and LISP.
Then I learned Haskell on my own.
Back in college, I had a class where we built a simple Scheme interpreter in Standard ML. The professor also demonstrated a taste of Haskell. I eventually plugged in to the local functional-programming community, which was into cooler stuff in general, and later got a full-time job working in Scala.
Heavy, inheritance-based object-oriented programming as in 1990s- and early 2000s-style C++ and Java feels tedious and inefficient in comparison.
I took a PL class in college, and we used Scheme. Ever since then, I noticed the concepts that I learned in that class seeping into other PLs. At the time I was programming Java 7 and JavaScript (ECMAScript 6). As soon as Java 8 hit, they had their stream API, and around the same time TC39 started adding FP-influenced APIs to JS.
My exposure to FP has not been "pure", but I have really enjoyed its influence in the languages that I use every day (Rust being the latest).
Started my career as a Java dev, Scala was just starting to take off at the time (circa 2016, so for instance LinkedIn had recently been rewritten from Ruby On Rails to using Scala with Play Framework and a generally stateless paradigm), so I started tinkering with it and Play Framework. When Java started picking up more FP features I started using them in my day job. In addition to all that, I started learning Python and Rust around that time, which influenced how I tended to use those languages as well, leaning more towards a Functional paradigm than OO or imperative. These days my job is primarily in Python, but I constantly use Functional style in my Python code.
I took a course on the theory of programming languages, which spent a lot of time on type systems and introduced my to O'Caml. I then looked at Haskell, fell in love, and used it in all of my personal projects for the next several years. (I mentioned this once to the professor who taught the class, and he admitted that that selling people on typed functional languages was basically one of the unofficial goals of the class. :-) )
After watching some FP popularization talks on Youtube I tried to learn Haskell and Clojure for fun, but quickly ran out of steam after first couple of exercises, feeling that I can't get real advantage here. Then the other day I needed to make a simple web app. Being new to frontend I thought to myself after tasting all the recommended JS frameworks: there must be something better than this. After some research I picked up the "Elm in Action" by R. Feldman and everything just clicked :)
Our introductory CS course in university used the Racket student languages from How to Design Programs. I also took the Programming Languages course which used Typed Racket, and the Compilers course which used OCaml.
I got some tastes of FP while writing Ruby. And then I got times to tinker with Emacs Lisp. Fascinated by the idea of FP, I tried Clojure after that (without even knowing Java). And then I wanted to discover more Lisp-family languages: Common Lisp, Scheme, Racket, etc. You name it. This summer I was to learn Haskell, but got distracted by some university homeworks with Java Stream API...
I got interested in FP in 2004 when I realized that Intel's Netburst architecture wasn't frequency scaling as hard as expected and thus we'd inevitably have multiple execution threads as Moore's Law marched onward.
That led me to a bunch of unfocused part time wandering through OCaml, Scheme, and Common Lisp. I then got into Clojure and wrote that professionally for a few years but I've mostly been paid to write JS. I personally like functional leaning JS but I've settled on signals/dataflow programming as enough of a reduction in state to be useful while still being generally acceptable to most teams.