Lisp is homoiconic, meaning code can be treated as data. Which implementations allow me to do so at runtime? The following is an example of what I mean, in pseudocode:
(defun (my-func)
(display "foo ")
(display "bar ")
(display "baz "))
(defun (main-loop)
(my-func)
(swap (first my-func) (second my-func))
(main-loop))
That should repeatedly output "foo bar baz bar foo baz ".
This is probably not the most elegant approach, but in common Lisp you can do something like this:
> (setq f '(defun foo () (princ "foo ") (princ "bar ") (princ "baz ")))
(DEFUN FOO NIL (PRINC "foo ") (PRINC "bar ") (PRINC "baz "))
> (eval f)
FOO
> (foo)
foo bar baz
NIL
> (defun frot ()
; Call foo (stored in f)
(funcall (eval f))
; Swap the 1st and 2nd statements in foo
(setf tmp (cadddr f))
(setf (cadddr f) (cadr (cdddr f)))
(setf (cadr (cdddr f)) tmp)))
FROT
> (frot)
foo bar baz
(PRINC "foo ")
> (frot)
bar foo baz
(PRINC "bar ")
> (frot)
foo bar baz
(PRINC "foo ")
This stores a Lisp function in f rather than executing it in situ, but it does illustrate the fact that a Lisp program is itself a Lisp data structure than can be dynamically manipulated and executed.
The other answers cover the question well.
From a practical level however if you are using Common Lisp and Slime and want to be able to compile code into your running program from Emacs you will need to tell Swank to update from inside your loop.
Add the following to your code and then add (update-swank) inside your loop.
(defmacro continuable (&body body)
`(restart-case
(progn ,#body)
(continue () :report "Just Continue")))
(defun update-swank ()
"Called from within the main loop, this keep the lisp repl working"
(continuable
(let ((connection (or swank::*emacs-connection*
(swank::default-connection))))
(when connection
(swank::handle-requests connection t)))))
This is one way to use the fact you can recompile live with your editor as in this video (sorry for plugging my own vid).
Another way (again with Slime) is to tell it to use a different thread for the communication. I prefer the former method however as opengl is very unstable when used across threads.
[More Details]
The continuable macro in the code above catches any error and gives you the option to ignore it and continue. I find this really helpful and I often make mistakes in the repl and I don't want to 'abort' from an error as this would abort my main loop.
If you are modifying code as you describe, then you know something about the structure of the code. Since you know the structure of the code, you can parameterize that structure
(define (foo-er foo bar baz)
(lambda ()
(display foo)
(display bar)
(display baz)))
Then you can do the swapping by explicitly passing your arguments as:
(define (main-loop)
(let looping ((foo "foo ") (bar "bar ") (baz "baz "))
((foo-er foo bar baz))
(looping bar foo baz)))
> (main-loop)
foo bar baz bar foo baz foo bar baz ...
The CommonLisp version is analogous.
If you need to keep my-func around:
(define my-func #f)
(define (main-loop)
(let looping ((foo "foo ") (bar "bar ") (baz "baz "))
(set! my-func (foo-er foo bar baz)
(my-func)
(looping bar foo baz)))
Related
Common Lisp allows any lisp object to serve as a hash table key. But what if you only want to use part of an object as the key. For example, in
(defstruct action
(name nil :type symbol)
(parameters nil :type list)
(time 0 :type fixnum)
(database nil :type hash-table))
the time slot is inappropriate for equalp hashing situations. What is a good strategy for accessing a hash table using a (partial) lisp object as key? One approach might use a key like (list (action-name act1) (action-parameters act1) (action-database act1)), but this seems rather inefficient. Another approach might create a substructure to the action defstruct with just the three appropriate slots, and use that substructure as a key, but this seems somewhat ad-hoc just for the purpose of hash table access. Are there other methods that could work better?
I will use Common Lisp library from here, as for example
cl-custom-hash-table
Then going to your code, first when you create an action like this:
CL-USER> (setq action-1 (make-action
:parameters '(1 2 3)
:time 45))
produce this error:
The value NIL is not of the expected type HASH-TABLE.
[Condition of type TYPE-ERROR]
so you need to change your definition to something like this:
CL-USER> (defstruct action
(name nil :type symbol)
(parameters nil :type list)
(time 0 :type fixnum)
(database (make-hash-table) :type hash-table))
ACTION
CL-USER> (setq action-1 (make-action
:parameters '(1 2 3)
:time 45))
#S(ACTION :NAME NIL :PARAMETERS (1 2 3) :TIME 45 :DATABASE #<HASH-TABLE :TEST EQL size 0/60 #x3020012E708D>)
Then you should define a function for equal time or what ever you need as follow:
accesing to the data
CL-USER> (action-time action-1)
45
create another action
CL-USER> (setq action-2 (make-action
:parameters '(1 2 3)
:time 102))
#S(ACTION :NAME NIL :PARAMETERS (1 2 3) :TIME 102 :DATABASE #<HASH-TABLE :TEST EQL size 0/60 #x3020012FE58D>)
create the function for testing
CL-USER> (defun equal-actions-by-time (a1 a2) (= (action-time a1) (action-time a2)))
EQUAL-ACTIONS-BY-TIME
define the hash-function:
CL-USER> (defun hash-action (a) (action-time a))
HASH-ACTION
create your hash
CL-USER> (define-custom-hash-table-constructor make-action-hash :test equal-actions-by-time :hash-function hash-action)
MAKE-ACTION-HASH
CL-USER> (defparameter *foo-hash* (make-action-hash) "variable for stackoverflow")
*FOO-HASH*
try it:
CL-USER> (setf (gethash action-1 *foo-hash*) 1
(gethash action-2 *foo-hash*) 10)
10
CL-USER> (gethash action-1 *foo-hash*)
1
T
You can avoid using a library if the distribution will work in implementations that support custom TEST/HASH functions natively, if not you can use with-custom-hash-table
In the optimus case you can work as follow:
CL-USER> (defparameter *foo-hash* (make-hash-table :test 'equal-actions-by-time :hash-function 'hash-action))
*FOO-HASH*
CL-USER> (setf (gethash action-1 *foo-hash*) 1
(gethash action-2 *foo-hash*) 10)
10
CL-USER> (gethash action-1 *foo-hash*)
1
T
I have a file "file.scm"
(define (foo ...) ...)
(define (bar ...) ...)
(define (baz ...) ...)
If I use (load "file.scm") it returns Value :baz
Since it evaluated baz the function is available to be used, but foo and bar were not evaluated and cannot be used.
What modifications would need to be made to file.scm so that it returns:
Value: foo
Value: bar
Value: baz
when I type (load "file.scm") into the REPL?
class Foo
attr_accessor :a,
:time, # ms since epoch
:b,
:c
end
In text mode, the variables listed after 'a' would indent as written above, but in ruby mode they would instead be flush with 'attr_accessor'. How can I get ruby mode to indent like text mode in this situation? Note that I'd like to be able to select the whole file and hit c-m-\ to get the above indentation in addition to all the other ruby-mode.el indentation rules.
This hack should work in the majority of cases.
(defadvice ruby-indent-line (after line-up-args activate)
(let (indent prev-indent arg-indent)
(save-excursion
(back-to-indentation)
(when (zerop (car (syntax-ppss)))
(setq indent (current-column))
(skip-chars-backward " \t\n")
(when (eq ?, (char-before))
(ruby-backward-sexp)
(back-to-indentation)
(setq prev-indent (current-column))
(skip-syntax-forward "w_.")
(skip-chars-forward " ")
(setq arg-indent (current-column)))))
(when prev-indent
(let ((offset (- (current-column) indent)))
(cond ((< indent prev-indent)
(indent-line-to prev-indent))
((= indent prev-indent)
(indent-line-to arg-indent)))
(when (> offset 0) (forward-char offset))))))
Example:
class Comment < ActiveRecord::Base
after_create :send_email_to_author,
:if => :author_wants_emails?,
:unless => Proc.new { |comment| comment.post.ignore_comments? }
end
From Remi (in comments):
Note that Emacs will correctly indent class Foo attr_accessor(:a, :time, # ms since epoch :b, :c) end – Rémi Dec 11 '10 at 8:50
You can add parens and have it indent properly -- I'm adding this here because I'm looking for unanswered questions, and this one comes up (incorrectly, since it has been answered in the comments).
When using Emacs 24.4 or newer, your example will be indented like this by default.
What does the syntax, colons preceding variable in Common Lisp, mean? I've seen programs with such, and I'll present some sample code here, out of a large set of functions.
(defun expand (successorf node)
(mapcar (lambda (action-state-cost)
(let ((action (car action-state-cost))
(state (cadr action-state-cost))
(cost (caddr action-state-cost)))
(make-node :state state :parent node
:action action :path-cost (+ (node-path-cost node) cost)
:depth (1+ (node-depth node)))
))
(funcall successorf (node-state node))
))
Keyword Symbols
:foo is a keyword symbol.
interned in and exported from the KEYWORD package
constantly bound to itself
Usage
Keyword symbols are used when one needs the combination of the following properties:
a symbol is the right data structure
symbols with the same name should be unique (by interning them in a package) -> package KEYWORD
different packages are not needed or wanted -> package KEYWORD
writing the symbol should be easy by not needing to quote them -> :foo better than ':foo
the ability to act as a variable with different values is not needed -> :foo evaluates to :foo itself and only to :foo
In Common Lisp generally symbols can be in a package (kind of a namespace).
An unexported symbol bar in a package foo is written as foo::bar. The double colon is between the package name and the symbol name.
An exported symbol then is written as foo:bar. A single colon is used.
If the symbol is available in the current package then is written as bar without the package.
The package KEYWORD
There is a special package called KEYWORD. A symbol bar in that package is simply and always written as :bar.
Examples
These keyword symbols have also these interesting properties: the symbols are automatically exported from the package KEYWORD (so keyword::bar, keyword:bar, ::bar and :bar are all the same symbol) and they evaluate to themselves:
CL-USER 5 > :bar
:BAR
CL-USER 6 > (describe :bar)
:BAR is a SYMBOL
NAME "BAR"
VALUE :BAR
FUNCTION #<unbound function>
PLIST NIL
PACKAGE #<The KEYWORD package, 0/4 internal, 5830/8192 external>
CL-USER 7 > (eq 'keyword::bar ':bar)
T
CL-USER 8 > (eq :bar ':bar) ; quoted or unquoted, each subform evaluates to :bar
T
Usage
Keyword symbols are used for example as names in named arguments:
(defun foo (&key bar) (+ bar 10))
(foo :bar 7)
Typically they are also used in arguments to instance and structure construction.
(defstruct node state parent action)
DEFSTRUCT is a Common Lisp macro and it generates several functions. One of them is a function MAKE-NODE, which can be used as:
(make-node :state 'open
:parent some-parent
:action an-action)
Note: sometimes the data might also be a keyword. For example in above form, the state might be :open and not open:
(make-node :state :open
:parent some-parent
:action an-action)
They're not variables, actually; those are keywords. They're a special kind of efficient token, similar to “atoms” in other languages. It's a convenient, built-in way to pass named (and, almost always, optional) parameters into a function call.
http://www.gigamonkeys.com/book/functions.html describes the syntax of function calls.
class Foo
attr_accessor :a,
:time, # ms since epoch
:b,
:c
end
In text mode, the variables listed after 'a' would indent as written above, but in ruby mode they would instead be flush with 'attr_accessor'. How can I get ruby mode to indent like text mode in this situation? Note that I'd like to be able to select the whole file and hit c-m-\ to get the above indentation in addition to all the other ruby-mode.el indentation rules.
This hack should work in the majority of cases.
(defadvice ruby-indent-line (after line-up-args activate)
(let (indent prev-indent arg-indent)
(save-excursion
(back-to-indentation)
(when (zerop (car (syntax-ppss)))
(setq indent (current-column))
(skip-chars-backward " \t\n")
(when (eq ?, (char-before))
(ruby-backward-sexp)
(back-to-indentation)
(setq prev-indent (current-column))
(skip-syntax-forward "w_.")
(skip-chars-forward " ")
(setq arg-indent (current-column)))))
(when prev-indent
(let ((offset (- (current-column) indent)))
(cond ((< indent prev-indent)
(indent-line-to prev-indent))
((= indent prev-indent)
(indent-line-to arg-indent)))
(when (> offset 0) (forward-char offset))))))
Example:
class Comment < ActiveRecord::Base
after_create :send_email_to_author,
:if => :author_wants_emails?,
:unless => Proc.new { |comment| comment.post.ignore_comments? }
end
From Remi (in comments):
Note that Emacs will correctly indent class Foo attr_accessor(:a, :time, # ms since epoch :b, :c) end – Rémi Dec 11 '10 at 8:50
You can add parens and have it indent properly -- I'm adding this here because I'm looking for unanswered questions, and this one comes up (incorrectly, since it has been answered in the comments).
When using Emacs 24.4 or newer, your example will be indented like this by default.