In Racket, if I invoke `lambda` with multiple body arguments, what happens? - functional-programming

The Racket Docs state that the lambda function can be invoked with multiple arguments after the body argument, e.g.:
((lambda () (display "foo") (display "bar")))
prints foobar.
How exactly does this work? I didn't find any explanation in the racket documentation. Did I miss something?

Procedure bodies have an implicit begin. Thus
(lambda ()
(foo)
(bar))
is treated as if the same as
(lambda ()
(begin
(foo)
(bar)))
See Sequencing in the Racket guide for more details.

Related

Why is Racket evaluating both of these functions in one case, but not the other?

Defining the function my-if to use cond internally results in different behavior than using cond directly.
Using cond, the DrRacket interpreter only prints the string for the first displayln.
Code:
(cond
(#t (displayln "Cond: should run"))
(else (displayln "Cond: shouldn't run")))
Output:
Cond: should run
Using my-if, the DrRacket interpreter prints both of the strings, despite seeming (at least to me) that it should expand to the same code.
Code:
(define (my-if condition statement-if statement-else)
(cond (condition statement-if)
(else statement-else)))
(my-if
#t
(displayln "My-If: should run")
(displayln "My-If: shouldn't run"))
Output:
My-If: should run
My-If: shouldn't run
I assumed that the function created by define would expand to the same code as the cond, but given that it has a different result, I assume it didn't.
Given that the 2 versions of the code have different results, my guess is something related to eager/lazy evaluation or cond being a macro in and of itself.
Function application in Racket is evaluated in the following way:
evaluate the function
evaluate the arguments
apply the function to the arguments
Since you're writing (my-if #t (displayln "should") (displayln "shouldn't")), each of the arguments (including both displaylns) are evaluated first.
This is why you can't define conditionals as a function. What you're really looking for is Racket's macro system. You can then define my-if as a macro in the following way:
#lang racket
(define-syntax-rule (my-if c t e)
(cond
[c t]
[else e]))
(my-if #t (displayln "should run") (displayln "shouldn't run"))
Note that unlike function application, which evaluates the arguments first, a macro is actually expanded syntactically (in Racket, also hygenically).

How to inline functions in Common Lisp

Could someone show me how to inline a function in Common Lisp?
I have a lot of small functions which are called all the time so it would be good to save the cost of these function calls.
For example, how would you inline the "standalone" function inside the "caller" function?
(defun standalone ()
(* 2 5))
(defun caller ()
(standalone))
(declaim (inline standalone))
(defun standalone ()
(* 2 5))
(defun caller ()
(standalone))
Documentation is here.
(But keep in mind that defining a function that always returns the numeric literal 10 doesn't make much sense...)
See the Cookbook: https://lispcookbook.github.io/cl-cookbook/performance.html#code-inline
The declaration inline replaces function calls with function body, if the compiler supports it. It will save the cost of function calls but will potentially increase the code size. The best situation to use inline might be those small but frequently used functions. The following snippets show how to encourage and prohibit code inline.
;; The globally defined function DISPATCH should be open-coded,
;; if the implementation supports inlining, unless a NOTINLINE
;; declaration overrides this effect.
(declaim (inline dispatch))
(defun dispatch (x) (funcall (get (car x) 'dispatch) x))
;; Here is an example where inlining would be encouraged.
;; Because function DISPATCH was defined as INLINE, the code
;; inlining will be encouraged by default.
(defun use-dispatch-inline-by-default ()
(dispatch (read-command)))
;; Here is an example where inlining would be prohibited.
;; The NOTINLINE here only affects this function.
(defun use-dispatch-with-declare-notinline ()
(declare (notinline dispatch))
(dispatch (read-command)))
;; Here is an example where inlining would be prohibited.
;; The NOTINLINE here affects all following code.
(declaim (notinline dispatch))
(defun use-dispatch-with-declaim-noinline ()
(dispatch (read-command)))
;; Inlining would be encouraged becuase you specified it.
;; The INLINE here only affects this function.
(defun use-dispatch-with-inline ()
(declare (inline dispatch))
(dispatch (read-command)))
Some implementations like the Allegro CL compiler ignore inline declarations.
Compiler macros as created by define-compiler-macro (different from defmacro!) can be also used instead to inline code.

HANDLER-CASE alternative which is not a macro

So consider the following code:
(define-condition some-condition (error) nil)
(defmethod print-object ((obj some-condition) stream)
(format stream "HELLO THERE"))
(defmacro error-report-test-aux (fn-to-cause-error error-type-to-catch fn-to-handle-error expected-message)
`(let ((result-message
(handler-case (funcall ,fn-to-cause-error)
(,error-type-to-catch (e) (funcall ,fn-to-handle-error e)))))
(assert (string= result-message
,expected-message))
t))
I can use it like so:
(error-report-test-aux (lambda () (error 'some-condition))
some-condition
#'princ-to-string
"HELLO THERE")
But I wanted to make error-report-test-aux a function instead of macro, so that i can pass to it a type of condition within a variable.
To simply write defun instead of defmacro and remove backquote and commas doesn't work because handler-case is macro and it doesn't evaluate error-type-to-catch.
My question is: Is there something like handler-case that would evaluate it's arguments (specifically condition type argument)?
Yes and no :-)
No to your exact question
There is no standard function that would do what you want because catching errors requires establishing bindings and one usually want to bind constant symbols (like in let/let*) because it is easier to optimize.
You might consider creating a "universal" handler using handler-bind and then declining to handle "uninteresting" conditions (as suggested by #jkiiski in comments), but I am not sure if that fits your exact requirements (untested!):
(defun error-report-test-aux (fn-to-cause-error error-type-to-catch expected-message)
(catch 'trap
(handler-bind ((error
(lambda (condition)
(when (typep condition error-type-to-catch)
(throw 'trap (string= (princ-to-string condition)
expected-message))))))
(funcall fn-to-cause-error))))
Yes, implementation-specific
IF your implementation implements handler-case/handler-bind by binding an internal global variable, you can use progv to bind it yourself and thus implement your error-report-test-aux as a function.
This is probably not the best idea (your code becomes wedded to a specific implementation).
Yes, kinda
You can use the fact that some-condition names a CLOS class and use generic functions instead of the macro.

Intercept and modify user input in Common Lisp

I defined an evaluator in common lisp that can simply be called like:
(repl)
From then on, the repl can interpret function calls like (.cos arg) that are otherwise unknown to lisp.
Ofcourse, to use it, one has to call (repl) first, or lisp doesn't know what .cos is.
I would like to be able to simply call (.cos 90) though, and have it run in the repl. Is there anyway to use lisp's reflection to intercept all user input and call another function before it?
Thanks!
The better way would be to make my-eval, then you can do
(defun my-cos (arg)
(my-eval (list '.cos arg)))
repl would be something like
(defun my-repl ()
(my-eval '((lambda (ev)
(ev ev))
(lambda (ev)
(print (eval (read)))
(ev ev)))))
I assume you have print, eval and read defined in your evaluators null environment.

In Common Lisp, how to test if variable is special?

I thought I would be able to find this through Google, SO, or the books I'm reading, but it is proving elusive.
In the implementation I'm learning with, I can do the following at the top-level:
(defvar *foo* 4)
(set 'bar 3)
If I then call (describe '*foo*) and (describe 'bar), I get a description saying that *foo* is special and bar is non-special (among other details).
Is there a function that takes a symbol variable as an argument and returns true or false if it is special? If so, is describe probably implemented in part by calling it?
Context: I'm learning Common Lisp, but at work I have a system with a dialect of Lisp similar to Common Lisp, but the describe function is unimplemented. There's sort of an XY thing going on here, but I'm also trying to grok Lisp and CL.
Many Common Lisp implementations provide the function variable-information in some system dependent package.
Here in SBCL:
* (require :sb-cltl2)
NIL
* (sb-cltl2:variable-information '*standard-output*)
:SPECIAL
NIL
((TYPE . STREAM))
This function was proposed as part of some other functionality to be included into ANSI CL, but didn't make it into the standard. Still many implementations have it. For documentation see: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node102.html
A non-special variable's environment will be captured when you create a closure over it:
(let ((x 1))
(let ((f (lambda () x)))
(let ((x 2))
(eql 2 (funcall f)))))
;;=> NIL
A special variable's lexical environment will not:
(defvar *x*) ; *x* is special
(let ((*x* 1))
(let ((f (lambda () *x*)))
(let ((*x* 2))
(eql 2 (funcall f)))))
;;=> T
Using this approach, you could easily define a macro that will expand to code like the previous that will let you determine whether a symbol is globally proclaimed special:
(defmacro specialp (symbol)
(let ((f (gensym "FUNC-")))
`(let ((,symbol 1))
(let ((,f (lambda () ,symbol)))
(let ((,symbol 2))
(eql 2 (funcall ,f)))))))
(specialp x) ;=> NIL
(specialp *x*) ;=> T
Note that this isn't a function, it's a macro. That means that the macro function for specialp is getting called with the symbols X and *X*. This is important, because we have to construct code that uses these symbols. You can't do this with a function, because there'd be no (portable) way to take a symbol and create a lexical environment that has a lexical variable with that name and a lambda function that refers to it.
This also has some risks if you try to use it with certain symbols. For instance, in SBCL, if you try to bind, e.g., *standard-output* to something that isn't a stream or a stream designator, you'll get an error:
CL-USER> (specialp *standard-output*)
; in: SPECIALP *STANDARD-OUTPUT*
; (LET ((*STANDARD-OUTPUT* 1))
; (LET ((#:FUNC-1038 (LAMBDA # *STANDARD-OUTPUT*)))
; (LET ((*STANDARD-OUTPUT* 2))
; (EQL 2 (FUNCALL #:FUNC-1038)))))
;
; caught WARNING:
; Constant 1 conflicts with its asserted type STREAM.
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
Defining globals with set or setq is not supported. There are 2 common ways to define globals:
(defparameter *par* 20) ; notice the earmuffs in the name!
(defvar *var* 30) ; notice the earmuffs in the name!
All global variables are special. Lexically scoped variables (not special) are not possible to get described. E.g.
(let ((x 10))
(describe 'x)) ; ==> X is the symbol X
It describes not the lexical variable but the symbol representation. It really doesn't matter since you probably never need to know in run time since you know this when you're writing if it's a bound lexical variable or global special by conforming to the earmuffs naming convention for global variables.
I believe the only way to get this information at run time* is by either using an extension to CL, as Rainer noted, or to use eval.
(defun specialp (x)
(or (boundp x)
(eval `(let (,x)
(declare (ignorable ,x))
(boundp ',x)))))
(Defect warning: If the variable is unbound but declared to be a type incompatible with nil, this could raise an error. Thanks Joshua for pointing it out in his answer.)
* The macro approach determines which symbol it is checking at macro expansion time, and whether that symbol is lexical or special at compile time. That's fine for checking the status of a variable at the repl. If you wanted to e.g. print all of the special variables exported by a package, though, you would find that to use the macro version you would end up having to use eval at the call site:
(loop for s being the external-symbols of :cl-ppcre
when (eval `(specialp-macro ,s)) do (print s))

Resources