info-gnus-english
[Top][All Lists]
Advanced

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

Re: need help on hobby project


From: Emanuel Berg
Subject: Re: need help on hobby project
Date: Fri, 16 Jan 2015 22:44:11 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4 (gnu/linux)

Hugh Lawson <hlawson@gmail.com> writes:

> To improve my scanty knowledge of elisp, I want to
> rewrite a macro as a function.

Macros are functions that accept code as arguments
(without evaluating it), and then use that code to put
together a new program, which is at last executed.

So macros are programs that write programs (macros are
"metaprograms"). The outcome of the macro invocation
is a function of the dynamically created program, in
turn the result of the code provided as well as the
macro itself.

Compare this to the much simpler model of an ordinary,
static function that just crunches input data and maps
it to the output result!

Macros are hard to understand, read, and write. It is
nothing for beginners, I would say, tho I don't want
to disencourage anyone from doing even difficult
things (unless "difficult" means climbing K2).

One example where macros can be useful is to create
functions that have a syntax that isn't that of the
programming language below (Elisp in this case). After
it is done, those functions can be used transparently
breaking the rules of the syntax. (So macros provide
for "metaprogramming" as well!)

As for me,

   grep defun **/*.el | wc -l

tells me I've 213 functions. I have only one
"defmacro", which I didn't even write. In the same
file, I have a defun which I *did* write, so let me
illustrate:

The function, which isn't the easiest one to read...

    (defun show-time-and-date (&optional insert)
      (interactive "P")
      (let ((date-script "long-date"))
        (if insert (insert-shell-command date-script)
          (with-temp-buffer
            (shell-command date-script 1)
            (message (buffer-substring (point-min) (1- (point-max)) ))))))

...is still one thousand times easier to read than
the macro:

    (defmacro measure-time (&rest body)
      "Measure and return the running time of the code block.
    http://nullprogram.com/blog/2009/05/28/";
      (declare (indent defun))
      (let ((start (make-symbol "start")))
        `(let ((,start (float-time)))
           ,@body
           (- (float-time) ,start))))

> (shell-command COMMAND &optional OUTPUT-BUFFER
> ERROR-BUFFER)

This should be read like this:

1. There is a function called shell-command.

2. shell-command always accepts one argument, which is
   referenced as COMMAND in the documentation and
   command in the code

3. shell-command may also accept two arguments,
   COMMAND and OUTPUT-BUFFER, or three: COMMAND,
   OUTPUT-BUFFER, and ERROR-BUFFER

> 3. I accomplised this with this keyboard macro:
>
> ;;look up latin words (fset 'whitaker [?\M-x ?c ?o ?p
> ?y ?- ?w ?o tab return ?\M-x ?s ?h ?e ?l tab ?- ?c ?o
> ?m ?m tab return ?l ?a ?t ?i ?n ? ?\C-y return])

Oh, no! KEYBOARD macro! Well, I'll just leave the
above... Perhaps it can be education to some.
(Keyboard macros are poor man's programming, plain
automatization of keystrokes, they don't relate to the
defmacro stuff I wrote about.)

If you get it to work with a keyboard macro, then just
use `C-h k' to get the function names. Put them
together in your functions. Check the documentation
for all the functions - sometimes, there are better
ways in Elisp code, than their keyboard/interactive
counterparts. If you are inpatient, you can use this
command

    emacs -batch -f batch-byte-compile source.el

and Emacs will tell you if there are improvements to
be made.

Good luck!

-- 
underground experts united


reply via email to

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