Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I will say that for all its faults, RMS's dynamically scoped un-namespaced Emacs Lisp interpreter was far better designed than James Gosling's MLisp interpreter. He honestly copped to how terrible a language MockLisp was in the 1981 Unix Emacs release notes:

https://archive.org/stream/bitsavers_cmuGosling_4195808/Gosl...

    12.2. MLisp - Mock Lisp 

    Unix Emacs contains an interpreter for a language 
    that in many respects resembles Lisp. The primary 
    (some would say only) resemblance between Mock Lisp
    and any real Lisp is the general syntax of a program, 
    which many feel is Lisp's weakest point. The 
    differences include such things as the lack of a 
    cons function and a rather peculiar method of 
    passing parameters. 
The "rather peculiar method of passing parameters" was an understatement!

When you called a function and passed it parameters that were MLisp expressions, they were not actually evaluated until the CALLED function PULLED the values with the (arg index "prompt") function, at which time the MLisp expressions from the CALLING were evaluated in the dynamic context of the CALLED function!!!

The official convention that we would use at UniPress to develop MLisp libraries that would work together without name clashes was:

Prefix all local variable names with an ampersand, then a (hopefully) unique abbreviation for the function name, then a dash, to make them unique across all known code.

So you could not use the same local variable names between functions that used each others parameters, because expressions passed as parameters would be evaluated with the bindings of the called function!

(I've written a couple of ; comments in the code to explain how it works.)

    MLisp has a rather strange (relative to other
    languages) parameter passing mechanism. The arg
    function, invoked as (arg i prompt) evaluates the
    i'th argument of the invoking function of the
    invoking function was called interactively or,
    if the invoking function was not called
    interactively, arg uses the prompt to ask you for
    the value. Consider the following function: 

    (defun 
      (in-parens ; The name of the function.
        (insert-string "(") 
        (insert-string (arg 1 "String to insert? ")) 
        (insert-string ")") 
      ) 
    ) 

    If you type ESC-X in-parens to invoke in-parens
    interactively then EMACS will ask in the minibuffer
    "String to insert? " and then insert the string
    typed into the current buffer surrounded by
    parenthesis. If in-parens is invoked from an
    MLisp function by (in-parens "foo") then the
    invocation of arg inside in-parens will evaluate 
    the expression "foo" and the end result will be
    that the string "(foo)" will be inserted into
    the buffer.

    The function interactive may be used to determine
    whether or not the invoking function was called 
    interactively. Nargs will return the number of
    arguments passed to the invoking function. 

    This parameter passing mechanism may be used to
    do some primitive language extension. For example,
    if you wanted a statement that executed a statement
    n times, you could use the following:

    (defun 
      (dotimes n ; n is not a parameter, it's 
                 ; just being "declared" as a local.
        (setq n (arg 1)) ; The first argument to dotimes
                         ; is the number of times to do
                         ; the second parameter.
        (while (> n 0) 
          (setq n (- n 1)) 
          (arg 2) ; The second argument to dotimes is
                  ; an expression to evaluate.
                  ; Each time you (arg 2) is called here,
                  ; the caller's second parameter
                  ; expression is evaluated in the
                  ; current context. 
        )
      )
    )

    Given this, the expression
    (dotimes 10 (insert-string "<>"))
    will insert the string "<>" 10 times. [Note: The 
    prompt argument may be omitted if the function can
    never be called interactively].
Here's an old Emacs manual with more information about the wonders of MLisp! The Emacs mascot (and icon) was a unicorn, because you needed one of your hands to hold down the control key, and your other hand to hold down the meta key, and a horn on your head to type the letter.

http://bitsavers.informatik.uni-stuttgart.de/pdf/cmu/Gosling...



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: