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

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

Re: conditionals in elisp


From: Pascal J. Bourguignon
Subject: Re: conditionals in elisp
Date: Tue, 27 Oct 2009 22:14:00 +0100
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/22.3 (darwin)

Harry Putnam <reader@newsguy.com> writes:

> pjb@informatimago.com (Pascal J. Bourguignon) writes:
>
> [...]
>
>> Why can't you see these links on the first page returned by Google?
>
> Be damned if I know..  Maybe I do need new glasses...
>
>> http://steve-yegge.blogspot.com/2008/01/emergency-elisp.html
>
> There they are, if/else examples... NICE!
>
> [...]
>
>> Just tell us when you have five minutes to learn all there is to know
>> about lisp ;-)
>
> OK, I'll bite, the only risk is looking a fool, and I'm so far into that
> at this point, it can't matter.

Ok. It's quite simple really.  
Here the 5-minute all you need to know about lisp:


There are two kinds of data:

- atoms, and
- lists.

Atoms are numbers of various sort such as: 123 1.23 1.2e.3,  vectors
such as [1 2 3], strings such as "abc", and other kind of objects such
as functions, predefined data structures (eg. hash-tables), or user
defined structures or objects, and  symbols such as: foo print if
what-a-nice-day, +, -, etc, that are used to name the various things
such as variables or functions.  (Symbol can contain mostly any
character that wouldn't be interpreted as another kind of atom or
list, including spaces (just escape them with \)).


Lists are sequences of data enclosed in parentheses:

(a list containing only symbols)
(a list containing (a sub list))
(1 list containing 2 numbers and a "string")


Programs are data of a certain form that is evaluated.  
The evaluation rules are:

- symbols alone are considered to be variable references, so the value
  bound to the variable named by the symbol is returned.

- the other atoms are self evaluating, that is, their value is themselves.

- lists are considered to be operator applications and have always the form:

      (operator  arguments...)

   There are three kinds of operators:

      - functions,
      - macro,
      - special operators.

   When the operator is a function, all the arguments are evaluated in
   turn (from left to right), then the function is called with the
   values of the arguments passed as parameters.
   
       (sin (/ pi 2))

       sin is a function, so we evaluate the argument:
            (/ pi 2)
            
             / is a function so we evaluate the arguments:

               pi is a symbol, so we get the value bound to the variable named 
pi.
               It's 3.141592

                  2 is a atom that is not a symbol, so its value is itself.
                  2

             We call the function / with the argument 3.141592 and 2
             We get the result: 1.570796

       We call the function sin with the argument 1.570796  
       We get the result: 1.


   When the operator is a macro, then the arguments ARE NOT evaluated,
   but are passed directly to the macro function.  The macro function
   must return a new expression that will be evaluated instead of the
   macro call.  By consequence, the meaning and possible order of
   evaluation of the arguments depend on the macro function itself:
   you have to lookup the documentation or source of the macro to know
   what the argument should be, and whether and when they are
   evaluated.

       For example, in: (dotimes (i 3) (insert "hi "))
       dotimes is a macro, therefore the two arguments, the lists (i 3) and
       (insert "hi ") are passed as-is to the macro function dotimes.
       What this macro function will do, is to generate an expression that:

       - will evaluate the second element of the first argument (eg. 3,
         returning 3),

       - will create a variable named i (the first element of the first
         argument, 

       - and that will evaluate the remaining arguments (the form (insert
         "hi "), and others if there were) the number of times indicated
         by that value, by binding a counter from 0 to the variable named
         i, for use by the body.

       You can see that by using the macroexpand function:
           (macroexpand '(dotimes (i 3) (insert "hi ")))
           --> (let ((--dotimes-limit-- 3) 
                     (i 0))
                   (while (< i --dotimes-limit--)
                      (insert "hi ")
                      (setq i (1+ i))))


   A special operator is like a primitive macro: the evaluation of the
   arguments depends on a rule specific to each special operator.  


There is a small number of special operators (about 20 to 30), and
while macros are used to extend the language beyond this small number
of special operators, they represent only a small percentage of the
operators available in a typical lisp system.


That's it, that's all there is to know about lisp. (It could be
expressed more shortly, in two pages of lisp code for the eval
function too ;-)).



All the rest is rather accidental, it could be different, and it would
still be lisp.  It may change from one kind of lisp to another too
(emacs lisp, Common Lisp, ISO-Lisp, Scheme, and older variants).
There's some operators that are common to most lisps, such as if, let
and lambda, and of course there's a whole culture,  quite endearing
and interesting, that may take however some time to learn and integrate.



To know what an operator is (function, macro or special operator), and
how to use it in emacs lisp, use the C-h f command.

For if:  C-h f if RET 

    if is a special form in `C source code'.
    (if cond then else...)

    If cond yields non-nil, do then, else do else...
    Returns the value of then or the value of the last of the else's.
    then must be one expression, but else... can be zero or more expressions.
    If cond yields nil, and there are no else's, the value is nil.


Try the same on dotimes and on insert.


-- 
__Pascal Bourguignon__


reply via email to

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