Why does lisp say this functon is undefined? - lisp

I write this in a source buffer:
(defun make-cd (artist album rating like)
(list :artist artist :album album :score rating :like like))
(defvar *dab* nil)
(defun addcd (cd) (push cd *dab*))
(defun readab ()
(dolist (cd *dab*)
(format t "~{~10t~a--~5t~a~%~}~%" cd)))
I compile into the REPL by pressing C-c C-k.
The first several functions work fine from REPL:
CL-USER> (make-cd "dixie" "fun time" 6 "y")
(:ARTIST "dixie" :ALBUM "fun time" :SCORE 6 :LIKE "y")
CL-USER> (addcd (make-cd "dixie" "whooola" 6 "y"))
((:ARTIST "dixie" :ALBUM "whooola" :SCORE 6 :LIKE "y"))
But the last is reported as undefined?
CL-USER> (readab)
; Evaluation aborted on #<CCL::UNDEFINED-FUNCTION-CALL #x302000B3895D>.
Am I missing something very obvious?

The issue is due to the C-c C-k command not automatically saving the source before it is processed, and thus the processing is happening on the old save of the source. Save first and the problem goes away.

Related

Haskell with emacs org-mode: Variable not in scope

After wandering off in frustration from before, I've decided to try Haskell in Emacs org-mode again. I'm using Haskell stack-ghci (8.6.3), Emacs 26.2, org-mode 9.2.3 set up with intero. This code block
#+begin_src haskell :results raw :session *haskell*
pyth2 :: Int -> [(Int, Int, Int)]
pyth2 n =
[ (x, y, z)
| x <- [1 .. n]
, y <- [x .. n]
, z <- [y .. n]
, x ^ 2 + y ^ 2 == z ^ 2
]
#+end_src
produces this RESULTS:
*Main| *Main| *Main| *Main| *Main|
<interactive>:59:16: error: Variable not in scope: n
<interactive>:60:16: error: Variable not in scope: n
<interactive>:61:16: error: Variable not in scope: n
However, this
#+begin_src haskell :results raw
tripleMe x = x + x + x
#+end_src
works fine. I've added the :set +m to both ghci.conf and the individual code block to no effect. This code works fine in a separate hs file run in a separate REPL. The pyth2 code in a separate file also can be called from the org-mode started REPL and run just fine as well. Not sure how to proceed. Can include Emacs init info if necessary.
Over on the org-mode mailing list I got an answer that basically is saying the same as you, D. Gillis. He had a similar work-around that actually is more org-mode-centric. Under a heading where your code blocks will be put this "drawer"
:PROPERTIES:
:header-args:haskell: :prologue ":{\n" :epilogue ":}\n"
:END:
and then (possibly in a local variable) run
#+begin_src haskell :results output
:set prompt-cont ""
#+end_src
For reasons unknown I've had to include the :results output otherwise a cryptic error of "expecting a string" happens.
On a few other notes, haskell babel doesn't respond/care about the :session option, i.e., when you run a code block, a REPL *haskell* starts and that will be the sole REPL. Also, a haskell-mode started REPL doesn't play well with an existing org-mode initiated REPL, i.e., if you start a REPL from haskell-mode, it kills the original org-mode *haskkell*REPL, and any new attempt to run org-mode code blocks can't see this new, non-*haskell*REPL. Then if you kill the haskell-mode REPL and try to run org-mode blocks, you get
executing Haskell code block...
inferior-haskell-start-process: List contains a loop: ("--no-build" "--no-load" "--ghci-options=-ferror-spans" "--no-build" "--no-load" . #2)
... you're hosed -- and nothing seems to shake it, not any restart/refresh, nor killing, reloading the file, i.e., a complete restart of Emacs is necessary. Anyone knowing a better solution, please tells usses.
This is a GHCi issue.
The same error occurs when your code is copied directly into GHCi, which also gives a parse error when it encounters the new line after the equal sign. This first error isn't showing up here because org-babel only shows the value of the last expression (in this case, the error caused by the list comprehension).
I'm not entirely familiar with how Haskell-mode sends the code to GHCi, but it looks like it involves loading in the buffer into GHCi as a file, which may be why you didn't have this problem working from the hs file.
There are a few options to fix this, none of which are completely ideal:
Move some portion of the list into the first line (e.g. the first line could be pyth2 n = [).
Wrap the entire function definition with :{ and :}.
Write an Elisp function to modify what is being sent to GHCi and then changes it back after it is evaluated.
The first two options require you to format your code in a form that the GHCi will accept. In your example case, the first option may not be too bad, but this won't always be so trivial for all multi-line declarations (e.g. pattern-matching function declarations). The downside to the second option is that it requires adding brackets to the code that shouldn't be there in real source code.
To fix the issue of extraneous brackets being added, I've written an Elisp command (my-org-babel-execute-haskell-blocks) that places these brackets around code blocks that it finds, evaluates the region, and then deletes the brackets. Note that this function requires that blocks be separated from all other code with at least one empty line.
Calling my-org-babel-execute-haskell-blocks on your example declares the function without any errors.
EDIT: The previous function I gave failed to work on pattern matching declarations. I've rewritten the function to fix this issue as well as to be comment aware. This new function should be significantly more useful. However, it's worth noting that I didn't handle multi-line comments in a sophisticated manner, so code blocks with multi-line comments may not be wrapped properly.
(defun my-org-babel-execute-haskell-blocks ()
"Wraps :{ and :} around all multi-line blocks and then evaluates the source block.
Multi-line blocks are those where all non-indented, non-comment lines are declarations using the same token."
(interactive)
(save-excursion
;; jump to top of source block
(my-org-jump-to-top-of-block)
(forward-line)
;; get valid blocks
(let ((valid-block-start-ends (seq-filter #'my-haskell-block-valid-p (my-get-babel-blocks))))
(mapcar #'my-insert-haskell-braces valid-block-start-ends)
(org-babel-execute-src-block)
(mapcar #'my-delete-inserted-haskell-braces (reverse valid-block-start-ends)))))
(defun my-get-blocks-until (until-string)
(let ((block-start nil)
(block-list nil))
(while (not (looking-at until-string))
(if (looking-at "[[:space:]]*\n")
(when (not (null block-start))
(setq block-list (cons (cons block-start (- (point) 1))
block-list)
block-start nil))
(when (null block-start)
(setq block-start (point))))
(forward-line))
(when (not (null block-start))
(setq block-list (cons (cons block-start (- (point) 1))
block-list)))))
(defun my-get-babel-blocks ()
(my-get-blocks-until "#\\+end_src"))
(defun my-org-jump-to-top-of-block ()
(forward-line)
(org-previous-block 1))
(defun my-empty-line-p ()
(beginning-of-line)
(= (char-after) 10))
(defun my-haskell-type-declaration-line-p ()
(beginning-of-line)
(and (not (looking-at "--"))
(looking-at "^.*::.*$")))
(defun my-insert-haskell-braces (block-start-end)
(let ((block-start (car block-start-end))
(block-end (cdr block-start-end)))
(goto-char block-end)
(insert "\n:}")
(goto-char block-start)
(insert ":{\n")))
(defun my-delete-inserted-haskell-braces (block-start-end)
(let ((block-start (car block-start-end))
(block-end (cdr block-start-end)))
(goto-char block-start)
(delete-char 3)
(goto-char block-end)
(delete-char 3)))
(defun my-get-first-haskell-token ()
"Gets all consecutive non-whitespace text until first whitespace"
(save-excursion
(beginning-of-line)
(let ((starting-point (point)))
(re-search-forward ".*?[[:blank:]\n]")
(goto-char (- (point) 1))
(buffer-substring-no-properties starting-point (point)))))
(defun my-haskell-declaration-line-p ()
(beginning-of-line)
(or (looking-at "^.*=.*$") ;; has equals sign
(looking-at "^.*\n[[:blank:]]*|")
(looking-at "^.*where[[:blank:]]*$")))
(defun my-haskell-block-valid-p (block-start-end)
(let ((block-start (car block-start-end))
(block-end (cdr block-start-end))
(line-count 0))
(save-excursion
(goto-char block-start)
(let ((token 'nil)
(is-valid t))
;; eat top comments
(while (or (looking-at "--")
(looking-at "{-"))
(forward-line))
(when (my-haskell-type-declaration-line-p)
(progn
(setq token (my-get-first-haskell-token)
line-count 1)
(forward-line)))
(while (<= (point) block-end)
(let ((current-token (my-get-first-haskell-token)))
(cond ((string= current-token "") ; line with indentation
(when (null token) (setq is-valid nil))
(setq line-count (+ 1 line-count)))
((or (string= (substring current-token 0 2) "--") ;; skip comments
(string= (substring current-token 0 2) "{-"))
'())
((and (my-haskell-declaration-line-p)
(or (null token) (string= token current-token)))
(setq token current-token
line-count (+ 1 line-count)))
(t (setq is-valid nil)
(goto-char (+ 1 block-end))))
(forward-line)))
(and is-valid (> line-count 1))))))

Function to determine holiday in elisp

It's there any function to determine current system date is holiday or not in elisp.
function like this.
(is-holiday (current-time))
The answer requires that the user set up a calendar of predefined holidays, like this example. I have included a test holiday for May 9 -- if the user wishes to test out this function on any day other than May 9, the user may wish to change the Arbitrary Test Holiday to whatever day the test is being performed -- after the function has been tested, the test entry can be removed.
For examples of how to format the holidays, please refer to the doc-string for the variable calendar-holidays within the library holidays.el -- e.g., holiday-fixed; holiday-float; holiday-sexp; (lunar-phases); (solar-equinoxes-solstices); holiday-hebrew; holiday-islamic; holiday-bahai; holiday-julian; holiday-chinese; etc.
How can you try out this example?: Block/copy/paste the code into your *scratch* buffer; and type M-x eval-buffer RET; and then type M-x is-holiday RET. It is a fully functional working draft. If you decide that you don't like it after you try it, just restart Emacs and you'll be back to where you were before you tried it.
The testing that was performed was done with the most recent public release of Emacs: GNU Emacs 24.4.1 (x86_64-apple-darwin10.8.0, NS apple-appkit-1038.36) of 2014-10-20 on builder10-6.porkrind.org.
(require 'holidays)
(defcustom my-custom-holiday-list (mapcar 'purecopy '(
(holiday-fixed 1 1 "New Year's Day")
(holiday-float 1 1 3 "Martin Luther King Day")
(holiday-float 2 1 3 "President's Day")
(holiday-float 5 1 -1 "Memorial Day")
;; ARBITRARY TEST HOLIDAY -- MAY 9
(holiday-fixed 5 9 "Arbitrary Test Holiday -- May 9")
(holiday-fixed 7 4 "Independence Day")
(holiday-float 9 1 1 "Labor Day")
(holiday-float 10 1 2 "Columbus Day")
(holiday-fixed 11 11 "Veteran's Day")
(holiday-float 11 4 4 "Thanksgiving")
(holiday-fixed 12 25 "Christmas")
(solar-equinoxes-solstices)
(holiday-sexp calendar-daylight-savings-starts
(format "Daylight Saving Time Begins %s"
(solar-time-string
(/ calendar-daylight-savings-starts-time (float 60))
calendar-standard-time-zone-name)))
(holiday-sexp calendar-daylight-savings-ends
(format "Daylight Saving Time Ends %s"
(solar-time-string
(/ calendar-daylight-savings-ends-time (float 60))
calendar-daylight-time-zone-name))) ))
"Custom holidays defined by the user."
:type 'sexp
:group 'holidays)
(defun is-holiday ()
"Is today a holiday?"
(interactive)
(let* (
(d1 (time-to-days (current-time)))
(date (calendar-gregorian-from-absolute d1))
ee
res-holidays
(displayed-month (nth 0 date))
(displayed-year (nth 2 date))
(holiday-list
(dolist (p my-custom-holiday-list res-holidays)
(let* (h)
(when (setq h (eval p))
(setq res-holidays (append h res-holidays)))))) )
(mapcar
(lambda (x)
(let ((txt (format "%s -- %s" (car x) (car (cdr x)))))
(when (eq d1 (calendar-absolute-from-gregorian (car x)))
(push txt ee))))
holiday-list)
(if ee
(message "The following holiday(s) is/are today: %s" (nreverse ee))
(message "Today is not a holiday."))))

How to read user input in Lisp

I'm very new to Lisp and am trying to write a program that simply asks a user to enter 3 numbers and then sums them and prints the output.
I've read that you can you a function like:
(defvar a)
(setq a (read))
To set a variable in Lisp, but when I try to compile my code using LispWorks I get the following error:
End of file while reading stream #<Concatenated Stream, Streams = ()>
I feel like this should be relatively simple and have no idea where I'm going wrong.
I've not worked with LispWorks, so it's only a guess.
When compiler traverses your code it gets to the line (setq a (read)), it tries to read input, but there is no input stream while compiling, thus you get an error.
Write a function:
(defvar a)
(defun my-function ()
(setq a (read))
It should work.
This should evaluate properly in your Lisp:
(defun read-3-numbers-&-format-sum ()
(flet ((prompt (string)
(format t "~&~a: " string)
(finish-output)
(read nil 'eof nil)))
(let ((x (prompt "first number"))
(y (prompt "second number"))
(z (prompt "third number")))
(format t "~&the sum of ~a, ~a, & ~a is:~%~%~a~%"
x y z (+ x y z)))))
Simply evaluate the above function definition, then run the form:
(read-3-numbers-&-format-sum)
at your LispWorks interpreter.

rx macro and eager macro-expansion failure in Emacs

(defun my-blah (str)
(rx (+ (eval (substring str 1)))))
Evaluation of that code puts the following message in the Messages buffer:
Eager macro-expansion failure: (void-variable str)
What does it mean and is it something to worry about?
The function seems to work fine. On the other hand, evaluation of the following code doesn't generate such a message:
(defvar my-str "oink")
(rx (+ (eval (substring my-str 1))))
Appendix: alternative ways to define the function without generating such messages
(defun my-nah (str)
(rx-to-string `(+ ,(substring str 1))))
(defun my-llama (str)
(eval `(rx (+ ,(substring str 1)))))
rx is a macro, which implies that it can be expanded pretty much at any time before actually evaluating the code. Typically, it means it will be expanded during compilation. Compilation happens before str is known, so the expansion of rx cannot depend on the value of str.
If you test it without compiling it, then macroexpansion happens late (just before/during evaluation) so the problem is hidden (tho if you use lexical-binding the problem will re-appear because the eval will not have access to the lexical context in which str is defined).
Eager macroexpansion (new in 24.4), is used to expand macros when loading a non-compiled file, which provides a macro-expansion behavior similar to the one for compiled code. For backward-compatibility, when an error occurs during eager macro-expansion, Emacs falls back on expanding macros late (after emitting the warning you saw).
If you want to easily test your rx expressions, use this :
(defun test-rx (test-file test-reg)
(if (get-buffer (setq test-buffer "RX"))
(kill-buffer test-buffer))
(with-temp-buffer
(insert-file-contents-literally test-file)
(goto-char (point-min))
(while
(re-search-forward test-reg nil t)
(when (match-string 0)
(let ((one (match-string 1))
(two (match-string 2)))
(if one
(progn
(pop-to-buffer test-buffer)
(goto-char (point-max))
(insert (format "Found %s and possibly %s" one two)))))))))
(defun test-rx-now (file)
"plop"
(interactive
(let (file)
(setq file (read-file-name "File to search: "))
(list file)))
(test-rx file
(rx
"$(function"
(*? anything)
(or "'" "\"")
(group
(* (not (any "'" "\"")))
".php"
)
(or "'" "\"")
(*? anything)
"})"
)))

Trouble formatting first exercise from Practical Common LISP

I'm beginning to work through Practical Common LISP and the first exercise is to write a simple database. I'm using GNU CLISP 2.48 (2009-07-28) on cygwin.
This code, which I've compared against the book several times, doesn't produce output the way the book says it should
(defun make-cd (title artist rating ripped)
(list :title title :artist artist :rating rating :ripped))
(defvar *db* nil)
(defun add-record (cd) (push cd *db*))
(add-record (make-cd "Roses" "Kathy Mattea" 7 t))
(add-record (make-cd "Fly" "Dixie Chicks" 8 t))
(add-record (make-cd "Home" "Dixie Chicks" 9 t))
(defun dump-db ()
(dolist (cd *db*)
(format t "~{~a:~10t~a~%~}~%" cd)))
(dump-db)
I get
TITLE: Home
ARTIST: Dixie Chicks
RATING: 9
RIPPED:
*** - There are not enough arguments left for this format directive.
Current point in control string:
"~{~a:~10t~a~%~}~%"
|
I don't understand format or LISP well enough to being to troubleshoot. The book says I should be getting a list of all the records in the database. What has gone wrong?
First, let's look at the return from (make-cd):
[12]> (make-cd "Home" "Dixie Chicks" 9 t)
(:TITLE "Home" :ARTIST "Dixie Chicks" :RATING 9 :RIPPED)
You aren't including a value for :ripped! Change (make-cd) to:
(defun make-cd (title artist rating ripped)
(list :title title :artist artist :rating rating :ripped ripped))
Note the ripped after :ripped.
If you use the compiler in CLISP, it tells you what is wrong:
[1]> (defun make-cd (title artist rating ripped)
(list :title title :artist artist :rating rating :ripped))
MAKE-CD
[2]> (compile 'make-cd)
WARNING: in MAKE-CD : variable RIPPED is not used.
Misspelled or missing IGNORE declaration?
MAKE-CD ;
1 ;
NIL
The variable RIPPED is not used.
The format directive ~{...~} is an iterative construct, and its corresponding argument is expected to be a list. Furthermore in this case, because of the two occurrences of ~a, each iteration will consume two items, so the total number of items in the list is expected to be even. Yet you provided it with an odd number of items.