6
$\begingroup$

When working to teach developers Scheme (which is functional programming) I'll often show them analogous examples in C#. The idea is that by seeing something familiar it will make it easier for the students to understand the unfamiliar. But I'm not sure that this may actually be causing more confusion to the students. Any thoughts or suggestions on the wisdom (or lack thereof) of showing parallel code samples when teaching developers?

By the way, this is what I'm referring to by the phrase "Rosetta Code" in the question title. It's analogous to the idea of the Rosetta Stone presenting the same text in multiple languages.

EDIT

In case it wasn't clear from original question I was thinking of both the aspects of compare and contrast between languages (i. e. this is how we code a loop in C#, this is how we code it in Scheme) and the aspect of relating the unfamiliar (Scheme) by comparing it with the familiar (C#).

$\endgroup$
  • $\begingroup$ There is one true language, and it is mathematics. You cannot even precisely & clearly explain what any of the programs in any of the languages do without giving a rule to translate a program into math. That math of the semantics is the simplest possible way to explain what any program is doing. (The primary notion is of a mapping.) It is only, sadly, because languages & programming are taught [sic] without explicit semantics that reminscent variations in other languages are even sought for clarification. Forget analogies, explain what is actually going on. $\endgroup$ – philipxy Mar 27 '18 at 2:42
  • $\begingroup$ I think you're very much in danger of wandering into the realm of the sesquipedalian. Saying that mathematics is the one true language may be true (if a tad reductive) but it's hardly helpful. By the way I don't think I've ever seen anyone use the adverb sic in reference to his or her own words. $\endgroup$ – Onorio Catenacci Mar 27 '18 at 18:41
  • $\begingroup$ I used relevant technical & everyday terms appropriately. You say you want to "teach" effectively. Then you could google based on my comment. $\endgroup$ – philipxy Mar 28 '18 at 2:27
  • $\begingroup$ If others see this question, this blog post has some relevance. $\endgroup$ – Onorio Catenacci May 23 '18 at 16:15
  • $\begingroup$ @philipxy Very little of programming today is math. Screen aesthetics occupies 50% or more of an application's budget. Even machine learning, which at its core is statistical modeling, has been reduced to "use this library to construct a neural net, and use a particular function from that library to apply the bias function". Sadly, I spend a lot of my time chasing scope errors in the definition of Spring beans. $\endgroup$ – pojo-guy Mar 1 at 4:11
6
$\begingroup$

Here I think the teacher's instinct and experience is the best judgement. You know your own students best. Your worry, of course, is well founded, especially since the two languages are so different.

Learning to think functionally is a big deal and a mind expander. In some ways doing it cold-turkey (with no support) is good to do, since the students need to just thrash about until the see the A-Ha. But that can be very frustrating. It isn't good to leave your students frustrated, of course.

Another reason for not using the technique you suggest is that you don't want their functional code to be just misspelled C#, using ideas from imperative and/or object-oriented thought patterns. Code in one language based on knowledge of another can be truly ugly and the programmer can miss the elegance of the new language.

And functional program can be truly elegant and mind expanding.

To balance the trade-off you can, of course, use "Rosetta Coding" only sparingly. And only when it seems really needed. Perhaps you could start out without it at all and use it only in situations in which the students are struggling, rather than as a main-line technique. You could also use it only when working with individuals (office hours) rather than with the larger group if a student needs to be reminded of the basic structure of an algorithm. Personally, I wouldn't use it as the main structure of the course and am happy to let my students thrash a bit in mildly turbulent waters. But that needs limits also, of course.

Salt is fine, but don't over-salt. Judgment and a bit of restraint, perhaps.


Since the two languages are from different paradigms the difference in resulting code can be quite stark. For example, reversing a list in linear time in Scheme is quite a lot different than you would likely program it in C# with mutable data. But even Java and Ruby, closely aligned, are not the same language and have different thought patterns. It is the thought patterns that are the most important lessons of the various paradigms.

$\endgroup$
  • $\begingroup$ Glad to see you follow what I'm asking @Buffy. I was beginning to despair of anyone understanding exactly how different FP is from the imperative OO, C Family languages that dominate these days. $\endgroup$ – Onorio Catenacci Mar 19 '18 at 13:36
  • $\begingroup$ With static methods, the linq namespace, and lambda expression support, you can go pretty far with c# to show FP principles, at least through applicative FP concepts. These might be segways into teaching more lisp-y ideas in their current language proficiency before introducing the ideas in scheme. $\endgroup$ – Jed Schneider Mar 22 '18 at 0:48
2
$\begingroup$

A Rosetta Stone is a temping way of thinking about the issue, and it works if the person knows two languages already (the way that we knew two of the languages on the Rosetta Stone and were trying to learn the third one). This is similar to how if you have two points of reference on a map, you can triangulate to locate a third.

But those first two languages are going to be holy hell to learn. That is because no Rosetta Stone exists if you haven't learned one language, let alone two. Fortunately, we learn to speak when we are babies, everything is irritating anyway, and we forget the whole thing! If only we started to program when we were 2. Maybe future generations will...

I started off sitting in front of a terminal hooked to a PDP-11, using either a shell script language or Basic, I forget which. When I could, I used one of the Apple ][s with Basic, until I got one myself in high school. I learned a smattering of Assembly then also. My first college course was in APL. From the standpoint of Basic and Assembly, this is Hieroglyphics indeed. Next we learned Lisp. It was all Greek to me for a while, some students never mastered it and washed out. None of these languages had anything in common, any more than Cuneiform, Linear-B and Hieroglyphics do, beyond the idea that: "we want the computer to do something."

That is not much to go on. Really, the only analogy shared by all forms of computing is: "we want the computer to do something." And people are just so creative in coming up with ever-more varied ways of forming such utterances. (Perhaps we should try standardizing a bit instead?) (Shh! You'll ruin the story)

All I can say is, keep throwing stuff at them, and if they can stay afloat, they might decide to make a living at it.

$\endgroup$
  • $\begingroup$ Well in my case in particular I'm teaching professional developers who already know C#; I'm attempting to teach them Scheme. So it's not quite as dire as trying to teach people who've never coded two languages at the same time. :) $\endgroup$ – Onorio Catenacci Mar 20 '18 at 14:15
  • $\begingroup$ @OnorioCatenacci, if they're already familiar with .Net, maybe you should teach them F# before Scheme? $\endgroup$ – Peter Taylor Mar 22 '18 at 8:27
2
$\begingroup$

Using C# (or some other OOP or procedural language) as example for the inherently recursion-based Scheme is harmful. You need to (re)learn how to program to grok Scheme, different languages are just a distraction.

Never forget the saying of "FORTRAN with semicolons" for much of the Pascal written in the beginning. Yes, contrasting different solutions in languages from varying paradigms is enlightening... if you know the relevant languages/paradigms beforehand.

$\endgroup$
  • $\begingroup$ Teaching Scheme from first principles to developers that already know C# will require them to unlearn quite a bit regardless. I'm not sure that showing them the C# version is that harmful--especially if one sticks to very isolated code fragments of C# $\endgroup$ – Onorio Catenacci May 18 '18 at 17:43
2
$\begingroup$

I swiped a Scheme example from a tutorial and created my own translation to a C# Console program. I tried to preserve the structure, naming and comments. The difference in length is mostly due to the placement of curly braces on separate lines vs the parens on same lines.

We could criticize the C# code by saying that it has to be sprinkled liberally with 'static' and 'decimal', but then would have to explain how much is missing from the Scheme example: The Lisp Interpreter (the entire concept of an interpreter...) and the built-in handling of numeric types therein.

Scheme

(define checkbook (lambda ()

; This check book balancing program was written to illustrate
; i/o in Scheme. It uses the purely functional part of Scheme.

        ; These definitions are local to checkbook
        (letrec

            ; These strings are used as prompts

           ((IB "Enter initial balance: ")
            (AT "Enter transaction (- for withdrawal): ")
            (FB "Your final balance is: ")

            ; This function displays a prompt then returns
            ; a value read.

            (prompt-read (lambda (Prompt)

                  (display Prompt)
                  (read)))

            ; This function recursively computes the new
            ; balance given an initial balance init and
            ; a new value t.  Termination occurs when the
            ; new value is 0.

            (newbal (lambda (Init t)
                  (if (= t 0)
                      (list FB Init)
                      (transaction (+ Init t)))))

            ; This function prompts for and reads the next
            ; transaction and passes the information to newbal

            (transaction (lambda (Init)
                      (newbal Init (prompt-read AT)))))

; This is the body of checkbook;  it prompts for the
; starting balance

  (transaction (prompt-read IB)))))

C# Console

using static System.Console;

// This check book balancing program was written to illustrate
// a Scheme example translated as closely as possible to C# Console
namespace CheckBookFromSchemeExample
{
    // These definitions are local to checkbook
    class Program
    {
        // These strings are used as prompts

        static string IB = "Enter initial balance: ";
        static string AT = "Enter transaction (- for withdrawal): ";
        static string FB = "Your final balance is: ";

        //this function displays a prompt then returns
        // a value read.

        static decimal prompt_read(string Prompt)
        {
            decimal result;
            WriteLine(Prompt);
            decimal.TryParse(ReadLine(), out result);
            return result;
        }

        //This function recursively computes the new
        // balance given an initial balance init and
        // a new value t. Termination occurs when the
        // new value is 0.

        static decimal newbal(decimal Init, decimal t)
        {
            if (t == 0)
            {
                WriteLine(FB + Init.ToString("c"));
                return (Init);
            }
            else
            {
                decimal result = Init + t;
                WriteLine(result.ToString("c"));
                return transaction(result);
            }
        }

        // This function prompts for and reads the next
        // transaction and passes the information to newbal
        static decimal transaction(decimal Init)
        {
            return newbal(Init, prompt_read(AT));
        }

        // This is the body of the checkbook; it prompts for the
        // starting balance

        static void Main(string[] args)
        {
            transaction(prompt_read(IB));
            ReadLine();
        }
    }
}

The translation to APL is left as an exercise for the reader. (no one expects them to do that!) (precisely)

$\endgroup$
  • $\begingroup$ Welcome to CSEducators and thanks for your post. I think that illustrating by starting with a Scheme program and showing it in some other language is probably the best path for this sort of thing, rather than the opposite. That way the new language has cleaner code and if the translation is "messy" it can illustrate the power of the new paradigm. Showing messy Scheme would be counterproductive. $\endgroup$ – Buffy Mar 20 '18 at 19:34
-3
$\begingroup$

philipxy's comment is correct. There is one true language: mathematics. Just explain what you are doing to your students, without using any computer language. If it's confusing them in one language, why double the confusion, rather than eliminate it altogether?

Except for maybe a small example here or there, the answer is No, you should not be venturing into procedural programming (I assume that's what you mean when you say C#) when teaching a functional programming class.

There are only two programming paradigms: functional and procedural. (And no, OO is not one of them.)

The purpose of teaching functional programming is to teach students to think in terms of building a circuit, that is, a black box function of other black box functions, without state (otherwise known as global variables), and also to teach complex recursion (again without state).

The idea of eliminating state is to teach students that a computer program is nothing more than just one big function, and that's it.

$\endgroup$
  • $\begingroup$ Your definition of "programming paradigm" is not commonly accepted. Please see programming paradigms. Many of them are inter-compatible, including both OOP with functional programming and OOP with procedural programming. $\endgroup$ – Ben I. Feb 27 at 1:23
  • $\begingroup$ I think the customary duality is functional/imperative--not functional/procedural. I also think you've possibly misapprehended a few other concepts as well. State is not "otherwise known as global variables"--at least not for any definition of state I've ever seen. $\endgroup$ – Onorio Catenacci Feb 27 at 21:19
  • $\begingroup$ Comments may only be edited for five minutes? What in the world? Little dictators. The people who run this site have never changed their mind or made an edit after five minutes? This site is weird. $\endgroup$ – Johnny Mar 2 at 14:04
  • $\begingroup$ State is most definitely another way of saying global variables. Maybe functional vs imperative is a better way of saying functional vs procedural, but the purpose of teaching functional is still about lack of state, as I clearly stated in my post. Being that OO is not a real concept for any practical (nor even theoretical) purposes, I have no response for anyone who uses OO. It is becoming increasingly clear to me that the state of CS education is in a quagmire, and the people here seem to have some very funny ideas about CS, Math, and Logic. $\endgroup$ – Johnny Mar 2 at 14:06

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.