Formatting a list - lisp

I have the following list: (X X O NIL NIL O NIL NIL O)
I'd like to format it to look like this:
X | X | O
--+---+--
| | O
--+---+--
| | O
I could probably cobble something together with what little I know about Lisp and FORMAT, but it would probably be pretty gross. Any pointers would be greatly appreciated.

* (format t "~{~A | ~A | ~A~%~^--+---+--~%~}"
(mapcar (lambda (x) (or x " ")) '(X O X NIL X X O X NIL)))
X | O | X
--+---+--
| X | X
--+---+--
O | X |
NIL

* (format t "~{~A | ~A | ~A~%~^--+---+--~%~}"
(mapcar (lambda (x) (or x " ")) '(X O X NIL X X O X NIL)))
X | O | X
--+---+--
| X | X
--+---+--
O | X |
NIL
A little explanation about the format string in the above. Crucial here are the '~{' '~}' and '~^'. A pair of matching Tilde braces take a list as input argument and iterate over it. The ~^ controls an early escape from this loop, if the list being iterated over is empty.
Relevant documentation ~{ and ~^.

Related

How do I get the list of all environment variables available in a Lisp process?

I want to enumerate the list of all environment variables available in my Lisp process. I want the same list that is returned by the C variable environ.
Neither SBCL nor Clozure CL seem to provide it out of the box. Can I do it using CFFI?
Interfacing with the OS and common lisp is still quite dependent on your lisp distribution. So more or less is not easy to find a good library that works in all CL distributions.
I recommend you to work with UIOP, which comes with ASDF 3 and above and it is the best library for working with the OS inside common lisp nowadays. However it doesn't have a function to list the environment variables, furthermother if we take a look at how it works with environment varables we can see that for every lisp distribution we have a different version of accessing the variables only for example:
(defun getenv (x)
"Query the environment, as in C getenv.
Beware: may return empty string if a variable is present but empty;
use getenvp to return NIL in such a case."
(declare (ignorable x))
#+(or abcl clasp clisp ecl xcl) (ext:getenv x)
#+allegro (sys:getenv x)
#+clozure (ccl:getenv x)
#+cmucl (unix:unix-getenv x)
#+scl (cdr (assoc x ext:*environment-list* :test #'string=))
#+cormanlisp
(let* ((buffer (ct:malloc 1))
(cname (ct:lisp-string-to-c-string x))
(needed-size (win:getenvironmentvariable cname buffer 0))
(buffer1 (ct:malloc (1+ needed-size))))
(prog1 (if (zerop (win:getenvironmentvariable cname buffer1 needed-size))
nil
(ct:c-string-to-lisp-string buffer1))
(ct:free buffer)
(ct:free buffer1)))
#+gcl (system:getenv x)
#+genera nil
#+lispworks (lispworks:environment-variable x)
#+mcl (ccl:with-cstrs ((name x))
(let ((value (_getenv name)))
(unless (ccl:%null-ptr-p value)
(ccl:%get-cstring value))))
#+mkcl (#.(or (find-symbol* 'getenv :si nil) (find-symbol* 'getenv :mk-ext nil)) x)
#+sbcl (sb-ext:posix-getenv x)
#-(or abcl allegro clasp clisp clozure cmucl cormanlisp ecl gcl genera lispworks mcl mkcl sbcl scl xcl)
(not-implemented-error 'getenv))
(defsetf getenv (x) (val)
"Set an environment variable."
(declare (ignorable x val))
#+allegro `(setf (sys:getenv ,x) ,val)
#+clisp `(system::setenv ,x ,val)
#+clozure `(ccl:setenv ,x ,val)
#+cmucl `(unix:unix-setenv ,x ,val 1)
#+ecl `(ext:setenv ,x ,val)
#+lispworks `(hcl:setenv ,x ,val)
#+mkcl `(mkcl:setenv ,x ,val)
#+sbcl `(progn (require :sb-posix) (symbol-call :sb-posix :setenv ,x ,val 1))
#-(or allegro clisp clozure cmucl ecl lispworks mkcl sbcl)
'(not-implemented-error '(setf getenv))
so for getting one variable:
CL-USER> (uiop:getenv "GEM_PATH")
"/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev:/Users/toni/.rvm/gems/ruby-2.1.6#global"
as pointed in a comment if you are usign SBCL you can get this with it:
SB-EXT:POSIX-ENVIRON
example in c:
extern char **environ;
//...
int i = 0;
while(environ[i]) {
printf("%s\n", environ[i++]); // prints in form of "variable=value"
}
| GEM_HOME=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev |
| SHELL=/bin/bash |
| TERM=dumb |
| TMPDIR=/var/folders/zs/t9wnzpqj2bdgjjgjwb8pqxc80000gn/T/ |
| Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.e0K30SfWTc/Render |
| USER=toni |
| SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.KvlUaU8PD5/Listeners |
| __CF_USER_TEXT_ENCODING=0x1F5:0x0:0x8 |
| PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev/bin:/Users/toni/.rvm/gems/ruby-2.1.6#global/bin:/Users/toni/.rvm/rubies/ruby-2.1.6/bin/:/usr/texbin:/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/toni/.rvm/bin |
| PWD=/Users/toni/learn/lisp/cl-l/stackoverflow/scripts |
| LANG=es_ES.UTF-8 |
| XPC_FLAGS=0x0 |
| XPC_SERVICE_NAME=org.gnu.Emacs.13016 |
| SHLVL=1 |
| HOME=/Users/toni |
| BUNDLE_PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev |
| LOGNAME=toni |
| GEM_PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev:/Users/toni/.rvm/gems/ruby-2.1.6#global |
| DISPLAY=/private/tmp/com.apple.launchd.ljkiChb2wE/org.macosforge.xquartz:0 |
| _=/tmp/babel-6131RLH/C-bin-6131T_s |
example in SBCL
(sb-ext:posix-environ)
("TERM=dumb" "TERMCAP=" "COLUMNS=139" "INSIDE_EMACS=25.2.1,comint"
"BUNDLE_PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev"
"GEM_PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev:/Users/toni/.rvm/gems/ruby-2.1.6#global"
"GEM_HOME=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev" "LANG=es_ES.UTF-8"
"XPC_FLAGS=0x0" "USER=toni" "XPC_SERVICE_NAME=org.gnu.Emacs.13016"
"DISPLAY=/private/tmp/com.apple.launchd.ljkiChb2wE/org.macosforge.xquartz:0"
"LOGNAME=toni"
"PATH=/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev/bin:/Users/toni/.rvm/gems/ruby-2.1.6#global/bin:/Users/toni/.rvm/rubies/ruby-2.1.6/bin/:/usr/texbin:/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/toni/.rvm/bin"
"SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.KvlUaU8PD5/Listeners"
"Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.e0K30SfWTc/Render"
"SHELL=/bin/bash" "HOME=/Users/toni" "__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x8"
"TMPDIR=/var/folders/zs/t9wnzpqj2bdgjjgjwb8pqxc80000gn/T/"
"SBCL_HOME=/Users/toni/.roswell/impls/x86-64/darwin/sbcl/1.3.16/lib/sbcl"
"ROS_OPTS=((\"program\"\"(:eval\\\"(ros:quicklisp)\\\")\")(\"lispdir\"\"/usr/local/Cellar/roswell/17.4.8.76/etc/roswell/\")(\"verbose\"\"0\")(\"homedir\"\"/Users/toni/.roswell/\")(\"wargv0\"\"/usr/local/bin/ros\")(\"argv0\"\"/usr/local/bin/ros\")(\"quicklisp\"\"/Users/toni/.roswell/lisp/quicklisp/\")(\"impl\"\"sbcl/1.3.16\")(\"dynamic-space-size\"\"3gb\")(\"sbcl.version\"\"1.3.16\")(\"allegro.version\"\"100express\")(\"ccl-bin.version\"\"1.11\")(\"ecl.version\"\"16.1.3\")(\"slime.version\"\"2017.02.27\")(\"sbcl-bin.version\"\"1.2.11\")(\"default.lisp\"\"sbcl\"))")
So for other implementations you mut investigate how to,
Finally exist a good library called OSICAT that:
OSICAT is a lightweight operating system interface for Common Lisp on
Unix-platforms. It is not a POSIX-style API, but rather a simple lispy
accompaniment to the standard ANSI facilities.
so in your case you must use:
(osicat:environment)
(("TERM" . "dumb") ("TERMCAP" . "") ("COLUMNS" . "139") ("INSIDE_EMACS" . "25.2.1,comint") ("BUNDLE_PATH" . "/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev") ("GEM_PATH" . "/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev:/Users/toni/.rvm/gems/ruby-2.1.6#global") ("GEM_HOME" . "/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev") ("LANG" . "es_ES.UTF-8") ("XPC_FLAGS" . "0x0") ("USER" . "toni") ("XPC_SERVICE_NAME" . "org.gnu.Emacs.13016") ("DISPLAY" . "/private/tmp/com.apple.launchd.ljkiChb2wE/org.macosforge.xquartz:0") ("LOGNAME" . "toni") ("PATH" . "/Users/toni/.rvm/gems/ruby-2.1.6#afs-dev/bin:/Users/toni/.rvm/gems/ruby-2.1.6#global/bin:/Users/toni/.rvm/rubies/ruby-2.1.6/bin/:/usr/texbin:/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/toni/.rvm/bin") ("SSH_AUTH_SOCK" . "/private/tmp/com.apple.launchd.KvlUaU8PD5/Listeners") ("Apple_PubSub_Socket_Render" . "/private/tmp/com.apple.launchd.e0K30SfWTc/Render") ("SHELL" . "/bin/bash") ("HOME" . "/Users/toni") ("__CF_USER_TEXT_ENCODING" . "0x1F5:0x0:0x8") ("TMPDIR" . "/var/folders/zs/t9wnzpqj2bdgjjgjwb8pqxc80000gn/T/") ("ROS_OPTS" . "((\"program\"\"(:eval\\\"(ros:quicklisp)\\\")\")(\"lispdir\"\"/usr/local/Cellar/roswell/17.4.8.76/etc/roswell/\")(\"verbose\"\"0\")(\"homedir\"\"/Users/toni/.roswell/\")(\"wargv0\"\"/usr/local/bin/ros\")(\"argv0\"\"/usr/local/bin/ros\")(\"quicklisp\"\"/Users/toni/.roswell/lisp/quicklisp/\")(\"impl\"\"ccl-bin/1.11\")(\"dynamic-space-size\"\"3gb\")(\"sbcl.version\"\"1.3.16\")(\"allegro.version\"\"100express\")(\"ccl-bin.version\"\"1.11\")(\"ecl.version\"\"16.1.3\")(\"slime.version\"\"2017.02.27\")(\"sbcl-bin.version\"\"1.2.11\")(\"default.lisp\"\"ccl-bin\"))"))
SO I hope that this should work

Showing thousand separator in org-mode spreadsheets

Is there a way to configure org-mode spreadsheets to show thousand separators? I would like 1000 to be shown as 1,000.
Here is a solution. First define the function group-number:
(defun group-number (num &optional size char)
"Format NUM as string grouped to SIZE with CHAR."
;; Based on code for `math-group-float' in calc-ext.el
(let* ((size (or size 3))
(char (or char ","))
(str (if (stringp num)
num
(number-to-string num)))
;; omitting any trailing non-digit chars
;; NOTE: Calc supports BASE up to 36 (26 letters and 10 digits ;)
(pt (or (string-match "[^0-9a-zA-Z]" str) (length str))))
(while (> pt size)
(setq str (concat (substring str 0 (- pt size))
char
(substring str (- pt size)))
pt (- pt size)))
str))
from: Emacs Cookbook - put commas in numbers
Next, use it in your formula:
| | | |
|-----------+-------+-------------|
| 2000 | 3100 | 5,100 |
| 11 | 22 | 33 |
| 111221212 | 29996 | 111,251,208 |
| | | 0 |
#+TBLFM: $3='(group-number (+ $1 $2));N
Here we are using the group-number function to format the result of an emacs lisp form - rather than using the calc formula syntax.

Emacs: how to find that at least one windows was vertically split

I don't know, how to write a function like this in elisp:
if(any window was split vertically)
return t;
else
return nil;
true:
|----------| |----------|----------|
| | | | |
| | | | |
|----------| |----------|----------|
false:
|--------| |--------|-------|
| | | | |
| | | | |
|--------| | |-------|
| | | | |
| | | | |
|--------| |--------|-------|
I found, that there is window-list function, that returns a list of all the windows. So, the algorithm should be like this:
(setq windows (window-list))
dolist(windows)
{
if($_->is_vertically_split())
{
return nil;
}
}
return t;
How can I determine, that this window is vertically split? It's height shouldn't be 100%.
Update
Using #lawlist answer I wrote the following, but it doesn't work (always returns nil):
(defun no-window-is-vertically-split ()
(let (windows (window-list)
(result nil))
(dolist (w windows)
(when (or
(window-in-direction 'above w)
(window-in-direction 'below w))
(setq result t)))
result))
(no-window-is-vertically-split)
Is it possible to break the dolist loop and just return the value, when 1-st split window is found?
You can use any of these to test whether there is a window above, below, left or right:
(window-in-direction 'above)
or
(window-in-direction 'below)
or
(window-in-direction 'left)
or
(window-in-direction 'right)
And here is an example using conditions -- just replace [... do something] with your preferred action:
(cond
((window-in-direction 'above)
[... do something])
((window-in-direction 'below)
[... do something])
((window-in-direction 'left)
[... do something])
((window-in-direction 'right)
[... do something]))
To test whether there is only one window, the following is useful:
(one-window-p t)
Here is a test similar to the call of the question, which is based upon the the test being performed from the selected window:
(if
(or
(window-in-direction 'above)
(window-in-direction 'below))
(message "There is either a window above or below the selected window.")
(message "There is are no windows above or below the selected window."))
EDIT (August 1, 2014):  Based on the updated question of the original poster, the following is an example of how to break the dolist loop and throw the result:
(defun no-window-is-vertically-split ()
(catch 'done
(let* (
result
(windows (window-list)))
(dolist (w windows)
(when (or
(window-in-direction 'above w)
(window-in-direction 'below w))
(setq result t)
(throw 'done result))))))
These two functions will detect horizontal and vertical splits:
(defun any-vertical-splits-p ()
"Return t if any windows have been split vertically."
(when (member nil (mapcar #'window-full-height-p (window-list))) t))
(defun any-horizontal-splits-p ()
"Return t if any windows have been split horizontally."
(when (member nil (mapcar #'window-full-width-p (window-list))) t))
I wasn't quite sure I knew what you meant in your diagram. Vertical and horizontal are used here as Emacs uses them with split-window-vertically and split-window-horizontally.

fixed point combinator in lisp

;; compute the max of a list of integers
(define Y
(lambda (w)
((lambda (f)
(f f))
(lambda (f)
(w (lambda (x)
((f f) x)))))))
((Y
(lambda (max)
(lambda (l)
(cond ((null? l) -1)
((> (car l) (max (cdr l))) (car l))
(else (max (cdr l)))))))
'(1 2 3 4 5))
I wish to understand this construction. Can somebody give a clear and simple explanation for this code?
For example, supposing that I forget the formula of Y. How can I remember it , and reproduce it long after I work with it ?
Here's some related answers (by me):
Y combinator discussion in "The Little Schemer"
Unable to get implementation of Y combinator working
In Scheme, how do you use lambda to create a recursive function?
Basically, with Y defined as λr.(λh.h h) (λg.r (λx.(g g) x)), an application Y r reduces as
Y r
(λw.(λh.h h) (λg.w (λx.(g g) x))) r
(λh.h h) (λg.r (λx.(g g) x))
h h
;where
h = (λg.r (λx.(g g) x)) <----\
|
(λg.r (λx.(g g) x)) h |
r (λx.(g g) x) <-------------- | ----------\
;where | |
g = h -----/ |
;so that |
(g g) = (h h) = r (λx.(g g) x) ------/
So r must expect two arguments - first representing the recursive function to be called, and second - an actual argument:
r = λf (λx. ....x.....(f y)...... )
so that (Y r) x reduces as
(r (λx.(g g) x)) x
(r f) x
;where
f = (λx.(g g) x)
f y = (λx.(g g) x) y = (g g) y = (r f) y ; f is "fixed point" of r
The definiton f = (λx.(g g) x) means, when f y is called, (g g) y will be called, at which point g will be self-applied, r "pulled" from inside g and the result of (r f) called with y argument. I.e. any call (f y) in the body of lambda expression resulting from (r f) application, is translated back to (r f) y i.e. invocation of same body with a new argument y.
The important implementational detail is whether it is the same function body, or its copy, but the semantics are the same - we are able to enter the same function body with a new argument value.
The essence of Y combinator is replication through reference and self-application: we refer to the same thing through same name, twice; and thus we arrange for it to receive itself as an argument.
When there's no referencing, as in pure lambda calculus, and parameters receive textual copies of arguments - i.e. reduction is done by textual rewriting - this still works, because same copies get replicated and passed around, being fed as argument to self so it is available on the next iteration, if need be.
But it is much more efficient when shared referencing is available (all uses of same name refer to same thing). Under environment model of evaluation creation of self-referential function is simple as
(let ((fact #f))
(set! fact
(lambda (n) (if (< 2 n) 1
(* n (fact (- n 1))))))
fact)
In fact the definition in your answer is that of applicative-order Y combinator. With normal-order, eta-reduction can be applied without causing infinite looping, to get Ynorm = (λw.(λh.h h) (λg.w (g g))) which is canonically written as
Ynorm = (λf.(λx.f (x x)) (λx.f (x x)))
indeed
Ynorm g
= (λx.g (x x)) (λx.g (x x))
= g ((λx.g (x x)) (λx.g (x x)))

How do I tell if a list contains NILs?

I have the following list:
(X O X O X NIL X NIL O)
If I do (find 'x (X O X O X NIL X NIL O)) it returns X, so I know the list contains X. But If I do (find nil (X O X O X NIL X NIL O)) I get NIL, which is meaningless because I'd get NIL even if my list didn't contain NIL.
How can I tell if my list contains NILs or not?
You can use position
(position NIL '(X O X O X NIL X NIL O))
--> 5
It may not be as processor-efficient as the others, but I'd likely write it pretty much like I say it in English:
(some #'null '(X O X O X NIL X NIL O))
Would something like this work?
(or
(map (lamdba (x)
(eq? x nil))
'(X O X O X NIL X NIL O)))
I don't have CL installed right now, but I think it would work. (or works that way in CL, right? or is there an any function?
EDIT:
Wait a second, nil counts as false, right?
(apply and '(X O X NIL))
;Or
(all '(X O X NIL))
;Whichever works in CL.
NOT is what you're looking for.
Here's an example:
(reduce #'(lambda (a b) (or a b))
(mapcar 'not '(1 2 3 4)))