|
|
 |
 |
 |
 |
Scheme Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
newbie: pls explain use of lambda
Hi all, I originally asked a dull question about how to use the procedure sort. The 'dull' bit was that I was looking for a procedure called less-than? noted in DrScheme Help and didn't realise it was a predicate that I had to define. Nils Holm discretely pointed me in the right direction and, at that time, I failed to notice his use of lambda in the example code he provided: (sort '(3 1 4 2 5) <=) => (1 2 3 4 5) (sort '("world" "hello") string<=?) => ("hello" "world") (sort '(#\o #\o #\f) char<=?) => (#\f #\o #\o) (sort '((2 second) (1 first)) (lambda (x y) (< (car x) (car y)))) => ((1 first) (2 second)) Ok - just learning. Lambda declares a procedure? In his example code, so far as I can tell, the procedure (lambda (x y) (< (car x) (car y))) is a predicate that resolves to #t or #f. But it does not have a name. If I typed that code it returns: #<procedure> If I do this: (define (x y) (+ y 1)) x Then it returns ==> #<procedure:x> - and I'm interpreting this to mean the result is a procedure named x. Which suggests (lambda (x y) (< (car x) (car y))) is an un-named procedure that is used to do ... whatever within a code block. In my tiny world, I've only ever used lambda like this: (define x (lambda (y) (+ y 1))) Help was not particularly helpful here. Based on Nils' code, I can define procedures more or less on the fly (no name specifically required)? How does Scheme resolve this? What are the advantage / disadvantages of using lambda this way? Sorry if this is unclear ... let me know and I will rephrase it. Kindest regards, Mike
"Mike" <mcu87 @bigpond.net.au> wrote: > Hi all, > I originally asked a dull question about how to use the > procedure sort. The 'dull' bit was that I was looking for a > procedure called less-than? noted in DrScheme Help and > didn't realise it was a predicate that I had to define. > Nils Holm discretely pointed me in the right direction and, > at that time, I failed to notice his use of lambda in the > example code he provided: > (sort '(3 1 4 2 5) <=) => (1 2 3 4 5) > (sort '("world" "hello") string<=?) => ("hello" "world") > (sort '(#\o #\o #\f) char<=?) => (#\f #\o #\o) > (sort '((2 second) (1 first)) > (lambda (x y) > (< (car x) (car y)))) => ((1 first) (2 > second)) > Ok - just learning. Lambda declares a procedure? In his > example code, so far as I can tell, the procedure > (lambda (x y) (< (car x) (car y))) is a predicate that > resolves to #t or #f. But it does not have a name. If I > typed that code it returns: #<procedure> > If I do this: > (define (x y) > (+ y 1)) > x > Then it returns ==> #<procedure:x> - and I'm interpreting > this to mean the result is a procedure named x. Which > suggests (lambda (x y) (< (car x) (car y))) is an un-named > procedure that is used to do ... whatever within a code > block. > In my tiny world, I've only ever used lambda like this: > (define x (lambda (y) (+ y 1))) > Help was not particularly helpful here. Based on Nils' > code, I can define procedures more or less on the fly (no > name specifically required)? How does Scheme resolve this? > What are the advantage / disadvantages of using lambda this > way? > Sorry if this is unclear ... let me know and I will rephrase > it. > Kindest regards, > Mike
First of all, welcome to Scheme! I hope you enjoy it as much as the rest of us do! Lambda comes from lambda calculus, and is Scheme's way of creating a function literal. So 3 is to integer as (lambda (x) x) is to function. A lot of other languages have this feature, namely Haskell, ML, Dylan, Mercury, Javascript, ..., well, you get the idea. -Rob Hoelz
>>>>> "Mike" == Mike <mcu87 @bigpond.net.au> writes: Mike> Lambda declares a procedure? Indeed, that's exactly what it does. Mike> In his example code, so far as I can tell, the procedure Mike> (lambda (x y) (< (car x) (car y))) is a predicate that Mike> resolves to #t or #f. Exactly. Mike> But it does not have a name. Exactly -- no more than "4" has a name. Mike> Then it returns ==> #<procedure:x> - and I'm interpreting Mike> this to mean the result is a procedure named x. Which Mike> suggests (lambda (x y) (< (car x) (car y))) is an un-named Mike> procedure that is used to do ... whatever within a code Mike> block. Exactly again. Mike> Help was not particularly helpful here. Probably you read DrScheme's help, which probably doesn't explain lambda, since it's a core thing in Scheme, and the help only describes ways in which DrScheme differs from core scheme. I suggest you take a look at one of the basic Scheme books: The Little Schemer, maybe (which I've never read but hear is good), or How To Design Programs ... Mike> I can define procedures more or less on the fly (no name Mike> specifically required)? Ayup Mike> How does Scheme resolve this? I dunno. It just does :-) Mike> What are the advantage / disadvantages of using lambda this Mike> way? I can't think of any disadvantages, since you're always free to define _named_ procedures, with "define", as you've been doing. The advantage is simply that you don't _have_ to give a procedure a name if you don't want to. -- A DRE voting system is one of the simplest computer applications you could imagine. It just adds by one. -- Brit Williams, emeritus professor of computer science
http://www.scheme.com/tspl3/
Mike <mcu87 @bigpond.net.au> wrote: > In my tiny world, I've only ever used lambda like this: > (define x (lambda (y) (+ y 1))) (define (x y) (+ y 1)) is merely an abbreviation for (define x (lambda (y) (+ y 1))), so in fact you use lambda each time you define a procedure. More on procedures: http://t3x.org/sketchy/vol1/sl06.html -- Nils M Holm <n m h @ t 3 x . o r g> -- http://t3x.org/nmh/
"Rob Hoelz" <h @wisc.edu> wrote in message [...snip...] | First of all, welcome to Scheme! I hope you enjoy it as much as the | rest of us do! | | Lambda comes from lambda calculus, and is Scheme's way of creating a | function literal. So 3 is to integer as (lambda (x) x) is to | function. A lot of other languages have this feature, namely Haskell, | ML, Dylan, Mercury, Javascript, ..., well, you get the idea. | Hi Rob, I really love Scheme - it's a required unit in my studies but (as you might have noticed), I'm trying to wrap my head around it as much as possible. I program in Delphi or rather, thought I was programming. It's exciting to stumble onto something that (a) forces you to think (b) challenges your understanding about problem defining and solution construction and (c) is so much fun to work with that it should be illegal :) Now that I know how to properly exploit lambda, it opens up a slew of new doors. The good folk on this newsgroup have been incredibly patient with me and especially gracious in taking time to help steer me in the right direction. Hopefully, I'll be in a position to do the same too. As an aside, I had heard of Lisp many years ago and (incorrectly) believed it to be an old (read dead) relic from the past. Nothing could be further from the truth. This is what I *should* have done when I first started coding. So thanks for taking time to reply. Kindest regards, Mike
Thanks Eric, I've said it before and it's worth repeating. Sweet! No to see what sort of damage I can do with my new toy. I noticed that you are a professor in computer science. In case you don't hear it often, Scheme is exciting and challenging and so much fun to use and explore. I'm rewiring my head to remove bad habits developed over quite a few years. The fun stuff - it's what happens when you discover a long held belief is wrong and you *know* why and then see what else is waiting to discover. I've never wanted anyone to give me solutions - I've not earned that knowledge. And I'm just cheating myself. Your nudge has opened up a slew of exciting ways that I can craft solutions. Thank you. Kindest regards, Mike "Eric Hanchrow" <off @blarg.net> wrote in message news:878xc15pox.fsf@offby1.atm01.sea.blarg.net... | >>>>> "Mike" == Mike <mcu87@bigpond.net.au> writes: | | Mike> Lambda declares a procedure? | | Indeed, that's exactly what it does. | | Mike> In his example code, so far as I can tell, the procedure | Mike> (lambda (x y) (< (car x) (car y))) is a predicate that | Mike> resolves to #t or #f. | | Exactly. | | Mike> But it does not have a name. | | Exactly -- no more than "4" has a name. | | Mike> Then it returns ==> #<procedure:x> - and I'm interpreting | Mike> this to mean the result is a procedure named x. Which | Mike> suggests (lambda (x y) (< (car x) (car y))) is an un-named | Mike> procedure that is used to do ... whatever within a code | Mike> block. | | Exactly again. | | Mike> Help was not particularly helpful here. | | Probably you read DrScheme's help, which probably doesn't explain | lambda, since it's a core thing in Scheme, and the help only describes | ways in which DrScheme differs from core scheme. | | I suggest you take a look at one of the basic Scheme books: The Little | Schemer, maybe (which I've never read but hear is good), or How To | Design Programs ... | | Mike> I can define procedures more or less on the fly (no name | Mike> specifically required)? | | Ayup | | Mike> How does Scheme resolve this? | | I dunno. It just does :-) | | Mike> What are the advantage / disadvantages of using lambda this | Mike> way? | | I can't think of any disadvantages, since you're always free to define | _named_ procedures, with "define", as you've been doing. | | The advantage is simply that you don't _have_ to give a procedure a | name if you don't want to. | | -- | A DRE voting system is one of the simplest computer | applications you could imagine. It just adds by one. | -- Brit Williams, emeritus professor of computer science
Thanks Marlene, That's a fantastic resource (already book-marked). Brilliant! Kindest regards, Mike "Marlene Miller" <marlenemil@worldnet.att.net> wrote in message news:uPy%h.429254$5j1.224532@bgtnsc04-news.ops.worldnet.att.net... | http://www.scheme.com/tspl3/ | |
Rob Hoelz wrote: > "Mike" <mcu87 @bigpond.net.au> wrote: >> Ok - just learning. Lambda declares a procedure? >> In my tiny world, I've only ever used lambda like this: >> (define x (lambda (y) (+ y 1))) > Lambda comes from lambda calculus, and is Scheme's way of creating a > function literal. So 3 is to integer as (lambda (x) x) is to > function.
I'll expound a little here, Mike, but you definitely must read TSPL. Have you read in R5RS that "functions are first-class objects"? That means that functions (like numbers and all other scheme types) can be passed around, named, used anonymously, etc. Now, a number is "created" using numeric syntax: 4; and a vector is "created" using vector syntax: #(1 #f "foo"). "lambda" is part of the syntax for creating functions: (lambda (n) (+ n 1)). Consider: > (define (inc n) (+ n 1)) > (define x 4) > (inc x) ==> 5 "inc" and "x" are both names for something. "inc" is a function, and "x" is a number. "inc" can be equivalently defined without the shorthand as follows: > (define inc (lambda (n) (+ n 1))) This is _exactly_ the same as the earlier definition. The earlier def is just easier to write. We could create the same result with temporary definitions: > (let ((inc (lambda (n) (+ n 1))) (x 4)) (inc x)) ==> 5 Or we can forgo defining "inc" at all: > (let ((x 4)) ((lambda (n) (+ n 1)) x)) ==> 5 Viola! an anonymous function in action. OK, why do we care? Suppose we have coded up the following as part of solving a problem: > (define (inc-i n i) (+ n i)) > (define x '(1 2 3 4)) > (define (foo q) (let ((bar (lambda (a) (inc-i a q)))) (map bar x))) > (foo 10) ==> '(11 12 13 14) We decide in version 2 that foo can be simplified and we don't want inc-i cluttering our our namespace: > (define x '(1 2 3 4)) > (define (foo q) (map (lambda (n) (+ n q)) x)) > (foo 10) ==> '(11 12 13 14) The lambda inside the map is another anonymous function in action, keeping our namespace clean and our code simple. It is also acting as a closure, but that's the next layer of the onion. Closures are incredibly important -- read about them. Regards, Nate T.
"Mike" wrote > Thanks Marlene, > That's a fantastic resource (already book-marked). > Brilliant! > Kindest regards, > Mike > "Marlene Miller" wrote >| http://www.scheme.com/tspl3/
TSPL is also available in paperback. http://mitpress.mit.edu/catalog/item/default.asp?ttype=2&tid=9946
Thank you Nathan, I apologise for my delay in responding - was playing around with the new toys to see what I could do. I left your post deliberately for reference (will be keeping this). I swear I'm reading / doing as fast as possible :) So much candy in the store, so little time. The TSPL book is on my shopping list, but for the moment I'm working my way through the Little Schemer and about to start the Advanced Schemer. The authors were quite right about repetition which I why I'm over-working different areas - bed the concepts down (if that makes sense). I *think* I have bedded down lambda functions on the fly. I'm revisiting earlier code to see if I can improve it in any way using lambda. It's fun. Using lambda (and map) with a single param is relatively easy. The wheels fall off if I try to use them on procedures requiring multiple params. For example: Suppose I have two lists of strings: search-list and ref-list. I want to return a sorted list of indices in the ref-list where a ref-list item matches any of the items in the search-list. It screams at me that this would be an ideal place to use map but I can't seem to pull it off. Here is 'a' solution - it works but, I'm sure it can be done using map. And the nested procedure, search-helper, might be done using an un-named lambda function however, if it hasn't got a name I can't refer to it. (define (search search-list ref-list ) (define (search-helper item document doc-length) (if (member item document) (cons (- doc-length (length (member item document))) (search-helper item (cdr (member item document)) doc-length)) '())) (if (empty? search-list) '() (append (search-helper (car search-list) ref-list (length ref-list)) (search (cdr search-list) ref-list )))) (search '("a" "b") '("a" "b" "c" "a" "d" "b"));==> (0 3 1 5) On each pass of the recursive loop, the length of the ref-list decreased which means I have to adjust the returned index from (member item document). Am I wrong in thinking that this would be a useful example for map / lambda for the above reason, ie: (cdr (member item document)) results in a deceasing list on successive passes, to search in? The search-helper procedure takes 3 arguments, holding the original length of the ref-list through successive loops. If I was just looking to return the items in the ref-list that match the search-list, I lose their respective index in the original list ("a" "a" "b" "b") tells me I have 4 matching items - but not where they fit in the ref-list which is what I want. How might I have approached it using map and / or lambda? A code example would be great (I can play with it) but I'd appreciate your thoughts too. As in, your reasoning as to why (if it were possible) you decided to do what you did and what was it (about the problem) that indicated a map and / or lambda style solution would be 'better'. What would be your thinking behind the code choices you made? Hope that made some sense. Kindest regards, Mike "Nathan Thern" <nth @yahoo.com> wrote in message news:XHI%h.2$gb6.1@dfw-service2.ext.ray.com... | Rob Hoelz wrote:
| > "Mike" <mcu87@bigpond.net.au> wrote: | >> Ok - just learning. Lambda declares a procedure? | >> | >> In my tiny world, I've only ever used lambda like this: | >> (define x (lambda (y) (+ y 1))) | > | > Lambda comes from lambda calculus, and is Scheme's way of creating a | > function literal. So 3 is to integer as (lambda (x) x) is to | > function. | | I'll expound a little here, Mike, but you definitely must read TSPL. | | Have you read in R5RS that "functions are first-class objects"? That | means that functions (like numbers and all other scheme types) can be | passed around, named, used anonymously, etc. Now, a number is "created" | using numeric syntax: 4; and a vector is "created" using vector syntax: | #(1 #f "foo"). "lambda" is part of the syntax for creating functions: | (lambda (n) (+ n 1)). | | Consider: | > (define (inc n) (+ n 1)) | > (define x 4) | > (inc x) | ==> 5 | | "inc" and "x" are both names for something. "inc" is a function, and "x" | is a number. "inc" can be equivalently defined without the shorthand as | follows: | > (define inc (lambda (n) (+ n 1))) | This is _exactly_ the same as the earlier definition. The earlier def is | just easier to write. | | We could create the same result with temporary definitions: | > (let ((inc (lambda (n) (+ n 1))) (x 4)) (inc x)) | ==> 5 | | Or we can forgo defining "inc" at all: | > (let ((x 4)) ((lambda (n) (+ n 1)) x)) | ==> 5 | Viola! an anonymous function in action. | | OK, why do we care? Suppose we have coded up the following as part of | solving a problem: | > (define (inc-i n i) (+ n i)) | > (define x '(1 2 3 4)) | > (define (foo q) (let ((bar (lambda (a) (inc-i a q)))) (map bar x))) | > (foo 10) | ==> '(11 12 13 14) | | We decide in version 2 that foo can be simplified and we don't want | inc-i cluttering our our namespace: | > (define x '(1 2 3 4)) | > (define (foo q) (map (lambda (n) (+ n q)) x)) | > (foo 10) | ==> '(11 12 13 14) | | The lambda inside the map is another anonymous function in action, | keeping our namespace clean and our code simple. It is also acting as a | closure, but that's the next layer of the onion. Closures are incredibly | important -- read about them. | | Regards, | Nate T.
|
 |
 |
 |
 |
|