[13933] in Perl-Users-Digest
Perl-Users Digest, Issue: 1343 Volume: 9
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Wed Nov 10 18:10:50 1999
Date: Wed, 10 Nov 1999 15:10:21 -0800 (PST)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Message-Id: <942275421-v9-i1343@ruby.oce.orst.edu>
Content-Type: text
Perl-Users Digest Wed, 10 Nov 1999 Volume: 9 Number: 1343
Today's topics:
Re: Perl and commonsense part 2 <lr@hpl.hp.com>
Re: Perl and commonsense part 2 <aqumsieh@matrox.com>
Re: Perl and commonsense part 2 (David H. Adler)
Re: perl as first language? (Kragen Sitaker)
Re: perl as first language? (Kragen Sitaker)
Re: perl as first language? <cassell@mail.cor.epa.gov>
Re: Perl Extensions. Arrgh. (Kragen Sitaker)
Digest Administrivia (Last modified: 16 Sep 99) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: Wed, 10 Nov 1999 12:34:00 -0800
From: Larry Rosler <lr@hpl.hp.com>
Subject: Re: Perl and commonsense part 2
Message-Id: <MPG.129376938c263cd798a1ce@nntp.hpl.hp.com>
In article <80bur7$s5n$1@nnrp1.deja.com> on Wed, 10 Nov 1999 14:18:19
GMT, ajmayo@my-deja.com <ajmayo@my-deja.com> says...
<SNIP> of philosophical discussion, left to others to pursue. :-)
+ I close with a small piece of code that I wrote yesterday. Flame me if
+ you please; I think I am starting to 'grok' perl and that this code
+ respects the spirit of perl many of you felt so strongly about.
Criticism of code here shouldn't be construed as flaming, if it is
produced constructively.
In this case, the most notable criticism is the absence of 'use strict;'
and, presumably, '-w'.
+ The problem is to flatten a hash of hashes - i.e stringify or 'smoosh'
+ it (I particularly like the term 'smoosh', coined by another
+ contributor, as it has a nice flavour of flattening something with
+ structure, whereas stringify possibly doesn't). Of course technically
+ we are serialising the data stream, I suppose.
+
+ The reason I needed to flatten this hash and then reconstitute it was
+ that Apache::ASP session variables don't like to store hash references
+ for reasons I am too naive to fully comprehend yet. They are tied
+ variables; I know what that means, but apparently it is obvious (to
+ perl gurus) because of this fact that they can't. Be it as it may,
+ they can't, so in order to store a complex data structure in one, it
+ needs to be smooshed and then unsmooshed when it is retrieved.
+
+ As with my gripes above "can't" in this context means - will be
+ silently accepted if you try it but won't work.
But the code you show converts a hash of hash (referenc)es to an array
of array (reference)s. Why should this be any more acceptable?
Later, I'll show code that produces an array of scalar values, which
might work better.
+ Anyway, here 'tis. I know its a wheel that has undoubtedly been
+ invented before. The question is; have I done this elegantly or do I
+ still not grok perl?.
Not elegantly (see below); but 'grok' is so subjective.
+ #The problem. Freeze-dry a hash of hashes into a set of simple
+ #strings, and then reconstitute the original hash
+
+ #First, create a hash of two anonymous hashes for demonstration
+ #purposes
+
+ $a{'item1'}={'k1','v1','k2','v2'};
+ $a{'item2'}={'k3','v3','k4','v4'};
Same thing; less punctuation, more 'air':
$a{item1} = { qw( k1 v1 k2 v2 ) };
$a{item2} = { qw( k3 v3 k4 v4 ) };
+ #iterate over the outer hash keys
+
+ for $i (keys %a)
+ {
+
+ #and smoosh the hash into an array of key,value strings
+
+ @c=%{$a{$i}};
+
+ #append this to @s, which will be an array of anonymous arrays
+ #We include the outer hash key as the first element of the array
+
+ push @s,[$i,@c];
+
+ }
You demonstrate below that you are aware that you can roll a list
directly into a hash. Just so, you can unroll a hash directly into a
list. So your entire loop above reduces simply to:
@s = map [ $_, %{$a{$_}} ] => keys %a;
+ #@s can now be safely stored in a session variable.....
+
+ #now, to reconstitute our freeze-dried hash of hashes from @s
+
+ #iterate over the array of arrays, @s, retrieving each individual
array
+
+ for $j (@s)
+ {
+ # smoosh the individual anonymous array into an array, which
+ # will contain the individual key, value pairs for the hash
+
+ @z=@{$j};
+
+ #next, make a new hash of hashes, %h, from the array, using a
+ slice.
+
+ $h{$z[0]}={@z[1..(scalar @z-1)]};
+ }
And that loop can be written simply as:
$h{$_->[0]} = { @$_[1 .. $#$_] } for @s;
+ #finally, print the reconstituted hash to prove that it worked
+
+ print $h{'item1'}{'k1'},"\n";
+ print $h{'item2'}{'k3'},"\n";
There's lots of extra punctuation above, too.
So here's the above code, as a complete program, strictified and
uncommented:
#!/usr/local/bin/perl -w
use strict;
my %a;
$a{item1} = { qw( k1 v1 k2 v2 ) };
$a{item2} = { qw( k3 v3 k4 v4 ) };
my @s = map [ $_, %{$a{$_}} ] => keys %a;
my %h;
$h{$_->[0]} = { @$_[1 .. $#$_] } for @s;
print "$h{item1}{k1}\n";
print "$h{item2}{k3}\n";
Now, to deal with the problem I stated before: @s is an array of
references, which would be useless when retrieved. Let's make it into
an array of values.
my @s = map { $_, 2 * keys %{$a{$_}}, %{$a{$_}} } keys %a;
my %h;
while (@s) {
my $key = shift @s;
my $count = shift @s;
$h{$key} = { splice @s, 0, $count };
}
Having said all this, I now suggest you take a look at the already-
invented wheel that you mentioned before: some modules which I have
never used but which seem appropriate for this task, Data::Dumper and
Storable.
--
(Just Another Larry) Rosler
Hewlett-Packard Laboratories
http://www.hpl.hp.com/personal/Larry_Rosler/
lr@hpl.hp.com
------------------------------
Date: Wed, 10 Nov 1999 14:23:48 -0500
From: Ala Qumsieh <aqumsieh@matrox.com>
Subject: Re: Perl and commonsense part 2
Message-Id: <x3yaeomywu4.fsf@tigre.matrox.com>
ajmayo@my-deja.com writes:
> $a=\(1,2,3);
>
> If they are not, and many people would disagree with me that they
> should be - fair enough - then the least one might expect is a warning
> that what you have done is either not permissible or not likely to
> produce the expected results. Since I cannot for the life of me imagine
> why anyone would deliberately do what I just did above for the sake of
> getting a scalar reference to the number 3, I think perl should warn
> about these sorts of things.
If I understand you correctly, you want Perl to warn about anything
you do where the actual results will be different from what you would
expect? Does this sound reasonable to you?
Some people might disagree, but perl (the interpreter) is only a
program. People talk all the time about the PSI::ESP module, but it's
results aren't guaranteed (for now at least :)
If Perl knew what you were expecting, then why would it generate a
different result? Perl has a history with DWIM (Do What I Mean)
approaches, and most (if not all) of its shortcuts are geared towards
that.
But, using your logic, a snippet like:
my $x = 1;
my $y = 2;
my $z = $x + $x;
should give a warning of the sort:
"Attempt to add wrong variable (x) to variable (x) - should be 'y'"
So Perl should know beforehand what you are trying to do. Seems to me
like the chicken and egg problem.
I am not trying to make fun of you, or flame you or anything. I also
believe in good warning messages. But you have to know where to draw
the line.
And please do correct me if I'm wrong.
> This is the same reasoning behind Unix
> variants such as Linux, for which the cp and rm utilities default to
> warning you about the potential disasters that may befall you -
> contrary to 'pure' Unixes, where these utilities simple remove files
> without a warning or overwrite files silently. In Linux you must
> specify a flag for this behaviour - this is very sensible, since you
> can still have the silent behaviour when you want it.
But programs like 'rm' have one specific job to do. I can't believe
you are actually making such a comparison. 'rm' can safely
assume that you are trying to delete files! It knows what you
expect. I hope you know that Perl is not that simple.
> Pushing one hash onto another also seems logical, to me. It is surely
> consistent with the polymorphism of object-oriented programming and
> operator overloading (function overloading, I guess, in this case). I
> accept that push doesn't do this; I don't accept that it shouldn't.
Interesting idea. If we define a function by the type of input it
takes, then we'll end up with two functions called 'push'. In object
oriented terms, that would be called 'overloading'.
But it's not that obvious how to push() one hash onto another.
> Having said all this, I *am* going to continue with perl. I *am* going
> to recommend further development in perl. I am doing this because,
> despite the issues I have encountered, I believe perl is rock-solid,
> has excellent technical support, a growing base of programmers,
> documentation and infrastructure, and must be the optimal platform-
> neutral scripting language choice. These considerations outweigh any
> scruples I might have, especially since clearly I am on shaky ground in
> the eyes of many when I voice my criticisms.
Computer languages are designed by humans. Keep that in mind. No two
humans are alike. What you find intuitive, others might find
bizarre. You can surely suggest how to improve a language, but then
you have to convince the designer that your suggested features are
indeed useful.
> But I would like to hope that one day perl will have much nicer error
> reporting, in context, including for dynamically evaluated code, and
> that those wretched line numbers will be consigned to the dustbin of
> history, or invoked via a command line option. And that the -w option
> will be pickier about constructs like the list reference above. And
> that someone will reorganise the documentation into a more task-centric
> form (possibly in addition to the classic documentation we now have).
All of your wishes have been explicitly requested before. And many
times so. Do you have any idea of the amount of effort it takes to do
a fraction of what you ask? It's ENORMOUS!
Lurk on p5p for a while, and you'll have a wider view of the problems
at hand. Snoop around in the perl source code. Patches are always
welcome ;-)
Let me assure you that the perl porters (from what I have seen) always
try their best to make Perl better. The only thing that drives them is
their love for the language.
--Ala
------------------------------
Date: 10 Nov 1999 16:15:53 -0500
From: dha@panix.com (David H. Adler)
Subject: Re: Perl and commonsense part 2
Message-Id: <slrn82jo48.5av.dha@panix.com>
On Wed, 10 Nov 1999 14:18:19 GMT, ajmayo@my-deja.com
<ajmayo@my-deja.com> wrote:
>I define commonsense here as extrapolation from existing experience.
>Some people said that human languages couldn't be learned by using
>commonsense, so why should I expect computer languages to be this way?.
>But I think of, say, Bahasa Indonesian, a language deliberately chosen
>to be regular and simple in syntax. It was this language which unified
>the 10,000 islands of the Indonesian Archipelago, and diverse cultures
>and religions. If you learn a little Bahasa Indonesian, you can
>extrapolate from that, since the grammar is simple. Thus, commonsense
>will work. Is this not a *good* thing?
What you seem to be missing is that the *only* reason "commonsense"
works in this case is that the language was deliberately designed to
work along those lines. Most languages that are designed at all are
designed to facilitate things other than homogenization, admirable
though that goal may be in some cases.
>that someone will reorganise the documentation into a more task-centric
>form (possibly in addition to the classic documentation we now have).
I note that Bart, in his reply mentions the cookbook, with the caveat
that it is paperware. I also note that the cookbook is based heavily
on the faq, which has quite a lot of task oriented entries.
wrt your code, I merely note that (not having gone over it in detail)
you *may* not be aware that hashes can be unspooled into arrays and
arrays can be spooled into hashes (as long as they have an even number
of elements). If you are aware of that, perhaps someone else will
benefit from this comment. :-) Consider the following:
perl -e '%a=(a,1,b,2);@a=%a;for (@a) {print "$_\n"}'
and
perl -e '@a=(a,1,b,2);%a=@a;for (keys(%a)){print "$_ => $a{$_}\n"}'
best,
dha
--
David H. Adler - <dha@panix.com> - http://www.panix.com/~dha/
"If it's not Jewish, it's CRAP!:)" - IsraelBeta on #DWC
------------------------------
Date: Wed, 10 Nov 1999 20:47:58 GMT
From: kragen@dnaco.net (Kragen Sitaker)
Subject: Re: perl as first language?
Message-Id: <2SkW3.64827$23.2543751@typ11.nn.bcandid.com>
In article <80b662$54b$1@towncrier.cc.monash.edu.au>,
Damian Conway <damian@cs.monash.edu.au> wrote:
>sholden@pgrad.cs.usyd.edu.au (Sam Holden) writes:
>
>>> http://www.cs.monash.edu.au/~lindap/papers/ZerothGrail.ps
>
>>That really doesn't look like a postscript file...
>
>Oops, you're right. Looks like my student left some weird HP formatted
>monstrosity where the PostScript should be :-(
It's worse than that! Printing to my LaserJet 4000, I get:
PCL XL error
Subsystem: KERNEL
Error: IllegalAttribute
Operator: SetClipRectangle
Position: 260
>Unfortunately she's in Japan presenting the paper and won't be back till
>December :-( :-(
Maybe you should ask her to give you a copy of the TeX source? Has she
no telnet access in Japan?
>Apologies all round, but it seems I don't have a copy available until
>then.
I'm curious what you think of Python and Scheme for this purpose, and
I'm very interested in the results of your research.
strings | perl -ne 'print if /[a-zA-Z]{5}/ and not (/TimesNewRmn/ or
/Courier/ or /Arial/)' yields the following. I hope it is helpful.
Hey, how did Hewlett-Packard get a copyright on your paper? :)
%-12345X@PJL COMMENT RLW Driver
@PJL COMMENT 3.2.1.0
@PJL SET DUPLEX=OFF
@PJL SET PAGEPROTECT=AUTO
@PJL SET ECONOMODE=OFF
@PJL SET RESOLUTION=600
@PJL SET BITSPERPIXEL=2
@PJL SET TIMEOUT=90
@PJL ENTER LANGUAGE = PCLXL
) HP-PCL XL;2;0;Comment Copyright Hewlett-Packard Company 1989-1997
GRAIL: A Zeroth Programming Language
Linda M
Iver* & Damian Conway**
School of Computer Science and Software Engineering, Monash University, Australia
*linda.mciver@csse.monash.edu.au
**damian.conway@csse.monash.edu.au
This paper presents an overview of the structure and design
rationale for a new programming language designed specifically to
teach novice students the fundamental concepts of imperative
programming. The language, GRAIL, is designed to be used
before
the first programming course, to enable students to become
familiar with programming concepts without the attendant need to
grapple with the syntactic and semantic complexities of a full
modern programming language.
Keywords:
IT Education, Pedagogical Foundations,
Introductory Programming Education
Introduction
Learning to program is an unnatural act. It requires the novice to codify their notions of specification and
process, to acquire an understanding of abstractions for which they may have no prior referents, and to
express these concepts in a formal style of language they have never previously encountered. In other words,
it is like trying to alter their belief system by quoting theoretical philosophy to them in hieroglyphics.
In this paper, we present an introduction to the "pre-language" GRAIL. GRAIL starts from the position that it
is the unfamiliarity of the hieroglyphics (i.e. the language syntax) and the sheer complexity of the full theory
that are the primary stumbling blocks for the novice.
Hence GRAIL is designed to provide a means for the novice programmer to explore the most fundamental
concepts of programming, without the need to wrestle with the arcana of real-world syntax or the full power
of complex semantics.
The GRAIL language is extremely small (its full grammar fits comfortably on two pages[19]), and designed
to present imperative programming concepts through a syntax that is consistent with the student's prior
(mathematical) experience. The syntax also maps isomorphically to the small number of language constructs.
GRAIL is very much a short-term introductory language. Typical problems tackled by students using GRAIL
include real world tasks such as calculation of annual tax payable based on weekly salary rates, music
collection databases, student marks databases, and simple mathematical problems such as Fibonacci and
factorial.
The next section discusses the design principles which have allowed us to achieve the above goals. Following
sections describe the complete GRAIL language and then give an overview of the ongoing evaluation process
we are employing to examine whether the use of a
programming language like GRAIL can improve
students
acquisition of a first programming language.
Design Principles
The design of GRAIL has been guided by four main design principles: predictability, familiarity, affordance,
and simplicity.
Syntactic predictability
The need for "consistency" is a rare point of consensus in the literature on introductory programming
language design [1,2,3,4,5,6,7,8]. Consistency is, however, a slippery concept, particularly in the context of
programming language syntax. Certain kinds of apparent consistency (such as syntactic synonyms and
homonyms [7], or declarations which mimic their subsequent usage [9]) actually make learning harder for the
novice, by muddying semantic and conceptual distinctions between language components.
GRAIL is careful to avoid such self-defeating forms of "consistency". Instead, it attempts to offer
"predictability". For example:
Every construct which forms an agg
regation (such as a structure declaration, the body of a subroutine, or a
loop block) is bracketed in a
keyword
keyword
pair. Hence it is immediately possible to
determine which aggregation a "closing bracket" refers to. Contrast this with the use of "anonymous"
begin
blocking in Pascal [9].
In all types of declarations the keyword
denotes the declaration of a type equivalence (i.e. between two
types), whilst the keyword
holds
denotes the declaration of a type relationship (i.e. between a type and
an instance). Contrast this with the use of
for both these purposes in Eiffel [15].
The input and output syntaxes are identical for all types. Contrast this with the specificities of
scanf()
printf()
GRAIL's syntax and semantic
s are isomorphic. That is, every syntactic component of GRAIL has a single
meaning and every GRAIL construct has a single syntax. Compare this to the
distinct, context-
sensitive meanings of
in Turing [13] or the numerous reference generating mechanisms in Perl [12].
Memetic compatibility
"Cognitive dissonance" [17] is the discomfort engendered by information which is incompatible with existing
knowledge. Apart from the obvious negative reinforcement it produces in the student, cognitive dissonance
also sets up a "belief bias" (a tendency to discount the significance of dissonant information [10]) which
impairs learning.
In designing GRAIL we have addressed these impediments to the acquisition of programming skills by
grounding the syntax of the language in terms and symbols likely to be familiar to the average novice
programmer, and by deliberately avoiding widely used programming "memes" [7] which have meanings
inconsistent with everyday usage.
Thus GRAIL uses
Symbol400023sym:1:2G
PQXED
-,KRXED
dQXEi
N@NE#aDYEiSB
7+u++++++++++++++++sssss
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
for multiplicative operations, since they are likely to be more familiar and
"intuitive" to the novice than the computing standards
. Conversely, GRAIL does not use
while
keyword for repetitions, since mapping the usual
while
condition
statement(s)
syntax back
to English often results in the mistaken assumption that the condition is tested at
every
point in the loop. For
example, in the real-world algorithm:
while you are hungry do
the implication is that, if you cease to be hungry whilst shopping, the loop terminates at once without the
obligation to cook or eat.
Syntactic affordance
Norman [18] defines physical affordance as "the perceived and actual properties of the thing, primarily those
fundamental properties that determine just how the thing could possibly be used
[which] provide strong
clues to the operation of things.
By analogy, it is possible to design "syntactic affordances" by arranging the
grammar of a language so that it encourages the novice to write correct code.
For example, an early version of the GRAIL grammar specified a function definition syntax as follows:
function:
function
identifier
paramlist
returns
typename
statement
return
expression
function
This design requires the student to remember that the
return
directive must appear as the last instruction in
a function body (and may
appear elsewhere, since it is not a valid "statement"). In later versions of
GRAIL we were able to reduce this cognitive load by rearranging the function syntax:
function:
function
identifier
paramlist
returns
typename
statement
function returning
expression
so that the grammar itself now reinforces the correct position of the return directive.
Note that this change of design also had the beneficial side effect of better differentiating the keywords
associated with return specification and return invocation. Early testing indicated that students found
return
(for specification) and
returns
(for invocation) confusingly similar, which impaired their
acquisition of the (related, but distinct) underlying concepts.
Minimalism
GRAIL has been designed to be used in a short, prelimary
programming concepts
course. It is intended
that GRAIL would be taught for a single semester at most, and that, having laid a solid foundation of
understanding of the fundamental programming concepts, the course would subsequently move to a more
complex, powerful, and "difficult" language. GRAIL is intended as a means for students to quickly acquire
programming concepts, without getting bogged down in complex semantics or ornate and unfamiliar syntax.
In other words, GRAIL is designed for
teaching
programming, rather than for
doing
programming.
For these reasons, our overriding design principle has been Occam's Razor. When a useful but nonessential
construct was overly complex, or did not have a single, clear and obvious syntax, as well as intuitive, clear
and exception-free semantics, we have omitted it from the language.
These omissions include: direct access to individual characters of a string, string concatenation, dynamic
arrays or lists, structured loops, case statements, pointers, references, reference parameters in subroutines,
explicit initialization, object-orientation, first class functions or closures, nested functions. Specific rationales
for many of these decisions are presented in the next section.
Although this policy has led to the exclusion of many constructs which programmers will eventually
encounter, the resulting simplification makes the remaining (and more fundamental) concepts of
programming, which GRAIL
convey, that much easier for the beginner to grasp.
Significant Features
Imperative
GRAIL is an imperative language. This paradigm was selected, after much deliberation, because it represents
a style of algorithmic expression that students are already familiar with (from previous interactions with
instruction books, recipes, navigational directions, shampoo bottles, etc.), and because it is the paradigm most
widely favoured in actual teaching (imperative 48.7%, object-oriented and object-based 36.2%, functional
(scheme) 12%, functional (ML etc) 2.4%, other 0.7% [6]).
It is widely argued [2,11,14,15] that, given the increasing popularity of object-oriented languages in industry,
an object-oriented introductory language eliminates the need for a later paradigm shift.
It is our contention that, rather than removing the paradigm shift, this approach merely moves it to the
beginning of the students' computing education, when they are
least
equipped to deal with it.
Moreover, nothing is lost by teaching GRAIL ahead of an object-oriented language, since (with the possible
exception of non-method subroutine calls) all the concepts GRAIL teaches
type vs instance vs value,
aggregation, repetition and selection control structures, I/O, scoping, etc.
are also used in object-oriented
languages.
No pointers or references
Pointers and references are notoriously difficult for students to grasp. While they are extremely powerful
programming constructs, they are also hazardous and error prone [7]. Novice programmers are ill-prepared to
make use of the power, but easy prey to the pitfalls. In a language which possesses sufficiently powerful data
structures, there is little reason to use pointers and references early in the course.
For a teaching language which is not intended for long-term use, "sufficiently powerful" need not imply
significant complexity. A language with numbers, structures, strings and arrays is powerful enough for the
implementation of a range of relatively complex algorithms, without introducing the confusion and difficulty
of pointers and/or references. Even dynamically linked lists can be implemented by using array indices
instead of pointers.
Unicode characters
The non-ASCII Unicode characters
Symbol400023sym:1:2G
Symbol400023sym:1:2G
(assignment),
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
are used as operators in GRAIL,
rather than the more familiar (but only to experienced programmers!) symbols
. This decision was made in order to remain as consistent as possible with students' existing
knowledge. While much of students' educational background cannot be assumed, it is reasonable to rely on a
working knowledge of basic mathematical notation.
Given a user-friendly coding environment, there is little reason for adhering exclusively to the ASCII
character set. While the symbols for multiplication, division, etc. are a relatively trivial part of the language,
learning new symbols adds further complexity and confusion to an already difficult task.
The reasons for choosing
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
are self-evident, but the choice of
Symbol400023sym:1:2G
(rather than some "
variant) warrants further explanation. Our studies indicate that the use of
(or variants such as
assignment in many popular languages adds to novice confusion because of the mathematical meaning of the
symbol (that is: equality). For example, we have observed that students occasionally (and incorrectly) deduce
that the sequence:
should result in
containing the value
("since A equals B, and B equals C, that implies A equals C"). The
character
Symbol400023sym:1:2G
, which is not a common mathematical symbol, at least conveys some sense of a
transfer
of value
from right to left.
A single numeric type
In most languages, the distinction between reals and integers is usually made for reasons of efficiency, and
the specific details (such as the length of an integer) are dependent on the underlying hardware. In languages
such as C, the difference between an
can be critical. A student who uses an
represent a salary would be justifiably confused when the addition of a $4,000 bonus to a $30,000 salary
produces a negative number (as a result of untrapped overflow).
Because novices rarely differentiate between natural and rational numbers, neither does GRAIL. Instead, the
language provides a single numeric type (
number
), thereby avoiding the extra conceptual level [7] of
hardware based distinctions between floating point and integer. The
number
type provides arbitrary
precision rational numbers, which avoids confusing overflows and other mysterious fixed precision side-
effects.
Line-based strings
Real-world manipulation of character strings requires powerful and complex mechanisms, which are
inappropriate for a teaching language. GRAIL provides a simple string type (
), which is defined as a
line of characters. There is no separate character type; a single character is a text of length 1.
The choice of the line as a unit of text is unusual, but fits well with the common novice uses of strings
prompts, labels, output decoration, and simple data. More importantly, using an entire line as an atomic string
makes it possible for GRAIL to provide fully idempotent I/O (see below).
More unusual still is the fact that GRAIL
values are truly atomic. That is, it is not possible to directly
access an individual character in a
. This decision was taken because it reduces the syntactic complexity
of the language, by eliminating syntactic puns [7] such as:
Symbol
where the semantics of this statement depends entirely on the (possibly distant) declaration of
(as either
or an array of
). Removing direct access to characters also eliminates the need to define
semantics for assignment to invalid indices or assignment of multi-character strings to single elements, for
example:
Symbol
SymbolSymbol
| What should this mean?
Symbol
| Is this an append or invalid?
Symbol
| What about the intervening chars?
Similar arguments have led us to exclude string concatenation, substring extraction and other
advanced
string manipulations.
Static arrays
Arrays in GRAIL are indexed from 1 and may contain any single type, including user-defined types. The size
of an array is fixed, having been specified in the variable's declaration. However arrays used as subroutine
parameters may be declared without a fixed size, thereby allowing a single subroutine to accept arrays of any
size. All array accesses are bounds checked at runtime.
Dynamic arrays were considered for inclusion in GRAIL, but were rejected because they introduce a
surprising level of semantic complexity. Consider the statement:
array1[i]
Symbol
array2[j]
It is unclear to us (and hence certainly to a novice!) what the appropriate behaviour of this statement is under
the following conditions:
equals
length(array1)+1
(extend the array contiguously, or is it an error?)
equals
length(array1)+2
(extend the array non-contiguously, or is it an error?)
equals
length(array2)+1
(an error, or return some default
implicitly
initialized value?)
The use of non-contiguous arrays (that is, arrays which may have uninitialized gaps) solves some of these
problems but only by greatly increasing the complexity of the array concept. In our estimation, this "cognitive
cost" outweighs the potential benefits of dynamic arrays.
Idempotent I/O
As suggested in [7], the input and output operators in GRAIL are idempotent in effect. That is, an input
followed by an output is "value-preserving" in all cases.
Most languages provide non-idempotent I/O, which frequently leads to significant confusion for novices. For
example, in most languages a character string is read in to a variable until the first whitespace character is
encountered. However, when the same variable is written out the entire string it contains (including any
embedded whitespace) is printed.
GRAIL's use of line-based strings (
) and arbitrary precision rationals (
number
) makes idempotent I/O
of its basic data types automatic, and hence unsurprising.
Associative comparisons
GRAIL provides associative comparisons, so that the GRAIL expression
is valid and
behaves as
students naturally expect, resulting in a boolean value (
is between
false
otherwise).
Language Overview
Types
GRAIL provides three fundamental data types:
number
(arbitrary precision rationals),
(atomic line of
characters), and
boolean
Type aliases may be created:
type scoretype is number
Array types, implementing collections of elements of simpler type, may be defined:
type marklist is array of 10 number
type daily is array of 52
Symbol400023sym:1:2G
7 marklist
Structured types, which aggregate heterogeneously typed data, may also be defined:
type student_data has
field name holds a_name
field mark holds scoretype
field ID holds text
Values
Literal values of type
number
are decimal values of arbitrary length. They must conform to the pattern:
<digit(s)>(
<digit(s)>)
. For example:
there is no exponential notation available.
Literal values of type
consist of any sequence of characters (except '
') on a single line, enclosed in
matching quotation marks.
For example:
"enter new value"
"the data you entered was not valid"
"a line containing the " character"
"text which spans two or more
lines"
Literal values of type
boolean
false
Neither arrays nor structures have an associated mechanism for specifying compound literals.
Variables
All variables in GRAIL are specified with the
keyword:
item name holds text
item nextmark holds student_data
item marks holds array of 100 student_data
Variables are automatically initialized to the "null" value for their type (
number
false
boolean
). There is no explicit initialization syntax.
Access to the elements of an array is provided by the usual
indexing notation:
bestmark[1]
Symbol
marks[best]
Access to the fields of a structure is provided by the
operator:
item student holds student_data
student's name
Symbol
student's ID
Symbol
student's score
Symbol
Symbol
student's name
Constants
GRAIL supports the definition of constants:
constant pi is 3.15159
Assignment
All assignments in GRAIL use the
Symbol
operator:
Symbol400023sym:1:2G
height
Symbol400023sym:1:2G
Symbol400023sym:1:2G
nextmark
Note that aggregate types (arrays and structures) can be directly assigned.
Operators
Precedence
Operator
Operand type
highest
unary
, unary -
number
Symbol
Symbol
number
number
Symbol400023sym:1:2G
Symbol400023sym:1:2G
Symbol400023sym:1:2G
unary
boolean
boolean
lowest
boolean
Table 1: GRAIL Operator Summary
Control structures
GRAIL provides a single unconditional repetition control structure:
count
Symbol
count - 1
if count
Symbol400023sym:1:2G
factori
Symbol
factorial
Symbol400023sym:1:2G
count
GRAIL also offers a single selection mechanism:
Symbol400023sym:1:2G
Symbol400023sym:1:2G
grade
Symbol
"distinction"
Symbol400023sym:1:2G
grade
Symbol
conditional alternative
otherwise
grade
Symbol
unconditional alternative
Subroutines
GRAIL subroutines may be defined before or after the main program section (and hence before or after any
call to them). Subroutines may not be nested and do not have access to any information outside their own
scope apart from that which is passed via parameters (i.e. there are no global variables or lexical closures).
Recursive subroutines are supported.
Subroutines may take zero or more parameters of any type(s). Each parameter is specified using the standard
holds
... variable definition syntax. An empty parameter list must still be specified (as empty
brackets) both in the declaration and all calls. All parameters are passed by copy.
Functions may return single values of any type (including structures and arrays). There is only one exit point
for any subroutine: at its
function
marker.
A typical GRAIL function looks like:
function factorial (item n holds number) returns number
item result holds number
Symbol400023sym:1:2G
result
Symbol400023sym:1:2G
otherwise
result
Symbol400023sym:1:2G
Symbol400023sym:1:2G
factorial(n-1)
end function returning result
All input in GRAIL is performed using the
statement:
read name, rank, serial_number
To ensure idempotence, each item is read in from a separate line. Only variables of GRAIL's three basic types
may be read in. That is, array elements and structure fields must be read in individually:
item student holds student_data
read students's name, student's ID, student's mark
Output is performed with the
write
statement:
write name, rank, serial_number
Once again, each item is written to a separate line of the output.
File I/O has been deliberately simplified. To read from the file "data" and write to the file whose name is
stored in the text variable
outfile
read name, rank, serial_number from file "data"
write serial_number, name, rank to file outfile
Note that the first attempt to access a file causes the file to be opened for appropriate I/O operation (and
closed for the opposite operation). End of file is detected using the function
otherwise
read name,rank,serial_number from file "data"
Comments
Comments in GRAIL are prefixed by
Evaluation of GRAIL
No matter how sound our design principles and how careful our design process, the only useful measure for a
teaching language like GRAIL is how well it actually teaches.
In 1998 the School of Computer Science and Software Engineering at Monash University introduced a course
(known as "Jump Start") which aims to give students who have never programmed before a gentler
introduction to programming than is offered by our standard first year programming course (in C). The Jump
Start course will also be used to test the merits of GRAIL, and hence the validity of its underlying design
principles.
Jump Start involves two matched groups of students, one learning LOGO [16] and the other GRAIL. This
allows a three-way comparison, between students learning one of the two teaching languages, as well as with
a control group of students not involved in Jump Start (who therefore learn C as their first language). The
choice of LOGO as an alternative teaching language allows us to explore the effects of paradigm (GRAIL vs
LOGO) and pedagogical intent (GRAIL vs C) separately.
We will evaluate the effects of the Jump Start program by:
Direct observation of, and interaction with, students during programming exercises.
Analysis of transcripts of programming exercises (we have already collected over 1,200
transcripts, totalling more than 55,000 lines of code).
Questionnaire and interview feedback from course participants.
Statistical analysis of students' results at the end of the year.
While the statistical results are still being analysed, preliminary findings suggest that students in the GRAIL
groups showed great enthusiasm, and were keen to experiment with the language. Motivation was high, and
students exhibited new and innovative approaches to the exercises. Despite the
of the LOGO turtle,
students in the LOGO groups were more easily discouraged and disheartened, and less likely to experiment
when confronted with an error.
Conclusion
Despite the obvious advantages of an introductory language specifically designed to facilitate learning,
existing "teaching languages" struggle to achieve sufficient pedagogical advantage to overcome the
philosophical, political, financial and psychological arguments against them. These arguments are generally
based on the ultimate usefulness of industry-relevant languages, on student perceptions of (and demand for)
that usefulness, and on teacher familiarity with "mainstream" languages.
GRAIL is yet another attempt to overcome these barriers, but it has the advantage of being extremely simple
and deliberately "throw away" (reducing the force of the Industry Relevance From Day One argument).
Although providing all the fundamentals of programming in the commonest paradigm, GRAIL also departs in
significant ways from existing programming languages. It is "smaller", its semantics are simpler, and its
syntax is grounded in the students' prior experience. It is our hope that these advantages will allow GRAIL to
successfully find a niche in the "foothills" of the programmer's lifelong learning curve.
References
J. Murnane:
The Psychology of Computer Languages For Introductory Programming Courses
Ideas in Psychology, 11(2), 1993, pp 213-228.
Michael K
Tahoma400039sym:1:0G
Hgdir
CXEdj#Ei
Ed#EdadB-,
!!Y-,KRXED
-,KPXED
8YYYY!!!!-,KRXCe8
Tahoma400039sym:1:0G
Tahoma400039sym:1:0G
lling, Bett Koch, John Rosenberg:
Requirements for a First Year Object Oriented
Teaching Language
, SIGCSE Bulletin, 27(1), Mar 1995, pp 173-177.
Timothy A. Budd, Rajeev K Pandey:
Never Mind
Paradigm, What About Multiparadigm
Languages?
SIGCSE Bulletin, 27(2), June 1995, pp 25-30.
Damian Conway:
Criteria and Consideration in the Selection of a First Programming Language
Technical Report 93/192, Department of Computer Science, Monash University, December 1993.
Lambert Meertens:
Issues in the Design of a Beginners
Programming Language, Algorithmic
Languages
, de Bakker/van Vliet (eds), IFIP North Holland Publishing Company, 1981, pp167-184
Suzanne Levy:
Computer Language Usage in CS1: Survey Results
, SIGCSE Bulletin, 27(3), Sept
Linda M
Iver, Damian Conway:
Seven Deadly Sins of Introductory Programming Language Design
Proceedings: Software Engineering: Education & Practice, 1996 (SE:E&P
96), IEEE Computer
Society Press.
[8] S. S. Brilliant and T. R. Wiseman :
The First Programming Paradigm and Language Dilemma,
Proceedings of the 27th SIGCSE Technical Symposium on Computer Science Education, March
[9] Feuer, A. & Gehani, N.,
Comparing and Assessing Programming Languages: Ada, C, and
Pascal
,Prentice-Hall,1984.
[10] J St B T Evans, J L Barston, P Pollard:
On the Conflict Between Logic and Belief in Syllogistic
Reasoning
, Memory and Cognition 11, 1983, pp295-306
[11] Grady Booch:
Object Oriented Design with Applications
, 1991, Benjamin/Cummings, USA.
[12] Wall, L., Christianson, T., & Schwartz, R.L.,
Programming Perl, 2nd Edition
, O'Reilly &
Associates, 1996.
, Introduction to Computer Science using the Turing Programming
Language
, Prentice-Hall,1984.
[14] Michael K
lling, John Rosenberg
: Blue - A Language for Teaching Object-Oriented Programming
Proceedings of the 27th SIGCSE Technical Symposium on Computer Science Education, March
[15] Bertrand Meyer,
Eiffel: The Language,
Prentice-Hall,1992.
Michael Friendly,
Advanced LOGO : A Language for Learning.
Prentice-Hall,1992.
[17] Raymond J. Corsini
, Encyclopedia of Psychology
, Wiley, 1994.
[18] Donald A Norman,
The Design of Everyday Things
,Doubleday,1990.
[19] http://www.csse.monash.edu.au/~lindap/grailGrammar.html
--
<kragen@pobox.com> Kragen Sitaker <http://www.pobox.com/~kragen/>
The Internet stock bubble didn't burst on 1999-11-08. Hurrah!
<URL:http://www.pobox.com/~kragen/bubble.html>
------------------------------
Date: Wed, 10 Nov 1999 20:53:12 GMT
From: kragen@dnaco.net (Kragen Sitaker)
Subject: Re: perl as first language?
Message-Id: <YWkW3.64833$23.2544485@typ11.nn.bcandid.com>
In article <9g7W3.262$Y86.7686@nsw.nnrp.telstra.net>,
Martien Verbruggen <mgjv@comdyn.com.au> wrote:
>Agreed. The point was probably more that Perl can be taught in a
>decent way. And that it can be taught in a structured way. The fact
>that Perl has many ropes doesn't mean you need to tell people about
>them until they really start needing them.
I've heard this argument with C++ too. In C++, the problem is that
people tend to run into the ropes by accident. Teaching someone to
program in C++ without telling them about the hair is like raising a
child in a house with a loaded gun without telling them about the gun.
DrScheme allows you to turn the ropes off, which seems sensible to me.
GRAIL, Damian's research project, doesn't have them in the first
place.
--
<kragen@pobox.com> Kragen Sitaker <http://www.pobox.com/~kragen/>
The Internet stock bubble didn't burst on 1999-11-08. Hurrah!
<URL:http://www.pobox.com/~kragen/bubble.html>
------------------------------
Date: Wed, 10 Nov 1999 14:24:15 -0800
From: David Cassell <cassell@mail.cor.epa.gov>
Subject: Re: perl as first language?
Message-Id: <3829F08F.6F85FC16@mail.cor.epa.gov>
Damian Conway wrote:
>
> abigail@delanet.com (Abigail) writes:
>
> >Now I'm stuck with the image of a student using a canoe to get from
> >Australia to Japan and back.
>
> Canoes? We don't coddle them with "looxuries" like canoes!
>
> She'll be *swimming* back!
First thought: love the reference
Second thought: so you're the *typical* major prof...
David, "...and you tell them that today, and they won't believe you!"
--
David Cassell, OAO cassell@mail.cor.epa.gov
Senior computing specialist
mathematical statistician
------------------------------
Date: Wed, 10 Nov 1999 22:53:04 GMT
From: kragen@dnaco.net (Kragen Sitaker)
Subject: Re: Perl Extensions. Arrgh.
Message-Id: <kHmW3.64933$23.2563065@typ11.nn.bcandid.com>
In article <AziW3.2915$c06.24415@news.rdc1.ct.home.com>,
Dan Sugalski <dan@tuatha.sidhe.org> wrote:
>Ilya Zakharevich <ilya@math.ohio-state.edu> wrote:
>> I "mildly depricated" it *several years* ago. Though probably we can
>> continue supporting it for some more time.
>
>We probably ought to just take it out of the docs entirely then, as on the
>whole you're best off setting the return type properly.
I think this would be a very bad idea. I use docs not just to
understand how to make my code work, but also how other people's code
works -- or, more commonly, fails to work. I think it is very
important to avoid undocumenting features.
--
<kragen@pobox.com> Kragen Sitaker <http://www.pobox.com/~kragen/>
The Internet stock bubble didn't burst on 1999-11-08. Hurrah!
<URL:http://www.pobox.com/~kragen/bubble.html>
------------------------------
Date: 16 Sep 99 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 16 Sep 99)
Message-Id: <null>
Administrivia:
The Perl-Users Digest is a retransmission of the USENET newsgroup
comp.lang.perl.misc. For subscription or unsubscription requests, send
the single line:
subscribe perl-users
or:
unsubscribe perl-users
to almanac@ruby.oce.orst.edu.
| NOTE: The mail to news gateway, and thus the ability to submit articles
| through this service to the newsgroup, has been removed. I do not have
| time to individually vet each article to make sure that someone isn't
| abusing the service, and I no longer have any desire to waste my time
| dealing with the campus admins when some fool complains to them about an
| article that has come through the gateway instead of complaining
| to the source.
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
To request back copies (available for a week or so), send your request
to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
where x is the volume number and y is the issue number.
For other requests pertaining to the digest, send mail to
perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
sending perl questions to the -request address, I don't have time to
answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V9 Issue 1343
**************************************