Lisp redefining functions - lisp

Can someone help understand what is happenning here?
(DEFUN G(L)(+(CAR L)(CADR L)))
(SETQ H`F)(SET H `G)
I want to know what happends when I evaluate (F` (2 3 4 5 6 ))
I've written it in my lisp interpreter but I get the following error:
Undefined function F

Common Lisp has a namespace for values and another namespace for functions.
CL-USER 49 > (DEFUN G(L)(+(CAR L)(CADR L)))
G
CL-USER 50 > (SETQ H 'F)
F
CL-USER 51 > (SET H 'G)
G
CL-USER 52 > F
G
CL-USER 53 > (symbol-value 'F)
G
CL-USER 54 > (symbol-function 'f)
Error: Undefined function F in form (SYMBOL-FUNCTION F).
All you did was setting the value of F, but not the function F.

Related

LISP macro that process variables and data structure inside at runtime

I have LISP written in JavaScript (https://jcubic.github.io/lips/ with online demo where you can try it) and I have macro like this:
(define-macro (globalize symbol)
(let ((obj (--> (. lips 'env) (get symbol))))
`(begin
,#(map (lambda (key)
(print (concat key " " (function? (. obj key))))
(if (function? (. obj key))
(let* ((fname (gensym))
(args (gensym))
(code `(define (,(string->symbol key) . ,args)
(apply (. ,obj ,key) ,args))))
(print code)
code)))
;; native Object.key function call on input object
(array->list (--> Object (keys obj)))))))
In this code I use this:
(let ((obj (--> (. lips 'env) (get symbol))))
and I call this macro using:
(globalize pfs)
to create function for each static method of pfs (which is LightingFS from isomorphic-git where each function return a promise, it's like fs from node).
But it will not work for something like this:
(let ((x pfs))
(globalize x))
because lips.env is global enviroment.
So my question is this how macro should work? Should they only process input data as symbols so they never have access to object before evaluation of lisp code?
How the LISP macro that generate bunch of functions based on variable should look like. For instance in scheme if I have alist in variable and want to generate function for each key that will return a value:
input:
(define input `((foo . 10) (bar . 20)))
output:
(begin
(define (foo) 10)
(define (bar) 20))
Can I write macro that will give such output if I use (macro input)? Or the only option is (macro ((foo . 10) (bar . 20)))?
I can accept generic Scheme or Common LISP answer but please don't post define-syntax and hygienic macros from scheme, My lisp don't have them and will never have.
The problem seems to be that I want to access value at macro expansion time and it need to have the value that in runtime. And second question Is eval in this case the only option?
This works in biwascheme:
(define-macro (macro obj)
(let ((obj (eval obj)))
`(begin
,#(map (lambda (pair)
(let ((name (car pair))
(value (cdr pair)))
`(define (,name) ,value)))
obj))))
(define input `((foo . 10) (bar . 20)))
(macro input)
(foo)
;; ==> 10
(bar)
;; ==> 20
(in my lisp eval don't work like in biwascheme but that's other issue).
but this don't work, because x is not global:
(let ((x '((g . 10)))) (macro x))
Is macro with eval something you would normally do, or should them be avoided? Is there other way to generate bunch of functions based on runtime object.
In Common Lisp: creating and compiling functions at runtime.
CL-USER 20 > (defparameter *input* '((foo . 10) (bar . 20)))
*INPUT*
CL-USER 21 > (defun make-my-functions (input)
(loop for (symbol . number) in input
do (compile symbol `(lambda () ,number))))
MAKE-MY-FUNCTIONS
CL-USER 22 > (make-my-functions *input*)
NIL
CL-USER 23 > (foo)
10
CL-USER 24 > (bar)
20
From a local variable:
CL-USER 25 > (let ((input '((foo2 . 102) (bar3 . 303))))
(make-my-functions input))
NIL
CL-USER 26 > (bar3)
303
With a macro, more clumsy and limited:
CL-USER 37 > (defparameter *input* '((foo1 . 101) (bar2 . 202)))
*INPUT*
CL-USER 38 > (defmacro def-my-functions (input &optional getter)
`(progn
,#(loop for (symbol . number) in (if getter
(funcall getter input)
input)
collect `(defun ,symbol () ,number))))
DEF-MY-FUNCTIONS
CL-USER 39 > (def-my-functions *input* symbol-value)
BAR2
CL-USER 40 > (foo1)
101

How to apply a function repeatedly to get an infinite sequence?

For example,
(require racket/generator)
(define f add1)
(define init 0)
(in-producer (generator () (let loop ([x init]) (yield x) (loop (f x)))))
Is there any better way to do this? I don't quite like generators since they have hidden states.
Streams
Using streams is probably the easiest:
(require racket/stream)
;; X [X -> X] -> [Streamof X]
(define (repeated-fn-stream init f)
(stream-cons init (repeated-fn-stream (f init) f)))
(repeated-fn-stream 0 add1)
Sequences
Alternatively, using sequences and make-do-sequence:
(require racket/sequence)
;; X [X -> X] -> [Sequenceof X]
(define (repeated-fn-sequence init f)
;; A "Pos" is an X that's the result of applying f repeatedly to init
(define (pos->element pos) pos)
(define (next-pos pos) (f pos))
(define init-pos init)
(make-do-sequence
(λ ()
(values pos->element
next-pos
init-pos
#false
#false
#false))))
(repeated-fn-sequence 0 add1)
If you wanted to use sequences, and you wanted to use define-sequence-syntax to make for loops specialize it:
(this is completely unnecessary for "pure" functionality, but it may have different performance characteristics)
(require (for-syntax syntax/parse))
(define-sequence-syntax in-repeated-fn-sequence
(λ () #'repeated-fn-sequence) ; when used as a normal expression
(syntax-parser ; when used *directly* as a for-loop clause
[[(x) (_ init-expr f-expr)]
#'[(x) (:do-in
([(init) init-expr] [(f) f-expr])
#true
([x init])
#true
()
#true
#true
[(f x)])]]))
(for/list ([x (in-repeated-fn-sequence 0 add1)]
[i (in-range 10)])
x)
When using define-sequence-syntax, you should make sure that for everything there is a "single point of truth". Because of that you often see this pattern:
(define-sequence-syntax in-___
(λ () #'in-___/proc) ; when used as a normal expression
(syntax-parser
....everything that defines the actual functionality....))
;; This is completely determined by the sequence-syntax above,
;; that way there is NO duplicated functionality and NO chance for
;; it to get "out of sync".
(define (in-___/proc parameter ...)
(for/stream ([elem (in-___ parameter ...)])
elem))
What that means for this is that once you decide you want to use define-sequence-syntax, you should define the repeated-fn-sequence function in terms of it:
(define (repeated-fn-sequence init f)
(for/stream ([elem (in-repeated-fn-sequence init f)])
elem))
That way if the in-repeated-fn-sequence needs to be changed to fix a bug or switch representations, the function version changes with it automatically.
The best function for this job is an unfold… but unfortunately, Racket does not provide a built-in sequence-unfold or stream-unfold operation. However, there is a stream-unfold operation in the srfi/41 library, which will meet your needs. You can see this in action with the following program:
#lang racket
(require (only-in srfi/41 stream-unfold))
(define nats (stream-unfold identity (const #t) add1 0))
(for/list ([i (in-range 20)] [n nats]) n)
This produces the following output:
'(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
If you don’t want to use srfi/41, you can write stream-unfold yourself in terms of the racket/stream API without too much difficulty, and without any statefulness:
(define (stream-unfold mapper pred? gen base)
(let loop ([base base])
(if (pred? base)
(stream-cons (mapper base) (loop (gen base)))
empty-stream)))

Defining a let macro scope in emacs lisp

In emacs lisp (but answers relating to common lisp are also welcome) I have a library that uses a macro and I want to hijack one of the macro's arguments only when executed in a certain context. Essentially what I want is a macro:
; My macro. This is a sketch of what I want that doesn't work.
(defmacro hijack-f (body)
`(macrolet ((f (x) `(f (+ 1 ,x))))
,#body))
; Defined in the library, I don't want to deal with these
(defmacro f (x) x)
(defun g (x) (f x))
So that
(g 1) ; => 1
(hijack-f (g 1)) ; => 2
(hijack-f (hijack-f (g 1))) ; => 3
EDIT: #melpomene and #reiner-joswig correctly point out that f is expanded in g before hijack-f. As a followup is there a hijack-f such that:
(f 1) ; => 1
(hijack-f (f 1)) ; => 2
(hijack-f (hijack-f (f 1))) ; => 3
As far as I know, what you want is not possible because g does not contain an invocation of f. Instead f runs first and expands to (part of) the definition of g.
That is:
(defun g (x) (f x))
immediately turns into
(defun g (x) x)
Which then defines g as a function (whose value is (lambda (x) x)).
Messing with f at runtime doesn't affect anything because its invocation is long gone by the time you call g.
If you are happy for your f to be a function and not a macro, and to use CL not elisp, then you are after flet and a macro like this:
(defmacro hijack-f (&body body)
`(flet ((f (x)
(f (1+ x))))
,#body))
Given a global defintion of f:
(defun f (x)
x)
Then
> (hijack-f (f 1))
2
> (hijack-f (hijack-f (f 1)))
3
And so on.
(As others have pointed out, you can't hijack code that has already been compiled with a macro like this: you would need to do it by having f cooperate in the hijacking.)

Defining setf for function in closure

If I create a closure like this,
(let ((A (make-array '(10) :initial-element 5)))
(defun h (i)
(aref a i))
(defsetf h (i) (x) `(setf (aref ,a ,i) ,x)))
then, as I expect, (h i) will return the i-th element of a:
(h 1) ;; => 5
(h 2) ;; => 5
Butalthough the setf expansion semes to work and correctly set the i-th element of a, it also produces a warning in SBCL:
(setf (h 1) 10)
; in: SETF (H 1)
; (SETF (AREF #(5 10 5 5 5 5 5 5 5 5) 1) #:G1124)
; --> LET* MULTIPLE-VALUE-BIND LET FUNCALL SB-C::%FUNCALL
; ==>
; ((SETF AREF) #:NEW0 #(5 10 5 5 5 5 5 5 5 5) 1)
;
; caught WARNING:
; Destructive function (SETF AREF) called on constant data.
; See also:
; The ANSI Standard, Special Operator QUOTE
; The ANSI Standard, Section 3.2.2.3
;
; compilation unit finished
; caught 1 WARNING condition
In GCL an error is signalled:
>(setf (h 1) 10)
Error:
Fast links are on: do (si::use-fast-links nil) for debugging
Signalled by LAMBDA-CLOSURE.
Condition in LAMBDA-CLOSURE [or a callee]: INTERNAL-SIMPLE-UNBOUND-VARIABLE: Cell error on A: Unbound variable:
Broken at LIST. Type :H for Help.
1 Return to top level.
In CLISP and ECL, the example works just fine.
I am returning to Common Lisp after writing Scheme for a couple of years, so I may be mixing the two languages, conceptually. I suppose I have triggered behavior that is undefined according to the spec, but I can't see exactly what I did wrong. I would appreciate any help with this!
Your Problem
It is often instructive to try macroexpand:
(macroexpand '(setf (h 2) 7))
==>
(LET* ()
(MULTIPLE-VALUE-BIND (#:G655)
7
(SETF (AREF #(5 5 5 5 5 5 5 5 5 5) 2) #:G655)))
As you can see, your setf call expands into a form which calls setf on a literal array which is a bad idea in general and, in fact, this is precisely what SBCL is warning you about:
Destructive function (SETF AREF) called on constant data.
Note that despite the warning SBCL (and other conformant implementations like CLISP and ECL) will do what you expect them to do.
This is because the literal array is referred to by the local variable which is accessible to the function h.
Solution
I suggest that you use a function instead
(let ((A (make-array '(10) :initial-element 5)))
(defun h (i)
(aref a i))
(defun (setf h) (x i)
(setf (aref a i) x)))

Circular list in Common Lisp

I am working using a visual programming environment for musical composition based on CL . I am trying to create a function that when given say 3 elements (1 2 3) will return 1, 2, 3, 1, 2, 3 etc., one number at the time each time it is evaluated. The book Common Lisp a Gentle Introduction, mentions briefly that it's possible to create circular lists using sharp-equal notation but does not get into details on how to use them.
Keep in mind that I can insert actual Lisp code in the program using a object specifically designed for that.
CL-USER 3 > (defun circular (items)
(setf (cdr (last items)) items)
items)
CIRCULAR
CL-USER 4 > (setf *print-circle* t)
T
CL-USER 5 > (circular (list 1 2 3))
#1=(1 2 3 . #1#)
Example:
CL-USER 16 > (setf c1 (circular (list 1 2 3)))
#1=(1 2 3 . #1#)
CL-USER 17 > (pop c1)
1
CL-USER 18 > (pop c1)
2
CL-USER 19 > (pop c1)
3
CL-USER 20 > (pop c1)
1
also:
CL-USER 6 > '#1=(1 2 3 . #1#)
#1=(1 2 3 . #1#)
With a bit of CLOS added:
(defclass circular ()
((items :initarg :items)))
(defmethod initialize-instance :after ((c circular) &rest initargs)
(setf (slot-value c 'items) (circular (slot-value c 'items))))
(defmethod next-item ((c circular))
(prog1 (first (slot-value c 'items))
(setf (slot-value c 'items)
(rest (slot-value c 'items)))))
CL-USER 7 > (setf circ1 (make-instance 'circular :items (list 1 2 3)))
#<CIRCULAR 40200017CB>
CL-USER 8 > (next-item circ1)
1
CL-USER 9 > (next-item circ1)
2
CL-USER 10 > (next-item circ1)
3
CL-USER 11 > (next-item circ1)
1
CL-USER 12 > (next-item circ1)
2
In Sharpsign Equal-Sign notation, it's written as #0=(1 2 3 . #0#).
Here's a function which creates such a list from the given arguments:
(defun circular (first &rest rest)
(let ((items (cons first rest)))
(setf (cdr (last items)) items)))
Then, calling (circular 1 2 3) will return the circular list you wanted. Just use car and cdr to iterate through the elements ad infinitum.
And if you really want an iterator function that takes no arguments and returns the next item for each call, here's how you might do it:
(defun make-iter (list)
(lambda ()
(pop list)))
First, you want to let the printer know to recognize circular lists instead of trying to print the whole list:
(setf *print-circle* t)
Next, you can create a circular list using the Sharpsign Equal-Sign notation:
(setq x '#1=(1 2 3 . #1#))
Here is an idea worked out for a circular list in Lisp.
;;; Showing structure of the list
;;; (next prev is-end val)
; create items
setf L-0 (L-1 L-3 t "L-0 sentry") ; this will be the sentry item so know where to stop
setf L-1 (L-2 L-0 nil "L-1")
setf L-2 (L-3 L-1 nil "L-2")
setf L-3 (L-0 L-2 nil "L-3")
; how to access L-2 from L-0
eval (first (eval (first L-0)))
; result: (L-3 L-1 NIL "L-2")
I'm not giving defun functions to make adding, removing, and accessing the items. I'm thinking that what I gave is enough to show what you need to do in any functions you define for this kind of circular list. This appeared to me to work in the Listener.