Apologies for the munged formatting of my original message. Here it is with leading dots to preserve the indent. To: edu-sig@python.org Subject: CTL: Computer Thinking Language There is an interesting article in the latest ACM {Human Computing Skills: Rethinking the K-12 Experience, Fletcher & Lu, Communications of the ACM, Feb.09, p.23}. The authors make a strong case for re-vamping our curricula: . despite our best efforts to articulate that CS is more than just programming ... . computational thinking (CT) as a skill on a par with reading, writing and arithmetic ... places the core of CS, we believe . correctly, in the category of basic knowledge. . proficiency in computational thinking helps us systematically and efficiently process information and tasks. . lay the foundations of CT long before students experience their first programming language. . Programming is to CS what proof construction is to mathematics, and what literary analysis is to English. Then they move to more more controversial statements: . Knowledge of programming should not be necessary to proclaim literacy in basic computer science. . Substantial preparation in computational thinking is required before students enroll in programming courses. and a specific proposal: . a computational thinking language (CTL) that captures core CT concepts must permeate the pedagogy. . not a programming language, but rather vocabularies and symbols that can be used to annotate and describe computation, . abstraction, and information and provide notation around which semantic understanding of computational processes can be hung. They give as an example, a description of Euclid's algorithm for finding the greatest common divisor. They suggest a syntax, which I transcribe here using <lamba> as the Greek lower-case lambda: . <lambda> a,b. if a<b,(a, b-a); else (a-b, b) At this point, they really lost me. Why would anyone go to this much effort to avoid programming language. Python's equivalent statement is just as simple (although a bit odd in its ordering): . lambda a,b: (a, b-a) if (a<b) else (a-b, b) Have these guys never heard of Python? I think the problem may be a need to avoid favoring one language over another. Any time you make a proposal to use a specific language, you get immediate opposition from folks who favor another language. In my department (Java & C++), and at our community college (Java, BASIC, Alice), I seem to have been labeled as the "Python guy", pushing "yet another language", or even worse, the guy who wants to get rid of type declarations. Python is seen as a "scripting language", something equivalent to csh or bash. To avoid being pigeonholed, I now just say "we need a more agile language". I can see the need for a CTL, and I wouldn't object to it being something other than Python, and I'm all in favor of being "fair" to the other languages. The one requirement I would insist on is that the language "compute", i.e. no ambiguity as to a result (no psuedocode). It would also be nice if CTL could be automatically translated to a real computer language, so there is a smooth transition when students are ready for the real thing. Students could test their CTL by popping it into the translator, running it in a real interpreter, and getting immediate feedback. CTL should certainly include simple functions like min(), max(), sum(), and sqrt(). It could also include functions like range(a,b), introducing the idea that functions can return something besides numbers. At this point there may be some controversy over how to treat the endpoints, but that could be worked out in compromise between the different languages. Moving on to week three of the lesson plan, we could introduce the idea of defining our own functions, adding new concepts one at a time. f(a,b): (a+b)/2 # a simple function f(a,b): (a+b)/(2*pi) # with an "outside" variable f(a,b): if a<b,(a, b-a); else (a-b, b) # adding some conditional logic f(a,b): a2 = a**2; b2 = b**2; return (a2 + b2)/2 # temporary variables and a statement sequence # control flow with multiple statements f(a,b): if a<(b-5), return a; if (b-5)<=a<=(b+5), return (a+b)/2; return b # recursion f(a,b): if a<b, f(a, b-a); elif b<a, f(a-b, b); else (a,b) This is a bit Pythonic, but only because I'm more familiar with Python than Ruby or Lua, or some other language that might like to contribute some gems. We could even invite Java, if she will come down to this level. :>) What else do we need in CTL? Would anyone like to join me in defining this new "language"? I'll write the translator to Python. -- Dave ************************************************************ * * David MacQuigg, PhD email: macquigg at ece.arizona.edu * * * Research Associate phone: USA 520-721-4583 * * * * ECE Department, University of Arizona * * * * 9320 East Mikelyn Lane * * * * http://purl.net/macquigg Tucson, Arizona 85710 * ************************************************************ *
Before I discovered Python a couple of years ago I was experimenting with a pseudo-code approach for expressing math concepts. I had this kind of stuff in mind: factorial(n): if n < 2 ---> 1 else ---> n*factorial(n-1) No particular official syntactical rules here, just an attempt to organize ideas. Imagine my delight when I first saw Python! I started laughing. I think some kind of a CTL approach would be especially good for a math curriculum. Maybe instead of 'Computer' TL, call it 'Computational' TL. It's what algebra should be these days. And if your CTL also RUNS, well, so much the better. Most students, and probably most people, would read "2 + 2" as "2 plus 2", but notice how much more mathematically and computationally effective it would be if they could develop the habit of reading or thinking of "2 + 2" as "the sum of 2 and 2" or "sum(2, 2)". Think of the whole, the resulting value. And how about "2 + 3 * 4"? Again, the typical reading would be "2 plus 3 times 4", and that's ambiguous, and so in math classes we have to talk about 'order of operations', and usually the only justification we give for 'order of operations' is that we have to have some kind of social agreements in place in order to avoid confusion. Right? However, it is again more mathematically effective to read "2 + 3 * 4" as "the sum of 2 and the product of 3 and 4", or, sum(2, product(3, 4)). No ambiguity there! And this is how you have to think when you hook chains of functions together. This kind of stuff could be done very early in the curriculum. Doesn't have to wait for either advanced math classes or computer science. Math teachers often forget, or are unaware, that the ordinary arithmetic operators are themselves functions. I think it would be good for math classes to explore this kind of functional composition for very simple ideas. By the way, we started studying sequences today in class. What's a really good Pythonic tool for studying sequences ---> generators! - Michel On Mon, Mar 2, 2009 at 9:01 AM, David MacQuigg <macquigg@ece.arizona.edu>wrote:
Apologies for the munged formatting of my original message. Here it is with leading dots to preserve the indent.
To: edu-sig@python.org Subject: CTL: Computer Thinking Language
There is an interesting article in the latest ACM {Human Computing Skills: Rethinking the K-12 Experience, Fletcher & Lu, Communications of the ACM, Feb.09, p.23}.
The authors make a strong case for re-vamping our curricula:
. despite our best efforts to articulate that CS is more than just programming ... . computational thinking (CT) as a skill on a par with reading, writing and arithmetic ... places the core of CS, we believe . correctly, in the category of basic knowledge. . proficiency in computational thinking helps us systematically and efficiently process information and tasks. . lay the foundations of CT long before students experience their first programming language. . Programming is to CS what proof construction is to mathematics, and what literary analysis is to English.
Then they move to more more controversial statements:
. Knowledge of programming should not be necessary to proclaim literacy in basic computer science. . Substantial preparation in computational thinking is required before students enroll in programming courses.
and a specific proposal:
. a computational thinking language (CTL) that captures core CT concepts must permeate the pedagogy. . not a programming language, but rather vocabularies and symbols that can be used to annotate and describe computation, . abstraction, and information and provide notation around which semantic understanding of computational processes can be hung.
They give as an example, a description of Euclid's algorithm for finding the greatest common divisor. They suggest a syntax, which I transcribe here using <lamba> as the Greek lower-case lambda:
. <lambda> a,b. if a<b,(a, b-a); else (a-b, b)
At this point, they really lost me. Why would anyone go to this much effort to avoid programming language. Python's equivalent statement is just as simple (although a bit odd in its ordering):
. lambda a,b: (a, b-a) if (a<b) else (a-b, b)
Have these guys never heard of Python?
I think the problem may be a need to avoid favoring one language over another. Any time you make a proposal to use a specific language, you get immediate opposition from folks who favor another language. In my department (Java & C++), and at our community college (Java, BASIC, Alice), I seem to have been labeled as the "Python guy", pushing "yet another language", or even worse, the guy who wants to get rid of type declarations. Python is seen as a "scripting language", something equivalent to csh or bash. To avoid being pigeonholed, I now just say "we need a more agile language".
I can see the need for a CTL, and I wouldn't object to it being something other than Python, and I'm all in favor of being "fair" to the other languages. The one requirement I would insist on is that the language "compute", i.e. no ambiguity as to a result (no psuedocode). It would also be nice if CTL could be automatically translated to a real computer language, so there is a smooth transition when students are ready for the real thing. Students could test their CTL by popping it into the translator, running it in a real interpreter, and getting immediate feedback.
CTL should certainly include simple functions like min(), max(), sum(), and sqrt(). It could also include functions like range(a,b), introducing the idea that functions can return something besides numbers. At this point there may be some controversy over how to treat the endpoints, but that could be worked out in compromise between the different languages.
Moving on to week three of the lesson plan, we could introduce the idea of defining our own functions, adding new concepts one at a time.
f(a,b): (a+b)/2 # a simple function f(a,b): (a+b)/(2*pi) # with an "outside" variable f(a,b): if a<b,(a, b-a); else (a-b, b) # adding some conditional logic f(a,b): a2 = a**2; b2 = b**2; return (a2 + b2)/2 # temporary variables and a statement sequence
# control flow with multiple statements f(a,b): if a<(b-5), return a; if (b-5)<=a<=(b+5), return (a+b)/2; return b
# recursion f(a,b): if a<b, f(a, b-a); elif b<a, f(a-b, b); else (a,b)
This is a bit Pythonic, but only because I'm more familiar with Python than Ruby or Lua, or some other language that might like to contribute some gems. We could even invite Java, if she will come down to this level. :>)
What else do we need in CTL? Would anyone like to join me in defining this new "language"? I'll write the translator to Python.
-- Dave ************************************************************ * * David MacQuigg, PhD email: macquigg at ece.arizona.edu * * * Research Associate phone: USA 520-721-4583 * * * * ECE Department, University of Arizona * * * * 9320 East Mikelyn Lane * * * * http://purl.net/macquigg Tucson, Arizona 85710 * ************************************************************ *
_______________________________________________ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
As a current college student myself, I feel like chiming in here. 2009/3/2 michel paul <mpaul213@gmail.com>:
However, it is again more mathematically effective to read "2 + 3 * 4" as "the sum of 2 and the product of 3 and 4", or, sum(2, product(3, 4)). No ambiguity there! And this is how you have to think when you hook chains of functions together. This kind of stuff could be done very early in the curriculum. Doesn't have to wait for either advanced math classes or computer science.
Perhaps it may be appropriate to try and introduce prefix notation to students, such as what lisp uses. So instead of "2 + 3 * 4" or sum(2, product(3, 4)) it would be (+ 2 (* 3 4)). Unfortunately, that might make their eyes glaze over, but you could state how it is unambiguous and maybe formalize infix notation for them.
Math teachers often forget, or are unaware, that the ordinary arithmetic operators are themselves functions. I think it would be good for math classes to explore this kind of functional composition for very simple ideas.
Personally I found that being able to think about many math concepts as functions helped me a great deal with managing the complexity of many math courses. Just my 2 cents. -Jason
On Mon, Mar 2, 2009 at 1:41 PM, Jason Axelson <bostonvaulter@gmail.com> wrote:
As a current college student myself, I feel like chiming in here.
2009/3/2 michel paul <mpaul213@gmail.com>:
However, it is again more mathematically effective to read "2 + 3 * 4" as "the sum of 2 and the product of 3 and 4", or, sum(2, product(3, 4)). No ambiguity there! And this is how you have to think when you hook chains of functions together. This kind of stuff could be done very early in the curriculum. Doesn't have to wait for either advanced math classes or computer science.
The mental model in Python is 2, 3 and 4 each "know their stuff" when it comes to doing these operations, have them internalized ("in their bones"). In that sense, translating 2 + 3 to sum(2, 3) is less useful that using native Pythonic 2.__add__(3) with __add__ being a verb like "eat" (ingest). "2 eats 3, returns 5 object" is a better image that "sum eats a 3 and 2 objects, returns 5 object". Of course if you're bridging to Scheme, then maybe that's another matter. OO isn't going to be so important, your mental models will be different. However, in the Python head space, we don't so much like the idea of "operations" just floating as globals, unencapsulated, outside of any number objects. That's the old paradigm, kind of gets in the way. And yes, I know it's still quite possible to code and think in that way with Python, a forgiving environment. But in terms of helping students master OO, we want the idea of methods *internal* to the class definition. sum(2, product(3, 4)) means 2.__add__ ( 3.__mul__(4) ) -- like fish eating fish: http://www.efuse.com/Plan/fish-eat-fish-richard-cook-artville-com.jpg ( integers = fish )
Perhaps it may be appropriate to try and introduce prefix notation to students, such as what lisp uses. So instead of "2 + 3 * 4" or sum(2, product(3, 4)) it would be (+ 2 (* 3 4)). Unfortunately, that might make their eyes glaze over, but you could state how it is unambiguous and maybe formalize infix notation for them.
Math teachers often forget, or are unaware, that the ordinary arithmetic operators are themselves functions. I think it would be good for math classes to explore this kind of functional composition for very simple ideas.
There's not just one overarching model in my model. Different languages and notations, all with a claim to being mathematical, will come with different gestalts, core abstractions. This is what math teachers often forget: that there's no "one thing" that is "a mathematics". Wittgenstein's notion of "family resemblance" enters at this juncture, helps break the spell of "an essence" (so tempting, so wrong).
Personally I found that being able to think about many math concepts as functions helped me a great deal with managing the complexity of many math courses. Just my 2 cents.
-Jason
Finding a model helpful is a good recommendation for sharing it with others and I wouldn't want to get in your way of doing that. On the other hand, if Python is what we're learning, then looking at 2 + 3 as a way of firing the add method inside of an integer, is what we'd like to focus on in many cases. However, we're not so far apart, as functions are very akin to methods and static methods are really quite indistinguishable, not even needing a self.
From Oregon Curriculum Network (OCN): http://www.flickr.com/photos/17157315@N00/3308514585/sizes/o/
Kirby
On Mon, Mar 2, 2009 at 2:20 PM, kirby urner <kirby.urner@gmail.com> wrote: On Mon, Mar 2, 2009 at 2:20 PM, kirby urner <kirby.urner@gmail.com> wrote:
This is what math teachers often forget: that there's no "one thing" that is "a mathematics".
Yeah, this is what I appreciate about the Pythonic way of thinking. There are other schools of thought where mathematics is put into a box and anything outside of that box is ridiculed. I prefer an open world. - Michel On Mon, Mar 2, 2009 at 2:20 PM, kirby urner <kirby.urner@gmail.com> wrote:
On Mon, Mar 2, 2009 at 1:41 PM, Jason Axelson <bostonvaulter@gmail.com> wrote:
As a current college student myself, I feel like chiming in here.
2009/3/2 michel paul <mpaul213@gmail.com>:
However, it is again more mathematically effective to read "2 + 3 * 4" as "the sum of 2 and the product of 3 and 4", or, sum(2, product(3, 4)). No ambiguity there! And this is how you have to think when you hook chains of functions together. This kind of stuff could be done very early in the curriculum. Doesn't have to wait for either advanced math classes or computer science.
The mental model in Python is 2, 3 and 4 each "know their stuff" when it comes to doing these operations, have them internalized ("in their bones").
In that sense, translating 2 + 3 to sum(2, 3) is less useful that using native Pythonic 2.__add__(3) with __add__ being a verb like "eat" (ingest). "2 eats 3, returns 5 object" is a better image that "sum eats a 3 and 2 objects, returns 5 object".
Of course if you're bridging to Scheme, then maybe that's another matter. OO isn't going to be so important, your mental models will be different.
However, in the Python head space, we don't so much like the idea of "operations" just floating as globals, unencapsulated, outside of any number objects. That's the old paradigm, kind of gets in the way.
And yes, I know it's still quite possible to code and think in that way with Python, a forgiving environment. But in terms of helping students master OO, we want the idea of methods *internal* to the class definition.
sum(2, product(3, 4)) means 2.__add__ ( 3.__mul__(4) ) -- like fish eating fish:
http://www.efuse.com/Plan/fish-eat-fish-richard-cook-artville-com.jpg ( integers = fish )
Perhaps it may be appropriate to try and introduce prefix notation to students, such as what lisp uses. So instead of "2 + 3 * 4" or sum(2, product(3, 4)) it would be (+ 2 (* 3 4)). Unfortunately, that might make their eyes glaze over, but you could state how it is unambiguous and maybe formalize infix notation for them.
Math teachers often forget, or are unaware, that the ordinary arithmetic operators are themselves functions. I think it would be good for math classes to explore this kind of functional composition for very simple ideas.
There's not just one overarching model in my model. Different languages and notations, all with a claim to being mathematical, will come with different gestalts, core abstractions.
This is what math teachers often forget: that there's no "one thing" that is "a mathematics".
Wittgenstein's notion of "family resemblance" enters at this juncture, helps break the spell of "an essence" (so tempting, so wrong).
Personally I found that being able to think about many math concepts as functions helped me a great deal with managing the complexity of many math courses. Just my 2 cents.
-Jason
Finding a model helpful is a good recommendation for sharing it with others and I wouldn't want to get in your way of doing that.
On the other hand, if Python is what we're learning, then looking at 2 + 3 as a way of firing the add method inside of an integer, is what we'd like to focus on in many cases.
However, we're not so far apart, as functions are very akin to methods and static methods are really quite indistinguishable, not even needing a self.
From Oregon Curriculum Network (OCN): http://www.flickr.com/photos/17157315@N00/3308514585/sizes/o/
Kirby
Having come from APL, later Logo, I'm used to interactive REPL (direct interaction with an interpreter), gradually building up a "namespace" i.e. as you define turtle-drawing functions, these get remembered. You save to disk for persistence, but the primary experience is of being in a "session" and having a "workbench" of tools you've defined (more like in bash -- not afraid to compare Linux shell with Python shell). Tim Peters reminded me of ISETL awhile back, another attempt to harness an interpreter for math learning. There's a proud history here, ongoing of course. Where I think the idea of "a program" misleads is it may get you thinking about a full blown application, menu driven or GUI, where everything is tied together in some main loop, lots of infrastructure in that case. In that sense, very few .py files in Standard Library are "programs", probably why we refer to them as "modules" instead. We might say one "authors" or "writes" a module; I'm not sure the verb "to program" deserves such a central position here. We're writing and saving algorithms for our math library, making use of stuff we've proved on the white board, or accepted as proven from reliable sources (or maybe we're experimenting with conjectures, who's to say...). Python starts us in "calculator mode" (or can, if you've got IDLE set up right), and that's all REPL (read, evaluate, print, loop), all session-based thinking. Modules are more like "frozen sessions" i.e. all those classes and functions you defined (all objects) are now ready for reuse, for importing ("thawing") in other modules etc. But there's no implication of some "glue" holding all the classes and functions together, besides the running interpreter itself. When you import a module, it's like typing it really fast into your current session, giving your interpreter (our snake) more stuff for its memory. We can talk about pickling and marshalling too. Go ahead an say "persistence layer" why not? But the older idea of "library" is probably what most will hook onto. For example, one of the first namespaces we'd import in math class would be... (drum roll, suspense), the math module. But 'import math' gets you a grab bag, a fish tank, an aquarium, a zoo, a namespace... all these images are way better and more accurate the "program". What you get is a bunch of balloons (objects on strings), and when you go a = b, you're assigning another string to the same balloon. At least in Python that's the model, not saying all languages share the same model, which is why you shouldn't teach a language without also teaching its core concepts. Let's not pretend there's some pie in the sky generic model and write pseudo-code for it, or we'll just end up with yet another language with the disadvantage of not running (call it CTL for short -- always just around the corner, at the end of the rainbow, nothing at hand is ever quite good enough because...). Anyway, we all know Python is "good enough" and in that mental model, a module is like a "bunch of balloons" (good flying circus imagery, maybe a clown holding the strings). Another bias the "programmers" bring to our math class, which we don't necessarily share, is this tendency to use raw_input or input to "prompt" for data, e.g. "Please enter today's date: _ ". The psychology here is inherited from "programming for a user" i.e. I'm the behind the scenes puppet master programmer, and who I'm writing for is someone out there in the audience who doesn't get to see backstage. There's this dichotomy between "end user" and "coder" that's very strong, such that "programming" is a kind of "performance art", with CS the "back stage science". In contrast, since FOSS and the invention of interpreter-based math curricula (on .NET/Mono, on C, using whatever REPL or language, maybe Scheme **), we're happy to swap code around, share, but we're all back stage coders, are peers in the sense of knowing how to create modules. There's no "clueless audience" that "doesn't know FORTRAN". This is math class, and we all know how to write math notation (including the executable kind, which we prefer -- marketing: "ours runs, theirs walks or just sits there"). We simply assume the source code is available, along with a test suite, so go ahead in check out the documentation and go crazy, import our resources and mix 'em in with your own. That's the liberal arts culture. But raw_input? That's a throwback to the days of BASIC, gimme a break! Kirby ** please feel free to refer to Python's lambda as 'little lambda' (as in 'Mary had a...'), and suggest to your department that one reason Python is such a good entry point is that it has the seeds of these other languages, e.g. in the LISP/Scheme family, lambda is all grown up, is something huge, and people worship it, name their calculus after it etc.
participants (4)
-
David MacQuigg -
Jason Axelson -
kirby urner -
michel paul