Related
I'm learning scheme and until now have been using guile. I'm really just learning as a way to teach myself a functional programming language, but I'd like to publish an open source project of some sort to reenforce the study— not sure what yet... I'm a web developer, so probably something webby.
It's becoming apparent that publishing scheme code isn't very easy to do, with all these different implementations and no real standards beyond the core of the language itself (R5RS). For example, I'm almost certainly going to need to do basic IO on disk and over a TCP socket, along with string manipulation, such as scanning/regex, which seems not to be covered by R5RS, unless I'm not seeing it in the document. It seems like Scheme is more of a "concept" than a practical language... is this a fair assessment? Perhaps I should look to something like Haskell if I want to learn a functional programming language that lends itself more to use in open source projects?
In reality, how much pain do the differing scheme implementations pose when you want to publish an open source project? I don't really fancy having to maintain 5 different functions for basic things like string manipulation under various mainstream implementations (Chicken, guile, MIT, DrRacket). How many people actually write scheme for cross-implementation compatibility, as opposed to being tightly coupled with the library functions that only exist in their own scheme?
I have read http://www.ccs.neu.edu/home/dorai/scmxlate/scheme-boston/talk.html, which doesn't fill me with confidence ;)
EDIT | Let's re-define "standard" as "common".
I believe that in Scheme, portability is a fool's errand, since Scheme implementations are more different than they are similar, and there is no single implementation that other implementations try to emulate (unlike Python and Ruby, for example).
Thus, portability in Scheme is analogous to using software rendering for writing games "because it's in the common subset between OpenGL and DirectX". In other words, it's a lowest common denominator—it can be done, but you lose access to many features that the implementation offers.
For this reason, while SRFIs generally have a portable reference implementation (where practical), some of them are accompanied by notes that a quality Scheme implementation should tailor the library to use implementation-specific features in order to function optimally.
A prime example is case-lambda (SRFI 16); it can be implemented portably, and the reference implementation demonstrates it, but it's definitely less optimal compared to a built-in case-lambda, since you're having to implement function dispatch in "user" code.
Another example is stream-constant from SRFI 41. The reference implementation uses an O(n) simulation of circular lists for portability, but any decent implementation should adapt that function to use real circular lists so that it's O(1).†
The list goes on. Many useful things in Scheme are not portable—SRFIs help make more features portable, but there's no way that SRFIs can cover everything. If you want to get useful work done efficiently, chances are pretty good you will have to use non-portable features. The best you can do, I think, is to write a façade to encapsulate those features that aren't already covered by SRFIs.
† There is actually now a way to implement stream-constant in an O(1) fashion without using circular lists at all. Portable and fast for the win!
Difficult question.
Most people decide to be pragmatic. If portability between implementations is important, they write the bulk of the program in standard Scheme and isolate non-standard parts in (smallish) libraries. There have been various approaches of how exactly to do this. One recent effort is SnowFort.
http://snow.iro.umontreal.ca/
An older effort is SLIB.
http://people.csail.mit.edu/jaffer/SLIB
If you look - or ask for - libraries for regular expressions and lexer/parsers you'll quickly find some.
Since the philosophy of R5RS is to include only those language features that all implementors agree on, the standard is small - but also very stable.
However for "real world" programming R5RS might not be the best fit.
Therefore R6RS (and R7RS?) include more "real world" libraries.
That said if you only need portability because it seems to be the Right Thing, then reconsider carefully if you really want to put the effort in.
I would simply write my program on the implementation I know the best. Then if necessary port it afterwards. This often turns out to be easier than expected.
I write a blog that uses Scheme as its implementation language. Because I don't want to alienate users of any particular implementation of Scheme, I write in a restricted dialect of Scheme that is based on R5RS plus syntax-case macros plus my Standard Prelude. I don't find that overly restrictive for the kind of algorithmic programs that I write, but your needs may be different. If you look at the various exercises on the blog, you will see that I wrote my own regular-expression matcher, that I've done a fair amount of string manipulation, and that I've snatched files from the internet by shelling out to wget (I use Chez Scheme -- users have to provide their own non-portable shell mechanism if they use anything else); I've even done some limited graphics work by writing ANSI terminal sequences.
I'll disagree just a little bit with Jens. Instead of porting afterwards, I find it easier to build in portability from the beginning. I didn't use to think that way, but my experience over the last three years shows that it works.
It's worth pointing out that modern Scheme implementations are themselves fairly portable; you can often port whole programs to new environments simply by bringing the appropriate Scheme along. That doesn't help library programmers much, though, and that's where R7RS-small, the latest Scheme definition, comes in. It's not widely implemented yet, but it provides a larger common core than R5RS.
What do you lose in practice when you choose a statically-typed language such as Scala (or F#, Haskell, C#) instead of dynamically-typed ones like Ruby, Python, Clojure, Groovy (which have macros or runtime metaprogramming capabilities)? Please consider best statically-typed languages and best (in your opinion) dynamically-typed languages, not the worst ones.
Answers Summary:
Key advantages of dynamic languages like Ruby over statically-typed language like Scala IMHO are:
Quick edit-run cycle (does JavaRebel reduces the gap?)
Currently community of Scala/Lift is much smaller then of Ruby/Rails or Python/Django
Possible to modify type definitions (though motivation or need for that is not very clear)
In principle, you give up being able to ignore what type you're using when it is not clear (in the static context) what the right thing to do is, and that's about it.
Since complex type-checking can be rather time-consuming, you also probably are forced to give up fast on-line metaprogramming.
In practice, with Scala, you give up very little else--and nothing that I particularly care about. You can't inject new methods, but you can compile and run new code. You do have to specify types in function arguments (and the return type with recursive functions), which is slightly annoying if you never make type errors yourself. Since it compiles each command, the Scala REPL isn't as snappy as e.g. the Python shell. And since it uses Java reflection mechanisms, you don't have quite the ease of online inspection that you do with e.g. Python (not without building your own inspection library, anyway).
The choice of which static or dynamic language is more significant than the static/dynamic choice itself. Some dynamic languages have good performance and good tools. Some static languages can be concise, expressive, and incremental. Some languages have few of these qualities, but do have large libraries of proven code.
Dynamic languages tend to have much more flexible type systems. For example, Python lets you inject a new method into an existing classes, or even into a single object.
Many (not all) static languages lack the facility to construct complex literals. For instance, languages like C# and Java cannot easily mimic the following JavaScript { 'request':{'type':'GET', 'path':mypath}, 'oncomplete':function(response) { alert(response.result) } }.
Dynamic languages have very fluid semantics. Python allows import statements, function definitions and class definitions to appear inside functions and if statements.
eval is a staple of most dynamic languages and few static languages.
Higher order programming is easier (in my subjective opinion) in dynamic languages than static languages, due to the awkwardness of having to fully specify the types of function parameters.
This is particulary so with recursive HOP constructs where the type system can really get in the way.
Dynamic language users don't have to deal with covariance and contravariance.
Generic programming comes practically free in dynamic languages.
I'm not sure if you lose anything but simplicity. Static type systems are an additional burden to learn.
I suppose you usually also lose eval, but I never use it, even in dynamic languages.
I find the issue is much more about everything else when it comes to choosing which language to use for a given task. Tooling, culture, libraries are all much more interesting than typing when it comes to solving a problem with a language.
Programming language research, on the other hand, is completely different. :)
Some criticism of Scala has been expressed by Steve Yegge here and here, and by Guido van Rossum, who mainly attacked Scala's type system complexity. They clearly aren't "Scala programmers" though. On the other hand, here's some praise from James Strachan.
My 2 cents...
IMO (strong) statically-typed languages might reduce the amount of necessary testing code, because some of that work will be done by the compiler. On the other hand, if the compiling step is relatively long, it makes it more difficult to do "incremental-style" programming, which in the real life might result in error-prone code that was only tested to pass the compiler.
On the other hand, dynamically-typed languages feel like there is less threshold to change things, that might reduce the responding time from the point of bug-fixing and improvement, and as a result might provide a smoother curve during application development: handling constant flow of small changes is easier/less risky than handling changes which are coming in bug chunks.
For example, for the project where the design is very unclear and is supposed to change often, it might have been easier to use dynamic language than a static one, if it helps reduce interdependencies between different parts. (I don't insist on that one though:) )
I think Scala sits somewhere in between (e.g. you don't have to explicitly specify types of the variables, which might ease up code maintenance in comparison with e.g. C++, but if you end up with the wrong assumption about types, the compiler will remind about it, unlike in PHP where you can write whatever and if you don't have good tests covering the functionality, you are doomed to find it out when everything is live and bleeding). Might be terribly wrong of course :)
In my opinion, the difference between the static and dynamic typing comes down to the style of coding. Although there is structural types in Scala, most of the time the programmer is thinking in terms of the type of the object including cool gadgets like trait. On the other hand, I think Python/Javascript/Ruby programmers think in terms of prototype of the object (list of methods and properties), which is slightly different from types.
For example, suppose there's a family of classes called Vehicle whose subclasses include Plane, Train, and Automobile; and another family of classes called Animal whose subclasses include Cat, Dog, and Horse. A Scala programmer would probably create a trait called Transportation or something which has
def ride: SomeResult
def ride(rider: Someone): SomeResult
as a member, so she can handle both Train and Horse as a means of transportation. A Python programmer would just pass the train object without additional code. At the run time the language figures out that the object supports ride.
The fact that the method invocations are resolved at the runtime allows languages like Python and Ruby to have libraries that redefines the meaning of properties or methods. A good example of that is O/R mapping or XML data binding, in which undefined property name is interpreted to be the field name in a table/XML type. I think this is what people mean by "flexibility."
In my very limited experience of using dynamic languages, I think it's faster coding in them as long as you don't make mistakes. And probably as you or your coworkers get good at coding in dynamic language, they would make less mistakes or start writing more unit tests (good luck). In my limited experience, it took me very long to find simple errors in dynamic languages that Scala can catch in a second. Also having all types at compile time makes refactoring easier.
I have recently been looking around to learn a new language during my spare time and Scala seems to be very attractive.
I have a few questions regarding it:
Will not knowing Java impose a
challange in learning it? Will it be
a big disadvantage
later on? ( i.e How often do people rely on
Java-specific libraries? )
How big of a difference it is
compared to Ruby? (Apart from being
statically typed) Does it introduce
a lot of new terms, or will I be
familiar with most of the language's
mechanisms?
What resources would you recommend?
I have my eye on Programming Scala
and Beginning Scala books
Although subjective, is Scala fun to programme in? : P
Thanks
There are many concepts that are shared between Ruby and Scala. It's been a while since I've coded Ruby, so this isn't exhaustive.
Ruby <==> Scala (Approximately!)
Mixins <==> Traits
Monkey Patching <==> Pimp My Library (Implicit Conversions to a wrapper with extra methods)
Proc/Closure <==> Function/Function Literal
Duck Typing <==> Structural Types
Last Argument as a Proc <==> Curried Parameter List (see Traversable#flatMap)
Enumerable <==> Traversable
collect <==> map
inject <==> foldLeft/foldRight
Symbol.toProc <==> Placeholder syntactic sugar: people.map(_.name)
Dynamic Typing conciseness <==> Type Inference
Nil <==> null, although Option is preferable. (Not Nil, which is an empty list!)
Everything is an expression <==> ditto
symbols/hashes as arguments <==> Named and Default Parameters
Singleton <==> object Foo {}
Everthing is an object <==> Everthing is a type or an object (including functions)
No Primitives <==> Unified type system, Any is supertype for primitives and objects.
Everything is a message <==> Operators are just method calls
Ruby's Features you might miss
method_missing
define_method etc
Scala Features you should learn
Pattern Matching
Immutable Classes, in particular Case Classes
Implicit Views and Implicit Parameters
Types, Types, and more Types: Generics, Variance, Abstract Type Members
Unification of Objects and Functions, special meaning of apply and update methods.
Here is my take on it:
Never mind not knowing Java.
Scala relies a lot on Java libraries. That doesn't matter at all. You might have trouble reading some examples, sure, but not enough to be a hindrance. With little time, you won't even notice the difference between reading a Java API doc and a Scala API doc (well, except for the completely different style of the newest scaladoc).
Familiarity with the JVM environment, however, is often assumed. If I can make one advise here, it is to avoid Maven at first, and use SBT as a build tool. It will be unnecessary for small programs, but it will make much of the kinks in the Java-lang world easier to deal with. As soon as you want an external library, get to know SBT. With it, you won't have to deal with any XML: you write your build rules in Scala itself.
You may find it hard to get the type concepts and terms. Scala not only is statically typed, but it has one of the most powerful type systems on non-academic languages out there. I'm betting this will be the source of most difficulty for you. Other concepts have different terminology, but you'll quickly draw parallels with Ruby.
This is not that big of a hurdle, though -- you can overcome it if you want to. The major downside is that you'll probably feel any other statically typed language you learn afterwards to be clumsy and limited.
You didn't mention which Programming Scala you had your eyes on. There are two, plus one Programming in Scala. That latter one was written, among others, by the language creator, and is widely considered to be an excellent book, though, perhaps, a bit slow. One of the Programming Scala was written by a Twitter guy -- Alex Payne -- and by ex-Object Mentor's Dean Wampler. It's a very good book too. Beginning Scala was written by Lift's creator, David Pollack, and people have said good things about it to. I haven't heard anyone complain about any of the Scala books, in fact.
One of these books would certainly be helpful. Also, support on Stack Overflow for Scala questions is pretty good -- I do my best to ensure so! :-) There's the scala-users mailing list, where one can get answers too (as long as people aren't very busy), and there's the #scala IRC channel on Freenode, where you'll get good support as well. Sometimes people are just not around, but, if they are, they'll help you.
Finally, there are blogs. The best one for beginners is probably Daily Scala. You can find many, many others are Planet Scala. Among them, my own Algorithmically Challenged, which isn't getting much love of late, but I'll get back to it. :-)
Scala has restored fun in programming for me. Of course, I was doing Java, which is booooring, imho. One reason I spend so much time answering Stack Overflow questions, is that I enjoy working out solutions for the questions asked.
I'm going to introduce a note of caution about how much Java knowledge is required because I disagree that it isn't an issue at all. There are things about Java that are directly relevant to scala and which you should understand.
The Java Memory Model and what mechanisms the platform provides for concurrency. I'm talking about synchronization, threads etc
The difference between primitive types (double, float etc) and reference types (i.e. subclasses of Object). Scala provides some nice mechanisms to hide this from the developer but it is very important, if writing code which must be performant, to know how these work
This goes both ways: the Java runtime provides features that (I suspect, although I may be wrong) are not available in Ruby and will be of enormous benefit to you:
Management Extensions (MBeans)
JConsole (for runtime monitoring of memory, CPU, debugging concurrency problems)
JVisualVM (for runtime instrumentation of code to debug memory and performance problems)
These points #1 and #2 are not insurmountable obstacles and I think that the other similarities mentioned here will work strongly in your favour. Oh, and Scala is most certainly a lot of fun!
I do not have a Ruby background but nevertheless, I might be able to help you out.
I don't thing not knowing Java is a disadvantage, but it might help. In my opinion, Java libraries are used relatively often, but even a trained Java coder don't know them all, so no disadvantage here. You will learn some parts of the Java library by learning Scala because even the Scala libraries use them.
--
I started out by reading Programming Scala and turned over to read the source of the Scala library. The latter helped a lot to understand the language. And as always: Code, Code, Code. Reading without coding wont get you anywhere, but I'm sure you know that already. :-)
Another helpful resources are blogs, see https://stackoverflow.com/questions/1445003/what-scala-blogs-do-you-regularly-follow for a compilation of good Scala blogs.
It is! As you stated, this is very subjective. But for me, coming from a Java background, It is a lot of fun.
This is very late, but I agree to some extent with what oxbow_lakes said. I have recently transitioned from Python to Scala, and knowing how Java works -- especially Java limitations regarding generic types -- has helped me understand certain aspects of Scala.
Most noticeably:
Java has a horribly broken misfeature known as "type erasure". This brokenness is unfortunately present in the JVM as well. This particularly affects programming with generic types -- an issue that simply doesn't come up at all in dynamically-typed languages like Ruby and Python but is very big in statically typed languages. Scala does about as good a job as it can working around this, but the magnitude of the breakage means that some of it inevitably bleeds through into Scala. In addition, some of the fixes in Scala for this issue (e.g. manifests) are recent and hackish, and really require an understanding of what's going in underneath. Note that this problem will probably not affect your understanding of Scala at first, but you'll run up against it when you start writing real programs that use generic types, as there are things you'll try to do that just won't work, and you won't know why unless/until you understand the limitations forced by type erasure.
Sooner or later you'll also run up against issues related to another Java misfeature, which is the division of types into objects (classes) vs. primitive types (ints, floats, booleans) -- and in particular, the fact that primitive types aren't part of the object system. Scala actually does an awesome job hiding this from you, but it can be helpful to know about what Java is doing in certain corner cases that otherwise may be tricky -- particularly involving generic types, largely because of the type-erasure brokenness described in #1. (Type erasure also results in a major performance hit when using arrays, hash tables, and similar generic types over primitives; this is one area where knowing Java will help a lot.)
Misfeature #3 -- arrays are also handled specially and non-orthogonally in Java. Scala's hiding of this is not quite as seamless as for primitives, but much better than for type erasure. The hiding mechanism sometimes gets exposed (e.g. the ArrayWrapper type), which may occasionally lead to issues -- but the biggest problem in practice, not surprisingly, is again with generic types.
Scala class parameters and the way that Scala handles class constructors. In this case, Java isn't broken. Arguably, Scala isn't either, but the way it handles class constructors is rather unusual, and in practice I've had a hard time understanding it. I've only really been able to make sense of Scala's behavior by figuring out how the relevant Scala code gets translated into Java (or more correctly, into compiled Java), and then reasoning over what Java would do. Since I assume that Ruby works much like Java in this respect, I don't think you'll run into too many problems, although you might have to do the same mental conversion.
I/O. This is actually a library issue rather than a language issue. In most cases, Scala provides its own libraries, but Scala doesn't really have an I/O library, so you pretty much have no choice but to use Java's I/O library directly. For a Python or Ruby programmer, this transition is a bit painful, since Java's I/O library is big and bulky, and not terribly easy to use for doing simple tasks, e.g. iterating over all the lines in a file.
Note that besides I/O, you also need to use Java libraries directly for other cases where you interact with the OS or related tasks, e.g. working with times and dates or getting environment variables, but usually this isn't too hard to figure out. The other main Java libraries you might need to use are
Subprocess invocation, also somewhat big and bulky
Networking -- but this is always somewhat painful
Reflection, i.e. dynamically examining the methods and/or fields on a class, or dynamically invoking a method by name when the name isn't known at compile time. This is somewhat esoteric stuff that most people don't need to deal with. Apparently Scala 2.10 will have its own reflection library, but currently you have to use the Java reflection API's, which means you need to know a fair amount about how Scala gets converted to Java. (Thankfully, there's a -print option to the Scala compiler to show exactly how this conversion happens.)
Re. point 1. Not being familiar with Java the language is not necessarily a problem. 3rd party libraries integrate largely seamlessly into Scala. However some awareness of the differences in collections may be good (e.g. a Scala list is not a traditional Java list, and APIs may expect the latter).
The Java-related skills that carry over are related to Java the platform. i.e. you're still working with a JVM that performs class-loading, garbage collection, JIT compilation etc. So experience in this is useful. But not at all necessary.
Note that Scala 2.8 is imminent, and there are some incompatible changes wrt. 2.7. So any book etc. you buy should be aware of such differences.
This is another late answer, having recently come to Scala myself, but I can answer 1, 3, and 4:
1) I ported a large, multifaceted F# project to Scala without any use of either Java or .NET libraries. So for many projects, one can stick totally to native Scala. Java ecosystem knowledge would be a plus, but it can be acquired gradually during and after learning Scala.
3) Programming in Scala is not only great for learning Scala, it's one of the few truly readable computer books on any language. And it's handy for later reference.
4) I've used close to a dozen different programming languages, from assembly languages to Prolog, but Scala and F# are the two most fun programming languages I've ever used -- by a wide margin. (Scala and F# are very similar, an example of "convergent evolution" in two different ecosystems -- JVM and .NET.)
-Neil
I've been looking at Haskell lately and it seems like a very nice way to watch programming problems from an alternative point of view - alternative to my usual imperative (I have a strong C++ background) view, at least.
However, all the articles I see seem to deal with the same kinds of programming problems:
Parsers
Compilers
Numeric computation problems
I'd like to give Haskell a try myself, by writing some GUI application. Hence, I'm wondering: does it make sense to write event-driven systems like GUIs in a functional programming language like Haskell? Or is that a problem domain at which imperative languages excel? Unfortunately it still takes quite some time for me to switch my mind to 'functional' mode, so I have a hard time deciding argueing against or in favor of using a functional programming language for an event-driven system.
I'd also be interested in examples of GUI applications (or event-driven systems, in general) which are implemented in Haskell.
Here's a couple of Google keywords for you:
Functional Reactive Programming (FRP), a programming paradigm for, well reactive (aka event-driven) programming in purely functional languages,
Leksah, a Haskell IDE written in Haskell,
Yi, an Emacs-like editor which replaces Lisp with Haskell as the implementation, configuration, customization and scripting language,
Super Monao Bros. (yes, you guessed it, a Jump&Run game)
Frag (First-Person Shooter)
Purely Functional Retrogames is a 4-part series of blog articles about how to write games in a purely functional language, explained using Pacman as the example. (Part 2, Part 3, Part 4.)
xmonad is an X11 window manager written in Haskell.
Also, looking at how the various Haskell GUI Libraries are implemented may give some ideas of how interactive programs are made in Haskell.
Here's an example using epoll to implement an event driven web server: http://haskell.org/haskellwiki/Simple_Servers
Take a look at this wikibooks article, it's a basic wxHaskell tutorial. In particular see the Events section.
I recommend spending some quality time with Haskell and FP in general before jumping in to develop a fully-fledged application so you can get more familiarized with Haskell, since it's quite different from C++
xmonad is event-driven -- see the main event handling loop, which takes messages from the X server, and dispatches to purely functional code, which in turn renders state out to the screen.
"Functional reactive programming" was already mentioned, but it may seem complicated if you're looking at it for the first time (and if you're looking at some advanced articles, it will look complicated no matter how long have you studied it :-)). However, there are some very nice articles that will help you understand it:
Composing Reactive Animations by Conal Elliott shows a "combinator library" (a common programming style in functional languages) for describing animations. It starts with very simple examples, but shows also more interesting "reactive" bit in the second part.
Yampa Arcade is a more evolved demo of Functional Reactive Programming. It uses some advanced Haskell features (such as Arrows), but is still very readable. Getting it to actually run may be more complicated, but it is an excellent reading.
Haskell School of Expression by Paul Hudak is a book which teaches Haskell using multimedia and graphics (including some animations etc.). It is an excellent reading, but it takes more time as it is an entire book :-).
I find my way to functional programming through F#, which is a bit less "pure" compared to Haskell, but it gives you a full access to .NET libraries, so it is easy to use "real-world" technologies from a functional language. In case you were interested, there are a couple of examples on my blog.
Wikipedia says Ruby is a functional language, but I'm not convinced. Why or why not?
Whether a language is or is not a functional language is unimportant. Functional Programming is a thesis, best explained by Philip Wadler (The Essence of Functional Programming) and John Hughes (Why Functional Programming Matters).
A meaningful question is, 'How amenable is Ruby to achieving the thesis of functional programming?' The answer is 'very poorly'.
I gave a talk on this just recently. Here are the slides.
Ruby does support higher-level functions (see Array#map, inject, & select), but it is still an imperative, Object-Oriented language.
One of the key characteristics of a functional language it that it avoids mutable state. Functional languages do not have the concept of a variable as you would have in Ruby, C, Java, or any other imperative language.
Another key characteristic of a functional language is that it focuses on defining a program in terms of "what", rather than "how". When programming in an OO language, we write classes & methods to hide the implementation (the "how") from the "what" (the class/method name), but in the end these methods are still written using a sequence of statements. In a functional language, you do not specify a sequence of execution, even at the lowest level.
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.
I submit that supporting, or having the ability to program in a language in a functional style does not a functional language make.
I can even write Java code in a functional style if I want to hurt my collegues, and myself a few months weeks on.
Having a functional language is not only about what you can do, such as higher-order functions, first-class functions and currying. It is also about what you cannot do, like side-effects in pure functions.
This is important because it is a big part of the reason why functional programs are, or functional code in generel is, easier to reason about. And when code is easier to reason about, bugs become shallower and float to the conceptual surface where they can be fixed, which in turn gives less buggy code.
Ruby is object-oriented at its core, so even though it has reasonably good support for a functional style, it is not itself a functional language.
That's my non-scientific opinion anyway.
Edit:
In retrospect and with consideration for the fine comments I have recieved to this answer thus far, I think the object-oriented versus functional comparison is one of apples and oranges.
The real differentiator is that of being imparative in execution, or not. Functional languages have the expression as their primary linguistic construct and the order of execution is often undefined or defined as being lazy. Strict execution is possible but only used when needed. In an imparative language, strict execution is the default and while lazy execution is possible, it is often kludgy to do and can have unpredictable results in many edge cases.
Now, that's my non-scientific opinion.
Ruby will have to meet the following requirements in order to be "TRUELY" functional.
Immutable values: once a “variable” is set, it cannot be changed. In Ruby, this means you effectively have to treat variables like constants. The is not fully supported in the language, you will have to freeze each variable manually.
No side-effects: when passed a given value, a function must always return the same result. This goes hand in hand with having immutable values; a function can never take a value and change it, as this would be causing a side-effect that is tangential to returning a result.
Higher-order functions: these are functions that allow functions as arguments, or use functions as the return value. This is, arguably, one of the most critical features of any functional language.
Currying: enabled by higher-order functions, currying is transforming a function that takes multiple arguments into a function that takes one argument. This goes hand in hand with partial function application, which is transforming a multi-argument function into a function that takes less arguments then it did originally.
Recursion: looping by calling a function from within itself. When you don’t have access to mutable data, recursion is used to build up and chain data construction. This is because looping is not a functional concept, as it requires variables to be passed around to store the state of the loop at a given time.
Lazy-evaluation, or delayed-evaluation: delaying processing of values until the moment when it is actually needed. If, as an example, you have some code that generated list of Fibonacci numbers with lazy-evaluation enabled, this would not actually be processed and calculated until one of the values in the result was required by another function, such as puts.
Proposal (Just a thought)
I would be of great to have some kind of definition to have a mode directive to declare files with functional paradigm, example
mode 'functional'
Ruby is a multi-paradigm language that supports a functional style of programming.
Ruby is an object-oriented language, that can support other paradigms (functional, imperative, etc). However, since everything in Ruby is an object, it's primarily an OO language.
example:
"hello".reverse() = "olleh", every string is a string object instance and so on and so forth.
Read up here or here
It depends on your definition of a “functional language”. Personally, I think the term is itself quite problematic when used as an absolute. The are more aspects to being a “functional language” than mere language features and most depend on where you're looking from. For instance, the culture surrounding the language is quite important in this regard. Does it encourage a functional style? What about the available libraries? Do they encourage you to use them in a functional way?
Most people would call Scheme a functional language, for example. But what about Common Lisp? Apart from the multiple-/single-namespace issue and guaranteed tail-call elimination (which some CL implementations support as well, depending on the compiler settings), there isn't much that makes Scheme as a language more suited to functional programming than Common Lisp, and still, most Lispers wouldn't call CL a functional language. Why? Because the culture surrounding it heavily depends on CL's imperative features (like the LOOP macro, for example, which most Schemers would probably frown upon).
On the other hand, a C programmer may well consider CL a functional language. Most code written in any Lisp dialect is certainly much more functional in style than your usual block of C code, after all. Likewise, Scheme is very much an imperative language as compared to Haskell. Therefore, I don't think there can ever be a definite yes/no answer. Whether to call a language functional or not heavily depends on your viewpoint.
Ruby isn't really much of a multi-paradigm language either, I think. Multi-paradigm tends to be used by people wanting to label their favorite language as something which is useful in many different areas.
I'd describe Ruby is an object-oriented scripting language. Yes, functions are first-class objects (sort of), but that doesn't really make it a functional language. IMO, I might add.
Recursion is common in functional programming. Almost any language does support recursion, but recursive algorithms are often ineffective if there is no tail call optimization (TCO).
Functional programming languages are capable of optimizing tail recursion and can execute such code in constant space. Some Ruby implementations do optimize tail recursion, the other don't, but in general Ruby implementations are not required to do TCO. See Does Ruby perform Tail Call Optimization?
So, if you write some Ruby functional style and rely on TCO of some particular implementation, your code may be very ineffective in another Ruby interpreter. I think this is why Ruby is not a functional language (neither is Python).
Strictly speaking, it doesn't make sense to describe a language as "functional"; most languages are capable of functional programming. Even C++ is.
Functional style is more or less a subset of imperative language features, supported with syntactic sugar and some compiler optimizations like immutability and tail-recursion flattening,
The latter arguably is a minor implementation-specific technicality and has nothing to do with the actual language. The x64 C# 4.0 compiler does tail-recursion optimization, whereas the x86 one doesn't for whatever stupid reason.
Syntactic sugar can usually be worked around to some extent or another, especially if the language has a programmable precompiler (i.e. C's #define).
It might be slightly more meaningful to ask, "does language __ support imperative programming?", and the answer, for instance with Lisp, is "no".
Please, have a look at the beginning of the book: "A-Great-Ruby-eBook". It discusses the very specific topic you are asking. You can do different types of programming in Ruby. If you want to program like functionally, you can do it. If you want to program like imperatively, you can do it. It is a definition question how functional Ruby in the end is. Please, see the reply by the user camflan.