summaryrefslogtreecommitdiff
path: root/ml
diff options
context:
space:
mode:
authormichele.simionato <devnull@localhost>2008-10-28 05:08:08 +0000
committermichele.simionato <devnull@localhost>2008-10-28 05:08:08 +0000
commit79ac60621ea0e56aaf131ca8695beff297708d48 (patch)
tree887fe2c33753deb1ce284a734df9dad80743b3c8 /ml
parent37df30254dbdbabb89a38cb8e067d479415f188d (diff)
downloadmicheles-79ac60621ea0e56aaf131ca8695beff297708d48.tar.gz
Various fixes and improvements
Diffstat (limited to 'ml')
-rw-r--r--ml/intro.txt132
1 files changed, 70 insertions, 62 deletions
diff --git a/ml/intro.txt b/ml/intro.txt
index 49388b0..bda328b 100644
--- a/ml/intro.txt
+++ b/ml/intro.txt
@@ -5,11 +5,12 @@ Functional Programming For Dynamic Programmers - Introduction
:date: December 2007
This is the first of a series of articles on functional programming in
-statically typed languages. It is intended for dynamic programmers, i.e.
-for programmers with a background in dynamically typed languages, such as Perl,
-Python, Ruby, or languages in the Lisp family. The approch is eminently practical
-and example-based; the main goal is to see if we can stole some good idea from
-statically typed languages. I will mostly consider languages in the ML family, because
+statically typed languages. It is intended for dynamic programmers,
+i.e. for programmers with a background in dynamically typed
+languages, such as Perl, Python, Ruby, or languages in the Lisp
+family. The approch is eminently practical and example-based; the main
+goal is to see if we can stole some good idea from statically typed
+languages. I will mostly consider languages in the ML family, because
they are pretty nice and much easier to understand than Haskell.
Declaration of intents
@@ -33,18 +34,18 @@ alternatives. ll never be loyal to a single language. The *forma
mentis* of the dynamic programmer is very different from the *forma
mentis* of the language evangelist: the dynamic programmer can be
enhaumored of language for a while, but his love will not be
-exclusive.
-This premise is important in order to undestand the goals of this series
-of articles. The goal is not advocating functional programming. Others
-have taken this role. For instance, there is an infamous
-article written by John Hughes in 1984 and titled
-`Why Functional Programming Matters`_ which begins with the sentence
-*This paper is an attempt to demonstrate to the “real world” that functional
-programming is vitally important, and also to help functional programmers
-exploit its advantages to the full by making it clear what those advantages are.*
-This is *not* the goal of this series of articles. The goal is this series if
-merely educational, to broaden the view of the world of my readers,
-including myself (after all, I am the first of my readers ;)
+exclusive. This premise is important in order to undestand the goals
+of this series of articles. The goal is not advocating functional
+programming. Others have taken this role. For instance, there is an
+infamous article written by John Hughes in 1984 and titled `Why
+Functional Programming Matters`_ which begins with the sentence *This
+paper is an attempt to demonstrate to the “real world” that functional
+programming is vitally important, and also to help functional
+programmers exploit its advantages to the full by making it clear what
+those advantages are.* This is *not* the goal of this series of
+articles. The goal is this series if merely educational, to broaden
+the view of the world of my readers, including myself (after all, I am
+the first of my readers ;)
A pragmatic programmer may rightly wonder why to study functional
languages, since their relevance in enterprise programming is
@@ -70,47 +71,53 @@ of mutation and side-effects. I will follow this tradition too
(a dynamic programmer has no obbligation
to be innovative at any cost, he may well decide to follow the traditional way).
-I will just add that I don't find the arguments against mutation and side effects
-terribly compelling. Certainy there are bugs due to mutation and side
-effects, but in my working experience they are relatively rare. Most of the bugs I have
-in my code are actually issue of business logic (I understood the specs incorrectly or the
-specs where incomplete); many others are due to an incomplete or wrong knowledge of
-the system I have work with; and others are due to the deadlines.
-I would have the same bugs even using a functional language.
-On the other hand, I have nothing against diminuishing the language-related bugs,
-even if they are a minority, so, let me contrast the functional way with the imperative
-way here. I will mostly use Python as an example of imperative language,
-because it is a language that I know well enough, and because it is
-so readable that the examples will be easy to understand even for
-programmers not familiar with Python.
+I will just add that I don't find the arguments against mutation and
+side effects terribly compelling. Certainy there are bugs due to
+mutation and side effects, but in my working experience they are
+relatively rare. Most of the bugs I have in my code are actually issue
+of business logic (I understood the specs incorrectly or the specs
+where incomplete); many others are due to an incomplete or wrong
+knowledge of the system I have work with; and others are due to the
+deadlines. I would have the same bugs even using a functional
+language. On the other hand, I have nothing against diminuishing the
+language-related bugs, even if they are a minority, so, let me
+contrast the functional way with the imperative way here. I will
+mostly use Python as an example of imperative language, because it is
+a language that I know well enough, and because it is so readable that
+the examples will be easy to understand even for programmers not
+familiar with Python.
Let me begin by discussing the concept of mutation.
When you write code like
>>> lst = []; lst.append(1)
-in Python you are mutating the list ``lst``: originally it is empty, after the ``append``
-operation it contains the number ``1``. Mutation is a potential source of bugs and
-there are various workaround to make the bugs less likely. For instance, Scheme and
-Ruby use the *bang convention*: the name of a function/method performing mutation ends
-with an exclamation mark, so that they are more visible to the programmer. Python has
-no bang, but there is the convention that mutating methods returns ``None`` and
-not the mutated object. Pure functional languages such as Haskell take a radication
-position and they just make everything immutable. Making everything immutable
-has big advantages especially in multithreaded programming, since different threads cannot
-interfere each other and you can just forget about locks. On the other hand, various
-programming patterns based on mutability (for instance keeping a registry of callbacks)
-becames impossible.
+in Python you are mutating the list ``lst``: originally it is empty,
+after the ``append`` operation it contains the number ``1``. Mutation
+is a potential source of bugs and there are various workaround to make
+the bugs less likely. For instance, Scheme and Ruby use the *bang
+convention*: the name of a function/method performing mutation ends
+with an exclamation mark, so that they are more visible to the
+programmer. Python has no bang, but there is the convention that
+mutating methods returns ``None`` and not the mutated object. Pure
+functional languages such as Haskell take a radication position and
+they just make everything immutable. Making everything immutable has
+big advantages especially in multithreaded programming, since
+different threads cannot interfere each other and you can just forget
+about locks. On the other hand, various programming patterns based on
+mutability (for instance keeping a registry of callbacks) becames
+impossible.
Another very common operation in imperative languages is rebinding a variable.
When you write code like
>>> i = 1; i = i+1
-in Python, you are explicitely rebinding the name ``i`` which originally
-points to the value ``1``, making it to point to the value ``2``.
-This looks like an harmless operation. It is however not so harmless and it may be
-the source of subtle bugs. Consider for instance the following example
+in Python, you are explicitely rebinding the name ``i`` which
+originally points to the value ``1``, making it to point to the value
+``2``. This looks like an harmless operation. It is however not so
+harmless and it may be the source of subtle bugs. Consider for
+instance the following example
>>> f1, f2, f3 = [lambda : i for i in (1, 2, 3)]
@@ -129,8 +136,8 @@ In Haskell, where there is no rebinding, the corresponding list
comprehension would return three thunks, the first one returning
``1``, the second ``2``, the third ``3`` [#]_.
-.. [#] To get the same in Python you can recur to the default argument hack, i.e. you can
- rewrite ``f1, f2, f3 = [lambda i=i: i for i in (1, 2, 3)]``.
+.. [#] To get the same in Python you can recur to the default argument hack,
+ i.e. you can rewrite ``f1, f2, f3 = [lambda i=i: i for i in (1, 2, 3)]``.
Finally, let me discuss the side effects issue. To be concrete, consider
the following function with side effects::
@@ -140,9 +147,10 @@ the following function with side effects::
result = x * x
return result
-Each time the function ``square`` is called, you get a log message as side effect.
-Unfortunaly, side effects do not play well with memoization techniques and if you cache
-the result of ``square`` with a suitable decorator::
+Each time the function ``square`` is called, you get a log message as
+side effect. Unfortunaly, side effects do not play well with
+memoization techniques and if you cache the result of ``square`` with
+a suitable decorator::
square = memoize(square)
@@ -195,17 +203,17 @@ and better known. Programmers used to dynamic typing (i.e Pythonistas,
Rubystas, etc) will have less trouble to understand dynamically typed
functional language than statically types ones.
-Still I think it is interesting to look at statically typed languages. After all, I think
-a programmer should have at least a statically typed language in his
-toolbox (C++ and Java do not count ;) Also, I should notice that there are
-often issues of terminology when talking about types. Most people coming
-from the dynamic world will say that their language
-is strongly typed, contrasting it with weakly typed languages such as C
-or Assembly, where characters are the same as short integers, or with
-Perl, where 2+"3" is a valid expression and returns 5. On the other hand,
-people from the static world will say than dynamically typed languages
-are untyped, since you can change the type of a variable. For instance,
-the following is valid Scheme code::
+Still I think it is interesting to look at statically typed
+languages. After all, I think a programmer should have at least a
+statically typed language in his toolbox (C++ and Java do not count ;)
+Also, I should notice that there are often issues of terminology when
+talking about types. Most people coming from the dynamic world will
+say that their language is strongly typed, contrasting it with weakly
+typed languages such as C or Assembly, where characters are the same
+as short integers, or with Perl, where 2+"3" is a valid expression and
+returns 5. On the other hand, people from the static world will say
+than dynamically typed languages are untyped, since you can change the
+type of a variable. For instance, the following is valid Scheme code::
(define a 1)
(set! a "hello")