JSCL - why this mysterious error? - lisp

http://learnlispthehardway.org/try-lisp/
CL-USER> (defun saynextof ( a b c )(write a))
SAYNEXTOF
CL-USER> (saynextof "fred" "jim" "shiela")
ERROR[!]: too few arguments
(For the benefit of this form validation: This does completely describe the problem.)

JSCL requires (differently from the standard) more than one parameter in the write function, so this is the reason of the error.
If you use print instead, the error does not appear.

It seems that the error is thrown by the write function:
CL-USER> (write "foo")
ERROR[!]: too few arguments
CL-USER>
I just downloaded the latest version of JSCL from GitHub and compiled it. With that version, the error does not occur. The commit messages for JSCL's print.lisp suggest that there used to be a problem in the implementation of write which could cause "too few arguments" errors:
Author: David Vazquez <davazp#gmail.com>
Date: Mon Jan 4 19:23:28 2016 +0100
Fix the write function
It was using write-aux with too few arguments.

Related

How to declare a function before its definition in common lisp?

I will get an undefined function warning about f2 in SBCL with following code sample.
Is it possible that I can declare f2 first, like in C, to avoid the warning.
I Googled, without any clue.
(defun f ()
(print (f2)))
(defun f2 ()
(print "f2"))
If you use the function before you define it in a single compilation unit, e.g., the same file, then the compiler will not complain about the undefined function (plain load still may, so compile your code first!)
Otherwise, you can declaim ftype:
(declaim (ftype (function () t) f2)
meaning that f2 accepts no arguments and returns a single value of type t.
However, it makes much more sense to compile the file where you use the function while the definition is already loaded. You can (and should!) use asdf as a Lisp-specific make(1): specifying dependencies so that the compiler has the definitions of all the functions while it compiles their users.
If the functions are in the same file, a compiler won't give a warning.
Example SBCL:
bash-3.2$ sbcl
This is SBCL 1.3.10, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (compile-file "/tmp/order.lisp")
; compiling file "/private/tmp/order.lisp" (written 28 NOV 2016 12:14:37 PM):
; compiling (DEFUN F ...)
; compiling (DEFUN F2 ...)
; /tmp/order.fasl written
; compilation finished in 0:00:00.178
#P"/private/tmp/order.fasl"
NIL
NIL
* (load *)
T
*
You do not have to put functions into the same file in Common Lisp for them to be in the same compilation unit.
Doing this is an anti-pattern; large programs are, of course, constructed from modules, most of which call functions that are in another module. You cannot roll an entire program into a single physical module to avoid a warning about this.
Lisp has a mechanism by which a cluster of compiles is regarded as a single compilation unit: the with-compilation-unit macro:
(with-compilation-unit
(compile-file "file-f")
(compile-file "file-f2"))
If you use the ASDF build system, I seem to recall it does the with-compilation-unit under the hood for you, around all of the files of a system.
This approach will help eliminate those warnings which are deferred. That is to say, if the implementation warns about undefined identifiers, but defers doing so until the end of the compilation unit, then if you use this macro, the deferral is extended until the end of the total compilation unit spanning multiple files.
When warnings about undefined identifiers are deferred, the purpose is to eliminate those warnings. If the definition of a previously undefined function appears before the end of a translation unit, the warning can be suppressed. This macro allows a definition in one file to suppress a deferred warning in another file.
If an implementation doesn't defer warnings, then the macro will not help.
Just change the order of your defun's. First, define f2 and than f.

Lisp complaining with invalid function

I write these code and compile withnewlisp. I wrote these code:
(defun getdone ()(format t "we have a IDE for cLisp"))
getdone()
and the error message
ERR: invalid function : (defun getdone () (format t "we have a IDE for cLisp"))
====================
I finally realized that it is syntax error because newlisp's grammar is different from clisp's grammar. Now my code is runing well:
(define (getdone) (format "we have a IDE for cLisp"))
(getdone)
I don't know what is the t in format t used for ?
The function call should be
(getdone)
not getdone().
If you're using newLISP, don't use
defun
use
define
to define all your functions.
if you're not using newLISP, your question's tags are wrong.

Clisp REPL error output: how to find line number in file where error occurred?

I'm working through Land of Lisp, using CLisp, writing the code in Vim with Slimv, then alt-tabbing to another terminal window and loading the file into the REPL with (load 'file.lisp), then running the programs at the REPL.
When I get an error in the REPL, is there any way to ascertain what line in file.lisp the error occurred on? I don't see line numbers mentioned explicitly in the REPL error output, is there any other way?
I found this similar question, but the only answer says to use something other than Clisp like sbcl, allegro, etc.:
How can I improve clisp error messages?
Thanks!
Simple answer: Just compile the code instead of loading it into the REPL: clisp -c file.lisp. Compiler error/warnings show the line numbers. Debug it that way, then load into the REPL. Good enough for now.
If you just want to know what function it occurred in, you can use ":bt" at the REPL prompt when an error happens. It'll print out a GDB-like stacktrace that you can use to figure out which function the error happened at.
The load function in clisp has an :echo option, see the implementation notes. When you use this option your files gets echoed to the output. Hence when an error occurs you can see the corresponding code. For your case the expression would be:
(load 'file.lisp :echo t)
Some extra options may be useful, such as :verbose and :print, in which case the expression would be:
(load 'file.lisp :verbose t :print t :echo t)

Getting command line arguments in Common Lisp

How can I get the command line arguments in (specifically in GNU, if there are any differences) Common Lisp?
http://cl-cookbook.sourceforge.net/os.html provides some insight
(defun my-command-line ()
(or
#+CLISP *args*
#+SBCL *posix-argv*
#+LISPWORKS system:*line-arguments-list*
#+CMU extensions:*command-line-words*
nil))
is what you are looking for, I think.
I'm assuming that you are scripting with CLisp. You can create a file containing
#! /usr/local/bin/clisp
(format t "~&~S~&" *args*)
Make it executable by running
$ chmod 755 <filename>
Running it gives
$ ./<filename>
NIL
$ ./<filename> a b c
("a" "b" "c")
$ ./<filename> "a b c" 1 2 3
("a b c" "1" "2" "3")
Are you talking about Clisp or GCL? Seems like in GCL the command line arguments get passed in si::*command-args*.
A portable way is uiop:command-line-arguments (available in ASDF3, shipped by default in all major implementations).
Libraries-wise, there is the mentioned Clon library that abstracts mechanisms for each implementation, and now also the simpler unix-opts, and a tutorial on the Cookbook.
(ql:quickload "unix-opts")
(opts:define-opts
(:name :help
:description "print this help text"
:short #\h
:long "help")
(:name :nb
:description "here we want a number argument"
:short #\n
:long "nb"
:arg-parser #'parse-integer) ;; <- takes an argument
(:name :info
:description "info"
:short #\i
:long "info"))
Then actual parsing is done with (opts:get-opts), which returns two values: the options, and the remaining free arguments.
In SBCL,we can use sb-ext:*posix-argv* to get the argv from a Common Lisp script. sb-ext:*posix-argv* is a list holding all the arguments, the first member of the list is the script filename.
As seen in https://stackoverflow.com/a/1021843/31615, each implementation has its own mechanism. The usual way to deal with this is to use a wrapper library that presents a unified interface to you.
Such a library can provide further assistance in not only reading things in, but also converting them and giving helpful output to the user. A quite complete package is CLON (not to be confused with CLON or CLON, sorry), the Command Line Options Nuker, which also brings extensive documentation. There are others, though, should your needs be more lightweight, for example, command-line-arguments and apply-argv.
The packages in quicklisp for these are named net.didierverna.clon, command-line-arguments, and apply-argv, respectively.

AllegroServe on SBCL 1.0.28 failing with `accept invalid keyword argument: :AUTO-CLOSE`

New version of SBCL 1.0.28 running on debian breaks AllegroServe 1.2.47 on incoming connection with following error:
aserve-accept-6: 05/26/09 - 21:11:01 - accept: error 0 on accept invalid
keyword argument: :AUTO-CLOSE (valid keys are
:INPUT, :OUTPUT, :ELEMENT-TYPE, :EXTERNAL-FORMAT,
:BUFFERING, :TIMEOUT).
Portable AllegroServe page does make a mention of this problem. However, no google searches turn up anything of use for this problem.
Any ideas as to how to move forward with this problem, or alternatively, links pointing to places where this has been dealt with?
After some mucking around, I've come up with the following solution:
In my source files, after I declare my package, compile/load the appropriate modules but before I declare anything in my package, I added the following code:
(defmethod sb-bsd-sockets:socket-make-stream ((socket sb-bsd-sockets:socket)
&key input output
(element-type 'character)
(buffering :full)
(external-format :default)
timeout
(auto-close t))
"Default method for SOCKET objects. An ELEMENT-TYPE of :DEFAULT
will construct a bivalent stream. Acceptable values for BUFFERING
are :FULL, :LINE and :NONE. Streams will have no TIMEOUT
by default.
The stream for SOCKET will be cached, and a second invocation of this
method will return the same stream. This may lead to oddities if this
function is invoked with inconsistent arguments \(e.g., one might request
an input stream and get an output stream in response\)."
(let ((stream
(and (slot-boundp socket 'stream) (slot-value socket 'stream))))
(unless stream
(setf stream (sb-sys:make-fd-stream
(sb-bsd-sockets:socket-file-descriptor socket)
:name "a socket"
:dual-channel-p t
:input input
:output output
:element-type element-type
:buffering buffering
:external-format external-format
:timeout timeout
:auto-close auto-close)))
(setf (slot-value socket 'stream) stream)
(sb-ext:cancel-finalization socket)
stream))
(It's basically a lift from what is in the sb-bsd-sockets/socket.lisp with the auto-close key added to the argument list)
This way I avoid modifying or patching system files, and basically hook into the sb-bsd-sockets package directly.
So far, it seems to be working as it should. Basic testing via successive calls to (room) shows me that there's no obvious memory leaks, and the performance is as expected.
Please feel free to comment on this kludge, and if you think it might affect the stability of my system in unexpected ways.