Suppose I have some function which returns a struct:
(struct layer (points lines areas))
(define (build-new-layer height)
...
(layer list-a list-b list-c))
I want to keep track of the last returned result something like:
(define top-side (build-new-layer 0)) ; store the first result
...
(set! top-side (build-new-layer 0.5)) ; throw away the first result and store the new one
However, for that particular code I get the error:
set!: assignment disallowed;
cannot modify a constant
constant: top-side
Please, tell me what would be the right way to do what I want
What language are you using? it seems it's a matter of configuration, because in principle what you're doing should work. Go to the "choose language" window (Ctrl+L in Windows), click on "show details" and see if one of the options of the language currently in use disallows redefinition of variables. Alternatively, try using a different language.
Depending on where exactly you're going to use the stored result (I can't tell from the code in the question), you could pass it around as function parameters, in such a way that using a global variable is no longer necessary. This might be a better idea, relying on global state and mutation (the set! operation) is discouraged in Scheme.
If you always want to keep around the last layer, then you might prefer setting the last-layer every time one is built. Like this.
(define last-layer #f)
(define build-new-layer
(let ((save-layer #f))
(lambda (height)
(let ((new-layer (layer list-a ...)))
(set! last-layer save-layer)
(set! save-layer new-layer)
new-layer))))
Note: if the real problem is the 'constant-ness' of last-layer then build yourself a little abstraction as:
(define-values (last-layer-get last-layer-set!)
(begin
(define last-layer-access
(let ((last-layer #f))
(lambda (type . layer)
(case type
((get) last-layer)
((set) (set! last-layer (car layer)))))))
(values (lambda () (last-layer-access 'get))
(lambda (layer) (last-layer-access 'set layer))))
Related
I am struggling to understand how to read a file line by line with racket, while passing each line to a recursive function.
According to the manual, the idiomatic way of doing this is something like the following example:
(with-input-from-file "manylines.txt"
(lambda ()
(for ([l (in-lines)])
(op l))))
What if my function op is a recursive function that needs to do some complicated operations depending on the line just read from file and also on the history of the recursion?
For example, I could have a function like this:
(define (op l s)
;; l is a string, s is a list
(cond ((predicate? l)
(op (next-line-from-file) (cons (function-yes l) s)))
(else
(op (next-line-from-file) (append (function-no l) s)))))
I am not sure how to use this function within the framework described by the manual.
Here next-line-from-file is a construct I made up to make it clear that I would like to keep reading the file.
I think I could do what I want by introducing side effects, for example:
(with-input-from-file "manylines.txt"
(lambda ()
(let ((s '()))
(for ([l (in-lines)])
(if (predicate? l)
(let ((prefix (function-yes l)))
(set-cdr! s s)
(set-car! s prefix))
(let ((prefix (function-no l)))
(set-cdr! prefix s)
(set-car! s prefix)))))))
I actually did not try to run this code, so I'm not sure it would work.
Anyway I would bet that this common task can be solved without introducing side effects, but how?
Two approaches that Racket supports rather well are to turn the port into something which is essentially a generator of lines, or into a stream. You can then pass these things around as arguments to whatever function you are using in order to successively read lines from the file.
The underlying thing in both of these is that ports are sequences, (in-lines p) returns another sequence which consists of the lines from p, and then you can turn these into generators or streams.
Here's a function which will cat a file (just read its lines in other words) using a generator:
(define (cat/generator f)
(call-with-input-file f
(λ (p)
(let-values ([(more? next) (sequence-generate (in-lines p))])
(let loop ([carry-on? (more?)])
(when carry-on?
(displayln (next))
(loop (more?))))))))
Here call-with-input-file deals with opening the file and calling its second argument with a suitable port. in-lines makes a sequence of lines from the port, and sequence-generate then takes any sequence and returns two thunks: one tells you if the sequence is exhausted, and one returns the next thing in it if it isn't. The remainder of the function just uses these functions to print the lines of the file.
Here's an equivalent function which does it using a stream:
(define (cat/stream f)
(call-with-input-file f
(λ (p)
(let loop ([s (sequence->stream (in-lines p))])
(unless (stream-empty? s)
(displayln (stream-first s))
(loop (stream-rest s)))))))
Here the trick is that sequence->stream returns a stream corresponding to a sequence, and then stream-empty? will tell you if you're at the end of the stream, and if it's not empty, then stream-first returns the first element (conceptually the car) while stream-rest returns a stream of all the other elements.
The second one of these is nicer I think.
One nice thing is that lists are streams so you can write functions which use the stream-* functions, test them on lists, and then use them on any other kind of stream, which means any other kind of sequence, and the functions will never know.
I recently implement something similar, except in my case the predicate depended on the following line, not the preceding one. In any case, I found it simplest to discard in-lines and use read-line recursively. Since the predicate depended on unread input, I used peek-string to look ahead in the input stream.
If you really want to use in-lines, you might like to experiment with sequence-fold:
(sequence-fold your-procedure '() (in-lines))
Notice this uses an accumulator, which you could use to check the previous results from your procedure. However, if you're building a list, you generally want to build it backwards using cons, so the most recent element is at the head of the list and can be accessed in constant time. Once you're done, reverse the list.
I am reading the fix-point of SICP:
#+begin_src emacs-lisp :session sicp :lexical t
(defvar tolerance 0.00001)
(defun fixed-point(f first-guess)
(defun close-enoughp(v1 v2)
(< (abs (- v1 v2)) tolerance))
(defun try(guess) ;;
(let ((next (funcall f guess)))
(if (close-enoughp guess next)
next
(try next))))
(try first-guess))
(fixed-point #'cos 1.0)
#+end_src
#+RESULTS:
: 0.7390822985224024
From the above case, I learned that one nature of while is the abstract concept "try"
#+begin_src ipython :session sicp :results output pySrc/sicp_fixedpoint2.py
import math
def fixed_point(f, guess):
while True:
nex = f(guess)
if abs(guess-nex) < 0.0001:
return nex
else:
guess = nex #local assignment is nature of lambda
print(fixed_point(math.cos, 1))
#+end_src
#+RESULTS:
: 0.7390547907469174
So I could write iteration in python just with the effective functional abstraction thinking.
When reflect on try, more than "try is a while in iteration", what it teach me?
It could be reframed without try, but return return fixed_point(f, nex) directly.
#+begin_src ipython :session sicp :results output :tangle pySrc/sicp_fixedpoint.py
import math
tolerance = 0.00001
def fixed_point(f, guess):
def good_enoughp(a, b):
return abs(a-b) < tolerance
nex = f(guess)
if good_enoughp(guess, nex):
return nex
else:
return fixed_point(f, nex)
print(fixed_point(math.cos, 1))
#+end_src
#+RESULTS:
: 0.7390822985224024
So why SICP introduced try here, I guess efficiency might not be the author's key consideration.
Test with elisp
#+begin_src emacs-lisp :session sicp :lexical t
(defvar tolerance 0.00001)
(defun fixed-point(f guess)
(defun close-enoughp(v1 v2) ;
(< (abs (- v1 v2)) tolerance))
(let ((next (funcall f guess)))
(if (close-enoughp guess next)
next
(fixed-point f next)))
)
;;(trace-function #'fixed-point)
(fixed-point #'cos 1.0)
#+end_src
#+RESULTS:
: 0.7390822985224024
It works as expected.
It seems that return fixed-point f next is a bit cleaner than a inner iteration with try.
What's the consideration of SICP here, what was intended to teach?
It's the opposite: it's cleaner and more efficient with try because it doesn't need to redefine the good-enough-p.
(also, you're not supposed to use recursion in Python).
The version with try is better than the version which calls the top function, fixed-point, because fixed-point contains inner definitions, of the functions good-enough-p and try. A simple-minded compiler would compile it so that on each call it actually makes those definitions anew, again and again, on each call. With try there's no such concern as it is already inside the fixed-point's inner environment where good-enough-p is already defined, and so try can just run.
(correction/clarification: the above treats your code as if it were Scheme, with internal defines instead of the Common Lisp with defuns as you show. SICP is Scheme, after all. In Common Lisp / ELisp there's not even a question -- the internal defuns will always be performed, on each call to the enclosing function, just (re)defining the same functions at the top level over and over again.)
Incidentally, I like your Python loop translation, it is a verbatim translation of the Scheme's tail-recursive loop, one to one.
Your while translation is exactly what a Scheme compiler is supposed to be doing given the first tail-recursive Scheme code in your question. The two are exactly the same, down to the "horrible while True ... with an escape" which, personally, I quite like for its immediacy and clarity. Meaning, I don't need to keep track of which value gets assigned to what variable and which variable gets returned in the end -- instead, a value is just returned, just like it is in Scheme.
The natural way to write something like this in Python is something like this, I think:
tolerance = 0.00001
def fixed_point(f, first_guess):
guess = first_guess
next_guess = f(guess)
def close_enough(a, b):
return (abs(a - b) < tolerance)
while not close_enough(guess, next_guess):
guess = next_guess
next_guess = f(guess)
return next_guess
This:
uses a while loop rather than recursion in the way that is natural in Python;
doesn't use some horrible while True ... with an escape which is just confusing.
(In fact, since function-call in Python is generally very slow, it is probably more natural to open-code the call to close_enough and remove the local function altogether.)
But this is imperative code: it's full of assignment (the first two 'assignments' are really bindings of variables as Python doesn't distinguish the two syntactically, but the later assignments really are assignments). We want to express this in a way which doesn't have assignment. We also want to replace it by something which does not use any looping constructs or expresses those looping constructs in terms of function calls.
We can do this in two ways:
we can treat the top-level function as the thing we call recursively;
we can define some local function through which we recurse.
Which of these we do is really a choice, and in this case it probably makes little difference. However there are often significant advantages to the second approach: in general the top-level function (the function that is in some interface we might be exposing to people) may have all sorts of extra arguments, some of which may have default values and so on, which we really don't want to have to keep passing through the later calls to it; the top-level function may also just not have an appropriate argument signature at all because the iterative steps may be iterating over some set of values which are derived from the arguments to the top-level function.
So, it's generally better to express the iteration in terms of a local function although it may not always be so.
Here is a recursive version in Python which takes the chance to also make the signature of the top-level function sightly richer. Note that this approach would be terrible style in Python since Python does not do anything special with tail calls. The code is also littered with returns because Python is not an expression language (don't believe people who say 'Python is like Lisp': it's not):
default_tolerance = 0.00001
def fixed_point(f, first_guess, tolerance=default_tolerance):
guess = first_guess
next_guess = f(guess)
def close_enough(a, b):
return (abs(a - b) < tolerance)
def step(guess, next_guess):
if close_enough(guess, next_guess):
return next_guess
else:
return step(next_guess, f(next_guess))
return step(first_guess, f(first_guess))
Well, in Scheme this is much more natural: here is the same function written in Scheme (in fact, in Racket):
(define default-tolerance 0.00001)
(define (fixed-point f initial-guess #:tolerance (tolerance default-tolerance))
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess next)
(if (close-enough? guess next)
next
(try next (f next))))
(try initial-guess (f initial-guess)))
The only thing that is annoying about this is that we have to kick-off the iteration after defining try. Well, we could avoid even that with a macro:
(define-syntax-rule (iterate name ((var val) ...) form ...)
(begin
(define (name var ...)
form ...)
(name val ...)))
And now we can write the function as:
(define (fixed-point f initial-guess #:tolerance (tolerance default-tolerance))
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(iterate try ((guess initial-guess) (next (f initial-guess)))
(if (close-enough? guess next)
next
(try next (f next)))))
Well, in fact we don't need to write this iterate macro: it's so useful in Scheme that it already exists as a special version of let called 'named let':
(define (fixed-point f initial-guess #:tolerance (tolerance default-tolerance))
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(let try ((guess initial-guess) (next (f initial-guess)))
(if (close-enough? guess next)
next
(try next (f next)))))
And with any of these versions:
> (fixed-point cos 0)
0.7390822985224023
> (fixed-point cos 0 #:tolerance 0.1)
0.7013687736227565
Finally a meta-comment: I don't understand why you seem to be trying to learn Scheme using Emacs Lisp. The two languages are not alike at all: if you want to learn Scheme, use Scheme: there are probably hundreds of Scheme systems out there, almost all of which are free.
Scheme permits redefinition of top-level symbols, such as fixed-point; even the function f could redefine it! Compilers (and interpreters) need to take this into consideration, and check for a redefinition every call of fixed-point. On the other hand, try is not visible outside the definition of fixed-point, so f cannot redefine it. So, the compiler (or interpreter) can turn this tail recursive function into a loop.
Consider the make-account procedure in SICP.
(define (make-account balance)
(define (withdraw amount)
(if (>= balance amount)
(begin
(set! balance (- balance amount))
balance)
"Insufficient funds"))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (dispatch m)
(cond ((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Unknown request: MAKE-ACCOUNT" m))))
dispatch)
And the example:
(define peter-acc (make-account 100))
(define paul-acc peter-acc)
And the footnote:
The phenomenon of a single computational object being accessed by more
than one name is known as aliasing. The joint bank account situation
illustrates a very simple example of an alias. ... Bugs can
occur in our programs if we forget that a change to an object may
also, as a “side effect,” change a “different” object because the two
“different” objects are actually a single object appearing under
different aliases. These so-called side-effect bugs are so difficult
to locate and to analyze that some people have proposed that
programming languages be designed in such a way as to not allow side
effects or aliasing ..."
In normal situations, I would here people say: "paul-acc refers to peter-acc".
As I understand it, peter-acc and paul-acc are really names that point to one computational object. So they are the same.
I am confused as to how it would be modeled in the environment model of evaluation. For example:
(define (f bank-account) ((bank-account 'deposit) 69))
(define peter-acc (make-account 100))
(define paul-acc peter-acc)
(f paul-acc)
I cannot do environment diagrams because my eyes are destroyed. Here's what I think the interaction should be:
make-account and f have pointers to the global environment.
(define peter-acc (make-account 100)) is evaluated. make-account creates a new environment e1. Enclosing environment is global. The internal procedures withdraw, deposit and dispatch are created and have pointers to e1. Dispatch is returned and is bound to the name peter-acc in the global environment.
(define paul-acc peter-acc) is evaluated. The name peter-acc is found in the global frame. paul-acc is bound to the dispatch procedure object in e1 because that is where peter-acc is pointing to. Therefore, Dispatch in e1 is bound to the names peter-acc and paul-acc in the global environment.
(f paul-acc) is evaluated. A new environment e2 is created by f. Enclosing environment is global. paul-acc is found in global. In e2, banck-account is bound to the dispatch procedure object in e1 because that is where paul-acc is pointing to. Therefore, peter-acc with respect to the global environment, paul-acc with respect to the global environment, and bank-acount with respect to e2 all point to the dispatch procedure in e1.
The body gets executed.
Is this all correct?
The thing that confuses me is when I encounter things like this in SICP exercises, when constructing environment diagrams, I read people on the web saying things like "bank-account refers to paul-acc. Paul-acc refers to peter-acc." Why exactly is the word "refers" used here? Does bank-account with respect to e2 actually point to the name paul-acc and not it's value?
Your points 2 to 5 are correct. In your point 1, f and make-account do not "have" pointers to global environment - they do not need to, by themselves. They are both entries, bindings, in the global environment. Both "refer to", or "point at" simple values, functions in both cases.
bank-account with respect to e2 actually points to the value to which paul-acc points (which is the same value to which peter-acc points, or refers). In Scheme, (define n1 n2) means "set up new binding in the current environment, named n1, and pointing at the value of the expression n2". If n2 happens to be a variable, its value is just what that variable's value is. That's why we're talking about Scheme's evaluation semantics.
A function call (fun arg) is evaluated by finding the value of arg expression, binding the function's parameter to this value, and then evaluating the function's body in the resulting environment:
( (lambda (param) body) arg )
=
(let ( (param arg) )
body)
When using emacs or my android app I run
(defun big (num) (setf num2 5)(little num)))
(defun little (num)(+ num2 num))
Little happily accepts num2 but when I run it in my SBCL repl (with sublimetext3) it does not.
Is this correct?
What is a workaround without creating a global variable for num2?
I could just pass a second argument (little num num2)
But this wont work when I am trying to mapcar little over a list. Because I can only have one argument when mapcaring correct?
Please read §6. Variables from Practical Common Lisp.
Unlike Emacs Lisp, Common Lisp relies on lexical scope by default (Emacs Lisp is dynamic by default). Dynamic scope (i.e. indefinite scope and dynamic extent) is provided by declaring variables special, and by convention, they are written with asterisks around their names (named "earmuffs"), like *standard-output*. You use defparameter or defvar to declare those variables. Since it has a global effect, you should never use them from inside functions; likewise, your usage of setf is not defined in Common Lisp: no variable named num2 was declared previously in the scope; besides, even if it did, using a global/special variable for local variable is bad style.
Dynamic scope
With special variables, you can for example locally rebind the standard output: the new value is only visible while the code is inside the body of the let binding:
(let ((*standard-output* *error-output*))
(print "Stream redirection"))
By default, print writes to the stream bound to *standard-output*; here, the stream is locally bound to the one given by *error-output*. As soon as you escape the let, *standard-output* reverts to its previous value (imagine there is a stack).
Lexical scope
With lexical scope, your code can only access the bindings that are visible in the text surrounding your code (and the global scope), and the extent is indefinite: it is possible to access a binding (sometimes indirectly) even after the code returns from the let:
(let ((closure
(let ((count 0))
(lambda () (print (incf count))))))
(funcall closure)
(funcall closure))
;; prints:
;; 1
;; 2
The lambda expression creates a closure, which captures the variable named count. Every time you call it, it will increase the count variable and print it. If you evaluate the same code another time, you define another closure and create another variable, with the same name.
Mapcar
Because I can only have one argument when mapcaring correct?
Not exactly; the function called by mapcar should be able to accept at least as many elements as the number of lists that are given to it (and it should also not require more mandatory arguments):
(mapcar (lambda (x y) (* x y))
'(1 2 3)
'(0 3 6))
=> (0 6 18)
(mapcar #'list '(1 2) '(a b) '(+ /))
=> ((1 a +) (2 b /))
The function can also be a closure, and can use special variables.
... with a closure
(defun adder (x)
(lambda (y) (+ x y)))
(mapcar (adder 10) '(0 1 2))
=> (10 11 12)
The adder functions takes a number x and returns a closure which accepts a number y and returns (+ x y).
... with a special variable
If you prefer dynamic scope, use earmuffs and give it a meaningful name:
(defparameter *default-offset* 0)
... and define:
(defun offset (x)
(+ x *default-offset*))
You can then mapcar too:
(let ((*default-offset* 20))
(mapcar #'offset '(1 2 3)))
=> (21 22 23)
As said by jkiiski in comments, you can also declare special variables with (declare (special ...)) where you usually put declarations (when entering a let, a defun, ...). You could also use the special operator progv. This can be useful to have "invisible" variables that are only known by a set of functions to exchange information. You rarely need them.
Why won't this piece of code work?
(setf x '(foo bar (baz)))
(labels
((baz () (print "baz here")))
(baz) ;works
(eval (third x))) ;fails with the below message
*** - EVAL: undefined function BAZ
I'm using GNU CLISP.
In Common Lisp, eval evaluates its argument in a null lexical environment, so your lexically bound function baz can't be found.
While the Common Lisp standard doesn't provide a portable way to access the lexical environment and invoke eval with it, your implementation might have this functionality. For example, in CLISP:
cs-user> (setf x '(foo bar (baz)))
(foo bar (baz))
cs-user> (labels ((baz () (print "baz here")))
(eval-env (third x) (the-environment)))
"baz here"
"baz here"
cs-user>
See geocar's answer for other approaches.
Because common lisp doesn't have special functions.
Check the description of EVAL:
Evaluates form in the current dynamic environment and the null lexical environment.
Since the lexical environment is empty, your baz function (defined by labels) isn't accessible. You'd think you could fix this by putting baz in the dynamic environment (you might want something like (declare (special baz)) or (declare (special (function baz))) or something like this) but alas: there's no way to do this.
You could simulate it yourself by creating:
(defvar baz* nil)
(defun baz (&rest args) (apply baz* args))
You then need to dynamically set baz* instead of using labels:
(setf x '(foo bar (baz)))
(let ((baz* (lambda () (print "baz here"))))
(eval (third x)))
The reason why is just some hard bits about optimisation leaking into the spec. Basically, every function-call would need some stubbing unless the compiler could prove that the function would never get defined dynamically swizzleable. That's hard to do efficiently, and it's not something most CL programmers ever did, so the spec-writers simply forbade it.
As you can see, and as with most things in CL, you can easily get it yourself if you need it. However. Given that most CL programmers never do this, you may want to re-examine why you're trying to do things this way.