help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: becoming a lisp developer


From: ken
Subject: Re: becoming a lisp developer
Date: Wed, 27 Jun 2012 11:36:01 -0400
User-agent: Mozilla/5.0 (X11; Linux i686; rv:10.0.4) Gecko/20120424 Thunderbird/10.0.4



On 06/26/2012 08:29 AM Pascal J. Bourguignon wrote:
ken<gebser@mousecar.com>  writes:

People familiar with C say it's a difficult language.  But I guess
they never tried it.  You can pick up a book on it and if you give it
a little bit of time every day, you can learn enough in a week to
write interesting and working programs.  And it's fun.  Shell
programming like bash and ksh are easy and fun too.  C++ too, but to a
lesser degree. But elisp....  I tried repeatedly over more than ten
years to learn it, bought and read a couple books on it, did some
tutorials, of course spent a lot of time in the docs, but it wasn't
until just a few years ago (and with a lot of help from this list)
that I was able to write my first elisp program.  I started a second
one last year and I'm still plodding really slow through it (but not
often).  It takes so long to get things to work that I'm discouraged
from spending time on it.  Half the time I'm trying to figure out the
code and moan to myself that, if I could write this function in C, I
would have had it written in one-tenth the time... or less.  Then,
after I've written some working elisp code and look at, I see it's not
that difficult.  So how is it that it took so long to figure out?

The fact is, there are big categories of languages.

C and Pascal are the same.  C or C++ are almost the same (compare Homo
Sapiens Sapiens with Homo Neandertalis).  All the common languages fall
into the Algol category of languages; basically, when you know one, you
know all of them: the semantics are fundamentally the same, only the
unimportant syntax changes.

But beside the Algol category, there are:

- the logical programming category (Prolog, etc),

- the lisp category (eg. Common Lisp, Emacs Lisp, Scheme, and a lot of
   older lisps)

- the functional programming category (Haskell, ML, Ocaml, etc).

and a lot of others.
http://en.wikipedia.org/wiki/List_of_programming_languages_by_type


When you change of language category, the syntax may change or not, but
importantly, it's the semantics that change.  That's where you may be
misled and have to spend more learning time.


For example, syntactically, adding two numbers is written:

      {
         int a=1;
         int b=1111111112;
         int c=1111111113;
         a=b+c;
      }

in C, and:

     (let ((a 1)
           (b 1111111112)
           (c 1111111113))
       (setf a (+ b c)))

in lisp.  But the syntac is irrelevant.  You can easily write a
pre-processor to convert one into the other.
(See for example: http://paste.lisp.org/display/25134)

Yes, the latter sort of expression, where the operand is at the beginning of the expression, is called reverse-polish. There was at least one hand-held scientific calculator which came out in the mid-1970s which used this notation. Though it took only a few seconds to adjust one's thinking to this syntax, that sort of syntax on such devices pretty much died out (AFAIA), people, not surprisingly, preferring a notation which conformed more closely to natural language. Conforming to natural language has long been a goal of cyber-language developers, for understandable reasons: less attention to syntactic anomolies allows for more attention to logic and so too then probably better applications.

But, yes, just this once instance is trivial. Back in the 1980s I wrote an expression parser (in C). I remember being quite surprised how little code it required, just ten or twelve lines IIRC. It was so pleasing in its terseness and elegance that I assigned the same task to my college students to exercise our discussion on recursion. (To make it a homework assignment they could do in a week, their C code needn't perform error checking, but rather assume that all expressions their programs would read in were well formed, nor would they need consider critically heavy burdens on the stack due to very deep nesting.) This function/program was intended to parse C-style syntax (e.g., "(2 + (5 * 3))"), but it would be trivial to alter it to parse reverse-polish, or vice versa-- which offers up the question, why require text to be parsed to conform to one syntactical ruleset as opposed to another? The code for the parser is nigh identical... so why not cut developers a small break by conforming more closely to natural language?




What's more important to understand the meaning of those programs, is
their semantics.

In a 32-bit C, (ie. a C where int has a 32-bit two-complement
representation), the result would be -2072745071 with some compiler.
(In some other C compilers, it could signal a run-time error, the C
standard doesn't specify what must happen).

In a 64-bit C, (ie. a C where int has a 64-bit two-complement
representation), the result would be 2222222225.

In a 32-bit emacs, which has no bignums and where fixnums are limited to
29-bit two-complement the result would be 74738577.

In a 64-bit emacs, which has still no bignums, but where fixnums are
limited to 61-bit two-complement, the result would be 2222222225.

In a Common Lisp implementation, which therefore has bignums, whatever
the size of the fixnums, the results would be 2222222225.
>
> ....

Thank goodness such concerns are seldom central to applications developers, systems developers having for the most part isolated app developers from hardware vagaries (as von Neuman intended). This however has long been an area requiring more co-operation between hardware and systems folks.


The semantical differences are therefore:

In Common Lisp, + for integers implements the mathematical integer
addition (up to the available memory).

In emacs lisp, + for integers implements the addition modulo 29 or 61
depending on the machine word size.

In C, + for int may implement the addition modulo 32 or 64, or something
else (including signaling a run-time error, or a compilation-time error).

Yes, if these were the only barriers to understanding, for all practical purposes, there effectively be no barriers at all.



And this is only for the simpliest of the operation.  In the code sample
above, there are other semantic differences, like the fact that in lisp
there are no statement, therefore all expression returns a value.  setf
returns the last value assigned.  let returns the result of the last
expression in its body, so the let form actually returns the result of
the addition, and if you evaluate it in a REPL (read eval print loop),
then this result will be printed too.  On the other hand, {} is a
statement in C, which has no result value and nothing is ever returned
or printed by that code sample.  The let form is a valid lisp expression
as it is.  The {} however does not stand alone: you need to wrap it in a
C program to make it really meaningful.  There's the fact that in C,
types are a property of the variables, while in Lisp types are property
of the values.  The fact that setf is actually a macro, that while it's
provided by the language, could be written by the user if it was
missing, like any other macros, vs. the fact that = is a hard wired C
operator and the user can't add new operators (it's possible for some of
them in C++, but with vastly different mechanisms and semantics than
lisp macros).  Etc.

One thing you seem to be implying is that elisp is more consistent in its syntax than C in many regards. Consistency, however, can lead to ambiguity.



The conclusion is that to learn a programming language in a different
category of what you know already, you must forget what you know, and
just learn it from the beginning.

I wouldn't say, "forget what you know" but rather "don't make assumptions about one language based solely on knowledge from another language." As you pointed out above, while there are many differences, there are also many similarities. We don't really want to forget and then have to relearn the similarities.



And the existance of those different broad categories is also the reason
why you are told to learn different programming languages.  But learning
C and C++ doesn't count.  You must pick one language in each category!

My goal in life isn't to experience every category of programming language. I'd just like to contribute code to perform tasks which in my estimation seem to need coding... where and when I'm able to.


Since you already know C, you should learn at least Prolog, one lisp
(but it's also useful to learn elisp, scheme and Common Lisp),  Haskell,
APL and Smalltalk.

Too much samsara.  :)


Maybe, if I live to be three hundred, I'll write an elisp book myself.

Usually it comes much fater.

Thanks for the encouragement... and for the conversation. But it will depend on understanding, which doesn't conform itself in any way to calendars.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]