Is Ruby a Functional Language

Is Ruby a functional language?

I most definitely think you can use functional style in Ruby.

One of the most critical aspects to be able to program in a functional style is if the language supports higher order functions... which Ruby does.

That said, it's easy to program in Ruby in a non-functional style as well. Another key aspect of functional style is to not have state, and have real mathematical functions that always return the same value for a given set of inputs. This can be done in Ruby, but it is not enforced in the language like something more strictly functional like Haskell.

So, yeah, it supports functional style, but it also will let you program in a non-functional style as well.

Is it possible to do functional programming in a language without functions?

Yes. Method vs function is quite a fine distinction.

It's easy to view each particular method implementation as a function; just have it take as an extra parameter the object on which the method was invoked (if your language doesn't pass it explicitly; not terribly familiar with Ruby). That doesn't quite give you virtual method calls (i.e. where the particular implementation called is determined by the object at runtime). But it's also very easy to imagine a virtual method call as calling a function that just inspects its first parameter (self, this, whatever it's called) and uses it to determine which method implementation to call. With those conventions established, object.method(param1, param2) differs from method(object, param1, param2) only in a trivial syntactic way.

Personally, I view the above as "the truth", and that object-oriented languages just offer syntactic sugar and optimised execution for this because it's such a core part of writing/executing OO programs. That sort of system is also exactly how you do OO when you have functions but not true classes/methods.

It's also trivially easy to implement functions with methods, if you think methods aren't functions. Just have an object with a single method and no attributes! This is also how you do functional programming in languages like Java that insist upon everything being an object and don't let you pass methods/functions as first-class values.

All you need to do functional programming is things you can pass around as first-class values, which can be used to execute code determined by the creator of the "thing" (rather than determined by the code that's using the "thing"), on demand by code that has access to the "thing". I can't think of a programming language that doesn't have this capability.

Ruby's yield feature in relation to computer science

Ruby's yield is not an iterator like in C# and Python. yield itself is actually a really simple concept once you understand how blocks work in Ruby.

Yes, blocks are a functional programming feature, even though Ruby is not properly a functional language. In fact, Ruby uses the method lambda to create block objects, which is borrowed from Lisp's syntax for creating anonymous functions — which is what blocks are. From a computer science standpoint, Ruby's blocks (and Lisp's lambda functions) are closures. In Ruby, methods usually take only one block. (You can pass more, but it's awkward.)

The yield keyword in Ruby is just a way of calling a block that's been given to a method. These two examples are equivalent:

def with_log
output = yield # We're calling our block here with yield
puts "Returned value is #{output}"
end

def with_log(&stuff_to_do) # the & tells Ruby to convert into
# an object without calling lambda
output = stuff_to_do.call # We're explicitly calling the block here
puts "Returned value is #{output}"
end

In the first case, we're just assuming there's a block and say to call it. In the other, Ruby wraps the block in an object and passes it as an argument. The first is more efficient and readable, but they're effectively the same. You'd call either one like this:

with_log do
a = 5
other_num = gets.to_i
@my_var = a + other_num
end

And it would print the value that wound up getting assigned to @my_var. (OK, so that's a completely stupid function, but I think you get the idea.)

Blocks are used for a lot of things in Ruby. Almost every place you'd use a loop in a language like Java, it's replaced in Ruby with methods that take blocks. For example,

[1,2,3].each {|value| print value} # prints "123"
[1,2,3].map {|value| 2**value} # returns [2, 4, 8]
[1,2,3].reject {|value| value % 2 == 0} # returns [1, 3]

As Andrew noted, it's also commonly used for opening files and many other places. Basically anytime you have a standard function that could use some custom logic (like sorting an array or processing a file), you'll use a block. There are other uses too, but this answer is already so long I'm afraid it will cause heart attacks in readers with weaker constitutions. Hopefully this clears up the confusion on this topic.

Imperative vs Functional Programming in Ruby

You're not wrong. It is often the case that a purely functional solution will be slower than a destructive one. Immutable values generally mean a lot more allocation has to go on unless the language is very well optimized for them (which Ruby isn't).

However, it doesn't often matter. Worrying about the performance of specific operations is not a great use of your time 99% of the time. Shaving off a microsecond from a piece of code that runs 100 times a second is simply not a win.

The best approach is usually to do whatever makes your code cleanest. Very often this means taking advantage of the functional features of the language — for example, map and select instead of map! and keep_if. Then, if you need to speed things up, you have a nice, clean codebase that you can make changes to without fear that your changes will make one piece of code stomp over another piece's data.

If functional languages are really concise, why don't they have a better rank in the language shootout game?

  1. No language is always superior to another (well, there are a few exceptions... ;) ), so same applies for a group of broadly categorized languages. The benchmarks cover a broad array of topics, and X may be less suited for one than Y.
  2. The source code is gzipped, we don't really know how many lines of what length the programs were (yeah, it's an indicator)
  3. A considerable number of functional languages still do much better than the widespread imperative, static languages - it's not that functional programming languages aren't succinct, but the dynamic languages allow even more succinct programs
  4. At least in Haskell, much potential for conciseness comes from abstractions you can build yourself - but you do have to build them yourself and include them in your solution. A clever Haskell hacker may implement a monad in 20 lines that allows solving a small problem in 20 lines instead of 30 - the abstraction doesn't pay off for a small program, but could save many lines in a larger (eg. 200 lines instead of 300) program. I guess the same applies for Lisps (only macro instead of monad)
  5. Don't take the fanboys too seriously. FP is awesome and worth looking into, but it doesn't cure cancer and doesn't magically shorten any code by 25%
  6. They can still beat dynamic languages for some areas: For example, tree-like data structures and their processing is expressed extremely naturally in many functional languages, thanks to algebraic data types and pattern matching.

Is there a functional programming concept equivalent to the flip-flop operator in Perl or Ruby?

In a functional language such as haskell, you would pass in the flip and flop conditions as predicates, and filter an input list based on it. For example, the following is a definition of flipflop in haskell (don't worry about the implementation if you don't know haskell - the key part is how it is used):

flipflop flip flop = 
uncurry (++) . second (take 1) . break flop . dropWhile (not . flip)

This is how it can be used:

> flipflop (== 3) (== 5) [1..10]
[3,4,5]

It is an example of making an effectively new language construct just by using higher ordered function.

I don't know if there is a special name for that construct in functional languages.

Is Ruby's returning of a different type after a filter unusual from a functional programming perspective?

Which language does "perfectly implement the functional programming paradigm"? Haskell, Erlang, Pure, OCaml, Clojure? Pick your choice, they all tend to do things quite differently. I'm really not trying to be polemic here (I run a functional programming user group where we love discussing this type of stuff), but as with OOP, there are different ideas as what functional programming entails.

Now while most people wouldn't argue that Haskell leads the field in purity, it's by no means the only way to do FP. IMHO Michael Fogus and Chris Houser summed it up quite well in "The Joy of Clojure":

Functional programming concerns and
facilitates the application and
composition of functions. Further,
for a language to be considered
functional, its notion of function
must be first-class. The functions of
a language must be able to be stored,
passed, and returned just like any
other piece of data within that
language. It’s beyond this core
concept that the definitions branch
toward infinity, but thankfully, it’s
enough to start.

A function isn't really more than some sort of mapping from the domain to the codomain, and the two most certainly don't have to be the same. If you look at a function like f(x) = sqrt(x) and assume N (the natural numbers) to be the domain of f, it's quite obvious that the codomain will not be the same (unless you want a function that's undefined over large stretches).

With all that said, I don't think that this behavior is specifically problematic. Aligning the types (even though we don't commonly use this term in Ruby) is the responsibility of the developer, not the language. The latter can assist in finding those mismatches and also differ in when they find them (e.g. compile time vs run time).

As Mladen said, there are lots of things that prevent Ruby from being a purely functional language, but that's true for most languages, quite a few of them being functional languages themselves (Clojure e.g. commonly favors usability and pragmatism over purity). It is however quite possible to program in a very functional style in Ruby, if one really wants to and pays attention to some details. Here are some links on the topic:

  • Better Ruby through Functional Programming
  • Thinking Functionally in Ruby (PDF)
  • Thinking Functionally in Ruby (Talk)


Related Topics



Leave a reply



Submit