A few questions here, regarding letcc that is used in The Seasoned Schemer.
(define (intersect-all sets)
(letcc hop
(letrec
((A (lambda (sets)
(cond
((null? (car sets)) (hop '())
((null? (cdr sets)) (car sets))
(else
(intersect (car sets)
(A (cdr sets)))))))
; definition of intersect removed for brevity
(cond
((null? sets) '())
(else (A sets))))))
I think I understand what letcc achieves, and that is basically something like catch and throw in ruby (and seemingly CL), which basically means a whole block of code can be cut short by calling whatever the named letcc is. This feels like the least "functional" thing I've come across in this short series of books and it makes me feel a bit hesitant to use it, as I want to learn a good functional style. Am I just misunderstanding letcc, or is it not really a functional programming concept and only exists to improve performance? The whole idea that I can be in the middle of some routine and then suddenly get to another point in the code feels a bit wrong... like abusing try/catch in Java for program flow.
letcc doesn't seem to exist in the version of guile (1.8.7) I have installed in OS X. Is there another name for it that I should be looking for in guile?
If I'm misunderstanding letcc by comparing it with try/catch in Java, or catch/throw in ruby (which is not exception handling, just to be clear, for the non-rubyists), how exactly does it work, at the functional level? Can it be expressed in a longer, more complex way, that convinces me it is functional after all?
"Functional" has several meanings, but no popular meaning contradicts continuations in any way. But they can be abused into creating code that is hard to read. They're not tools that can be "abused for program flow" -- they are program flow tools.
Can't help you there. I know that there was semi-recent on continuations in Guile, but I don't know where things stand. It should definitely have call-with-current-continuation, usually also under the more friendly name of call/cc, and let/cc is a simple macro that can be built with call/cc.
I can tell you that in Racket there is a let/cc builtin together with a bunch of others builtins in the same family, and additionally there's a whole library of various control operators (with an extensive list of references.).
Simple uses of let/cc are indeed similar to a catch/throw kind of thing -- more specifically, such continuations are commonly known as "escape continuations" (or sometimes "upward"). This is the kind of use that you have in that code, and that is often used to implement an abort or a return.
But continuations in Scheme are things that can be used in any place. For a very simple example that shows this difference, try this:
(define (foo f) (f 100))
(let/cc k (+ (foo k) "junk") (more junk))
Finally, if you want to read more about continuations, you can see the relevant parts of PLAI, there's also a more brief by-example overview that Matthew Might wrote, and you can see some class notes that I wrote that are based on PLAI, with some examples that were inspired by the latter post.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I've been reading sicp trying to understand scheme, specially macros. I noticed that sicp doesnt talk about macros at all. I read on Paul Graham's site that:
The source code of the Viaweb editor was probably about 20-25% macros. Macros are harder to write than ordinary Lisp functions, and it's considered to be bad style to use them when they're not necessary. So every macro in that code is there because it has to be.
So I desperately wanted to know how to write macros and what to use them for, so I read this site about macros: http://www.willdonnelly.net/blog/scheme-syntax-rules/
But that site just explains how to write a "for" macro. I think Paul Graham talks about CL and the other blog talks about scheme, but they are partly the same. So, wat can be an example of something that cannot be done with ordinary procedures and thus must be done with macros?
EDIT: I have already seen a similar question, but wanted to ask if there was some sort of crazy algorithm that you could do with macros that couldn't possible be done with procedures(other than syntactic sugar as described in that question's answer).
Macros are a tricky subject that I've personally reversed my own opinions on no less than a dozen times, so take everything with a grain of salt.
If you are just getting acquainted with macros, you'll find the most helpful to be those macros that clarify or expedite existing expressions.
One such macro that you may have been exposed to is the anaphoric macro, which remains as popular today as the day Paul Graham coined the term:
(define-syntax (aif x)
(syntax-case x ()
[(src-aif test then else)
(syntax-case (datum->syntax-object (syntax src-aif) '_) ()
[_ (syntax (let ([_ test]) (if (and _ (not (null? _))) then else)))])]))
These macros introduce "anaphora" variables, namely it that you can use in the consequent and alternative clauses of an if statement, e.g:
(aif (+ 2 7)
(format nil "~A does not equal NIL." it)
(format nil "~A does equal NIL." it))
This saves you the hassle of typing a let statement -- which can add up in large projects.
More broadly, transformations that change the structure of a program, dynamically generate "templated" code or otherwise "break" rules (that you hopefully know well enough to break!) are the traditional domain of the macro. I could write on and on about how I've simplified countless projects and assignments with macros -- but I think you'll get the idea.
Learning Scheme-style macros is a little daunting, but I assure you that there are excellent guides to syntax-rules-style macros for the merely eccentric, and as you gain more and more experience with macros, you'll probably come to the conclusion that they are a beautiful idea, worthy of the name "Scheme".
If you happen to use Racket (previously known as PLT Scheme) -- It has excellent documentation on macros, even providing a few neat tricks along the way (I'd also guess most of what is written there can be readily written in another Scheme dialect without issue)
Here is one standard answer (part of which is also covered in SICP - see Exercise 1.6 for example; also search for the keyword "special form" in the text): in a call-by-value language like Scheme, an ordinary procedure (function) must evaluate its argument(s) before the body. Thus, special forms such as if, and, or, for, while, etc. cannot be implemented by ordinary procedures (at least without using thunks like (lambda () body), which are introduced for delaying the evaluation of the body and may incur performance overheads); on the other hand, many of them can be implemented with macros as indeed done in RnRS (see, for instance, the definition of and by define-syntax on page 69).
The simple answer is that you can make new syntax where delaying evaluation is essential for the functionality. Imagine you want a new if that works the same way as if-elseif. In Lisp it would be something that is like cond, but without explicit begin. Example usage is:
(if* (<= 0 x 9) (list x)
(< x 100) (list (quotient x 10) (remainder x 10))
(error "Needs to be below 100"))
It's impossible to implement this as a procedure. We can implement something that works the same by demanding the user to give us thunks and thus the parts will become procedures that can be run instead:
(pif* (lambda () (<= 0 x 9)) (lambda () (list x))
(lambda () (< x 100)) (lambda () (list (quotient x 10) (remainder x 10)))
(lambda () (error "Needs to be below 100")))
Now it's easy implementation:
(define (pif* p c a . rest)
(if (p)
(c)
(if (null? rest)
(a)
(apply pif* a rest))))
This is how JavaScript and almost every other language that doesn't support macros do it. Now if you want to give the user the power of making the first instead of the second you need macros. Your macro can write the first to the second so that your implementation can be a function or you can just change the code to a nested if:
(define-macro if*
(syntax-rules ()
((_ x) (error "wrong use of if*"))
((_ p c a) (if p c a))
((_ p c next ...) (if p c (if* next ...)))))
Or if you want to use the procedure it's even simpler to just wrap each argument in a lambda:
(define-syntax if*
(syntax-rules ()
((_ arg ...) (pif* (lambda () arg) ...)))
The need of macros is to reduce boilerplate and simplify syntax. When you see the same structure you should try to abstract it into a procedure. If that is impossible since the arguments are used in special forms you do it with a macro.
Babel, a ES6 to ES5 transpiler converts JavaSript ES6 syntax to ES5 code. If ES5 had macros it would have been as easy as making compability macros to support ES6. In fact most features of newer versions of the language would have been unnecessary since programmers don't have to wait for a new version of a language to give it new fancy features. Almost nothing of new language features in Algol languages (PHP, Java, JavaScript, Python) would have been necessary if the language had hygenic macro support.
I'm just starting to play with Clojure.
How do I run through a vector of items?
My naive recursive function would have a form like the classic map eg.
(defn map [f xs] (
(if (= xs [])
[]
(cons (f (first xs)) (map f (rest xs))
)
))
The thing is I can't find any examples of this kind of code on the web. I find a lot of examples using built-in sequence traversing functions like for, map and loop. But no-one doing the raw recursive version.
Is that because you SHOULDN'T do this kind of thing in Clojure? (eg. because it uses lower-level Java primitives that don't have tail-call optimisation or something?)?
When you say "run through a vector" this is quite vague; as Clojure is a lisp and thus specializes in sequence analysis and manipulation, the beauty of using this language is that you don't think in terms "run through a vector and then do something with each element," instead you'd more idiomatically say "pull this out of a vector" or "transform this vector into X" or "I want this vector to give me X".
It is because of this type of perspective in lisp languages that you will see so many examples and production code that doesn't just loop/recur through a vector but rather specifically goes after what is wanted in a short, idiomatic way. Using simple functions like reduce map filter for into and others allow you to elegantly move over a sequence such as a vector while simultaneously doing what you want with the contents. In most other languages, this would be at least 2 different parts: the loop, and then the actual logic to do what you want.
You'll often find that if you think about sequences using the more imperative idea you get with languages like C, C++, Java, etc, that your code is about 4x longer (at least) than it would otherwise be if you first thought about your plan in a more functional approach.
Clojure re-uses stack frames only with tail-recurstion and only when you use the explicit recur call. Everything else will be stack consuming. The above map example is not tail recursive because the cons happens after the recursive call so it can't be TCO'd in any language. If you switch it to use the continuation passing style and use an explicit call to recur instead of map then you should be good to go.
I'm new to Clojure and I think my approach to writing code so far is not in line with the "Way of Clojure". At least, I keep writing functions that keep leading to StackOverflow errors with large values. I've learned about using recur which has been a good step forward. But, how to make functions like the one below work for values like 2500000?
(defn fib [i]
(if (>= 2 i)
1
(+ (fib (dec i))
(fib (- i 2)))))
The function is, to my eyes, the "plain" implementation of a Fibonacci generator. I've seen other implementations that are much more optimized, but less obvious in terms of what they do. I.e. when you read the function definition, you don't go "oh, fibonacci".
Any pointers would be greatly appreciated!
You need to have a mental model of how your function works. Let's say that you execute your function yourself, using scraps of paper for each invocation. First scrap, you write (fib 250000), then you see "oh, I need to calculate (fib 249999) and (fib 249998) and finally add them", so you note that and start two new scraps. You can't throw away the first, because it still has things to do for you when you finish the other calculations. You can imagine that this calculation will need a lot of scraps.
Another way is not to start at the top, but at the bottom. How would you do this by hand? You would start with the first numbers, 1, 1, 2, 3, 5, 8 …, and then always add the last two, until you have done it i times. You can even throw away all numbers except the last two at each step, so you can re-use most scraps.
(defn fib [i]
(loop [a 0
b 1
n 1]
(if (>= n i)
b
(recur b
(+ a b)
(inc n)))))
This is also a fairly obvious implementation, but of the how to, not of the what. It always seems quite elegant when you can simply write down a definition and it gets automatically transformed into an efficient calculation, but programming is that transformation. If something gets transformed automatically, then this particular problem has already been solved (often in a more general way).
Thinking "how would I do this step by step on paper" often leads to a good implementaion.
A Fibonacci generator implemented in a "plain" way, as in the definition of the sequence, will always blow your stack up. Neither of two recursive calls to fib are tail recursive, such definition cannot be optimised.
Unfortunately, if you'd like to write an efficient implementation working for big numbers you'll have to accept the fact that mathematical notation doesn't translate to code as cleanly as we'd like it to.
For instance, a non-recursive implementation can be found in clojure.contrib.lazy-seqs. A whole range of various approaches to this problem can be found on Haskell wiki. It shouldn't be difficult to understand with knowledge of basics of functional programming.
;;from "The Pragmatic Programmers Programming Clojure"
(defn fib [] (map first (iterate (fn [[a b]][b (+ a b)])[0N 1N])))
(nth (fib) 2500000)
In the following (Clojure) SO question: my own interpose function as an exercise
The accepted answers says this:
Replace your recursive call with a call to recur because as written it
will hit a stack overflow
(defn foo [stuff]
(dostuff ... )
(foo (rest stuff)))
becomes:
(defn foo [stuff]
(dostuff ...)
(recur (rest stuff)))
to avoid blowing the stack.
It may be a silly question but I'm wondering why the recursive call to foo isn't automatically replaced by recur?
Also, I took another SO example and wrote this ( without using cond on purpose, just to try things out):
(defn is-member [elem ilist]
(if (empty? ilist)
false
(if (= elem (first ilist))
true
(is-member elem (rest ilist)))))
And I was wondering if I should replace the call to is-member with recur (which also seems to work) or not.
Are there cases where you do recurse and specifically should not use recur?
There's pretty much never a reason not to use recur if you have a tail-recursive method, although unless you're in a performance-sensitive area of code it just won't make any difference.
I think the basic argument is that having recur be explicit makes it very clear whether a function is tail-recursive or not; all tail-recursive functions use recur, and all functions that recur are tail-recursive (the compiler will complain if you try to use recur from a non-tail-position.) So it's a bit of an aesthetic decision.
recur also helps distinguish Clojure from languages which will do TCO on all tail calls, like Scheme; Clojure can't do that effectively because its functions are compiled as Java functions and the JVM doesn't support it. By making recur a special case, there's hopefully no inflated expectations.
I don't think there would be any technical reason why the compiler couldn't insert recur for you, if it were designed that way, but maybe someone will correct me.
I asked Rich Hickey that and his reasoning was basically (and I paraphrase)
"make the special cases look special"
he did not see the value in papering over a special case most of the time and leaving people
to wonder why if blows the stack later when something changes and the compiler can't guarantee the optimization. Untimely it was just one of the design decisions made to try and keep the language simple
I was wondering if I should replace the call to is-member with recur
In general, as mquander says, there is no reason to not use recur whenever you can. With small inputs (a few dozen to a few hundred elements) they are the same, but the version without recur will blow up on large inputs (a few thousand elements).
Explicit recursion (i.e. without 'recur') is good for many things, but iterating through long sequences is not one of them.
Are there cases where you specifically should not use recur?
Only when you can't use it, which is when
it is not tail recursive - i.e. it wants to do something with the return value.
the recursion is to a different function.
Some examples:
(defn foo [coll]
(when coll
(println (first coll))
(recur (next coll))) ;; OK: Tail recursive
(defn fie [coll]
(when coll
(cons (first coll)
(fie (next coll))))) ;; Can't use recur: Not tail recursive.
(defn fum
([coll]
(fum coll [])) ;; Can't use recur: Different function.
([coll acc]
(if (empty? coll) acc
(recur (next coll) ;; OK: Tail recursive
(conj acc (first coll))))))
As to why recur isn't inserted automatically when appropriate: I don't know, but at least one positive side-effect is to make actual function calls visually distinct from the non-calls (i.e. recur).
Since this can be the difference between "works" and "blows up with StackOverflowError", I think it's a fair design choice to make it explicit - visible in the code - rather than implicit, where you would have to start second-guessing the compiler when it doesn't work as expected.
I've been learning scheme, and I just realized that I don't really know how to properly comment my functional scheme code. I know how to add a comment of course - you add a ; and put your comment after it. My question is what should I put in my comments, and where should I comment for maximum readability and comprehensability for other programmers reading my code?
Here's a code snippet I wrote. It's a function called display-n. It can be called with any number of arguments and outputs each argument to the screen in the order that they are provided.
(define display-n
(lambda nums
(letrec ((display-n-inner
(lambda (nums)
(display (car nums))
(if (not (equal? (cdr nums) (quote ()))
(display-n-inner (cdr nums))))))
(display-n-inner nums))))
Edit: Improved tabbing and replaced '() with (quote ()) to avoid SO messing up the formatting.
I'm just not sure how/where to add comments to make it more understandable. Some scheme code I've seen just has comments at the top, which is great if you want to use the code, but not helpful if you want to understand/modify it.
Also - how should I comment macros?
The common style for Lisp comments is
Four semicolons for commentary on a whole subsection of a file.
Three semicolons for introducing a single procedure.
Two semicolons for a description of the expression/procedure definition on the following line.
One semicolon for an endline comment.
Procedure overview comments should probably follow the style of RnRS documens, so to just add comments to your procedure as-is, would look something like
;;; Procedure: display-n NUM ...
;; Output each argument to the screen in the order they are provided.
(define
display-n (lambda nums
(letrec ((display-n-inner (lambda (nums)
(display (car nums))
(if (not (equal? (cdr nums) '()))
(display-n-inner (cdr nums))))))
(display-n-inner nums))))
N.B. I don't use three semicolons for the whole procedure description, since it screws up fill-paragraph in Emacs.
Now about the code, I would ditch the whole define-variable-as-a-lambda thing. Yes, I get that this is the "purest" way to define a function, and it makes for a nice consistency with defining procedures are the results of LETs and other procedures, but there's a reason for syntactic sugar, and it's to make things more readable. Same for the LETREC—just use an internal DEFINE, which is the same thing but more readable.
It's not a huge deal that DISPLAY-N-INNER's parameter is called NUMS, since the procedure's so short and DISPLAY-N just hands its NUMS straight to it anyways. "DISPLAY-N-INNER" is sort of a lame name, though. You would give it something with more semantic meaning, or give it a simple name like "ITER" or "LOOP".
Now about the logic of the procedure. First, (equal? (cdr nums) '()) is silly, and is better as (null? (cdr nums)). Actually, when you are operating over an entire list, it's best to make the base case a test of whether the list itself, and not its CDR, is empty. This way the procedure won't error if you pass it no arguments (unless you want it to do that, but I think it makes more sense for DISPLAY-N to do nothing if it gets nothing). Furthermore, you should test whether to stop the procedure, not whether to continue:
(define (display-n . nums)
(define (iter nums)
(if (null? nums)
#t ; It doesn't matter what it returns.
(begin (display (car nums))
(iter (cdr nums)))))
(iter nums))
But for all that, I would say the the procedure itself is not the best way to accomplish the task it does, since it is too concerned with the details of traversing a list. Instead you would use the more abstract FOR-EACH method to do the work.
(define (display-n . nums)
(for-each display nums))
This way, instead of a reader of the procedure getting mired in the details of CARs and CDRs, he can just understand that FOR-EACH will DISPLAY each element of NUMS.
Some random notes:
Traditionally, Scheme and Lisp code has used ;;; for toplevel comments, ;; for comments in the code, and ; for comments on the same line as the code they're commenting on. Emacs has support for this, treating each of these a little differently. But especially on the Scheme side this is no longer as popular as it was, but the difference between ;; and ; is still common.
Most modern Schemes have adopted new kinds of comments: theres:
#|...|# for a block comment -- useful for long pieces of text that comment on the whole file.
#;<expr> is a comment that makes the implementation ignore the expression, which is useful for debugging.
As for the actual content of what to write, that's not different than any other language, except that with a more functional approach you usually have more choices on how to lay out your code. It also makes it more convenient to write smaller functions that are combined into larger pieces of functionality -- and this changes the documentation style too, since many such small functions will be "self documenting" (in that they're easy to read and very obvious in how they're working).
I hate to sound like a broken record, but I still think that you should spend some time with HtDP. One thing that it encourages in its design recipe is to write examples first, then the documentation, and then expand that to actual code. Furthermore, this recipe leaves you with code that has a very standard set of comments: the input/output types, a purpose statement, some documentation about how the function is implemented when necessary, and the examples can be considered as another kind of documentation (which would turn to commented code in "real" code). (There are other books that take a similar position wrt documentation.)
Finally, documenting macros is not different than documenting any other code. The only thing that can be very different i what's written in the comments: instead of describing what some function is doing, you tend to describe what code it expands too, so the comments are also more on the meta level. A common approach to macros is to to minimal work inside the macro -- just what's needed at that level (eg, wrap expressions in (lambda () ...)), and leave the actual implementation to a function. This helps in documenting too, since the two related pieces will have comments on how the macro expands and how it runs, independently.
I follow an approach similar to what's posted here:
http://www.cc.gatech.edu/computing/classes/cs2360/ghall/style/commenting.html
Note: this is for Common Lisp.
Specifically:
" Four Semicolons(;;;;)
...denote a sub heading in the file...
Three Semicolons(;;;)
...denote a description of the succeeding function, macro, or
variable definition...
[I usually just most of the description into the "docstring"
of the function or variable.]
Two Semicolons(;;)
...denote a description of the succeeding expression...
One Semicolon(;)
...denotes an in-line comment that explains a particular element
of the expression on that line... Brevity is important for
inline comments"
I think a great place to start would be to put your one-sentence description of what the function does
It can be called with any number of arguments and outputs each argument to the screen in the order that they are provided.
as a comment at the beginning.
I'm not particularly conversant in scheme, so I can't comment (:-) on whether additional line-by-line comments explaining the mechanics of how the function achieves that result would be expected according to normal scheme style (but I suspect not).