(define (thunk) (lambda (x) x)) should be a compile error?

DoneSubmitted by Joshua Branson.
Details
4 participants
  • Joshua Branson
  • Ricardo Wurmus
  • Stefan Israelsson Tampe
  • tomas
Owner
unassigned
Severity
normal
J
J
Joshua Branson wrote on 21 Jan 03:04 +0100
(define (thunk) (lambda (x) x)) should be a compile error?
(address . bug-guile@gnu.org)
87h7nb3v0g.fsf@dismail.de
Hello!
Consider this bit of simple code:
#+BEGIN_SRC scheme
(define (thunk) (lambda (x) x))
(thunk) ;; works ok, I guess.(thunk "hello world!\n") ;; runtime error
;;; <stdin>:1074:0: warning: possibly wrong number of arguments to `thunk'ice-9/boot-9.scm:1669:16: In procedure raise-exception:Wrong number of arguments to #<procedure thunk ()>
Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.#+END_SRC
Guile will compile this program seemingly with no error. Guile willcorrectly report at runtime that procedure '(thunk "hello world!\n")'takes no arguments, but it's lambda accepts 1 argument. Would it bepossible to report this error at compile time? Would that beadvantageous?
I personally can consider one time where reporting this error atcompile time would be advantageous. Here's how I found out about thiserror. (would ya'll call this an error/bug/feature)?
#+BEGIN_SRC scheme(use-modules (srfi srfi-9))
(define-record-type <lunch> (make-lunch food duration location) lunch? (food lunch-food) (duration lunch-duration) (location lunch-location))
(define dine-out (make-lunch "pizza" "30 min" "downtown"))
;; maybe this should be a syntax error instead of a runtime error?(define (list-lunch) (match-lambda (($ <lunch> food duration location ) (list food duration location))))
;; this is the proper way to do it.(define list-lunch (match-lambda (($ <lunch> food duration location ) (list food duration location))))#+END_SRC
I eventually discovered what the issue was, but I had to run the codeto discover it.
I don't know if this is a silly bug report. If it is, sorry for thenoise.
Thanks,
Joshua
P.S. Guile's error messages at compile time and runtime are superwell written. Thanks!
R
R
Ricardo Wurmus wrote on 21 Jan 14:56 +0100
Re: bug#46014: (define (thunk) (lambda (x) x)) should be a compile error?
(name . Joshua Branson)(address . jbranso@dismail.de)
87bldil7fo.fsf@elephly.net
Hi,
Toggle quote (24 lines)> Consider this bit of simple code:>> #+BEGIN_SRC scheme>> (define (thunk)> (lambda (x)> x))>> (thunk) ;; works ok, I guess.> (thunk "hello world!\n") ;; runtime error>> ;;; <stdin>:1074:0: warning: possibly wrong number of arguments to `thunk'> ice-9/boot-9.scm:1669:16: In procedure raise-exception:> Wrong number of arguments to #<procedure thunk ()>>> Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.> #+END_SRC>> Guile will compile this program seemingly with no error. Guile will> correctly report at runtime that procedure '(thunk "hello world!\n")'> takes no arguments, but it's lambda accepts 1 argument. Would it be> possible to report this error at compile time? Would that be> advantageous?
This is not a bug. What you call “thunk” here is a procedure thatreturns a procedure. That’s very common and is often done to delayevaluation.
It is in fact an error to call the procedure “thunk” with an argument.It doesn’t matter that it happens to return a procedure that *can* takean argument. The procedure it returns is just like any other value,though, and isn’t inspected any further.
That said, it is not true that Guile will compile this without acomplaint. I dumped your code snippet in a file foo.scm andcompiled it:
Toggle snippet (5 lines)guild compile foo.scmfoo.scm:6:0: warning: wrong number of arguments to `thunk'wrote `/home/rekado/.cache/guile/ccache/3.0-LE-8-4.4/home/rekado/dev/gx/gwl/foo.scm.go'
Isn’t that exactly what you’re asking for?
-- Ricardo
S
S
Stefan Israelsson Tampe wrote on 21 Jan 19:16 +0100
(name . Ricardo Wurmus)(address . rekado@elephly.net)
CAGua6m1v-yti0z-8MxAC2gPDSkrmydx_EckRjeLMK+bCiKR0bQ@mail.gmail.com
I will note that paying attention to those warnings is super heolpful inprogramming in guile. I miss these warningsalot when doing python programming.In a sense with these warnings you getclose to static typechecking programminglanguages and scheme/guile is really a nice mix of dynamic and static typing
On Thu, Jan 21, 2021 at 2:58 PM Ricardo Wurmus <rekado@elephly.net> wrote:
Toggle quote (56 lines)>> Hi,>> > Consider this bit of simple code:> >> > #+BEGIN_SRC scheme> >> > (define (thunk)> > (lambda (x)> > x))> >> > (thunk) ;; works ok, I guess.> > (thunk "hello world!\n") ;; runtime error> >> > ;;; <stdin>:1074:0: warning: possibly wrong number of arguments to> `thunk'> > ice-9/boot-9.scm:1669:16: In procedure raise-exception:> > Wrong number of arguments to #<procedure thunk ()>> >> > Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.> > #+END_SRC> >> > Guile will compile this program seemingly with no error. Guile will> > correctly report at runtime that procedure '(thunk "hello world!\n")'> > takes no arguments, but it's lambda accepts 1 argument. Would it be> > possible to report this error at compile time? Would that be> > advantageous?>> This is not a bug. What you call “thunk” here is a procedure that> returns a procedure. That’s very common and is often done to delay> evaluation.>> It is in fact an error to call the procedure “thunk” with an argument.> It doesn’t matter that it happens to return a procedure that *can* take> an argument. The procedure it returns is just like any other value,> though, and isn’t inspected any further.>> That said, it is not true that Guile will compile this without a> complaint. I dumped your code snippet in a file foo.scm and> compiled it:>> --8<---------------cut here---------------start------------->8---> guild compile foo.scm> foo.scm:6:0: warning: wrong number of arguments to `thunk'> wrote> `/home/rekado/.cache/guile/ccache/3.0-LE-8-4.4/home/rekado/dev/gx/gwl/foo.scm.go'> --8<---------------cut here---------------end--------------->8--->> Isn’t that exactly what you’re asking for?>> --> Ricardo>>>>
Attachment: file
J
J
Joshua Branson wrote on 21 Jan 21:09 +0100
(name . Ricardo Wurmus)(address . rekado@elephly.net)
87eeie2gs1.fsf@dismail.de
Ricardo Wurmus <rekado@elephly.net> writes:
Toggle quote (45 lines)> Hi,>>> Consider this bit of simple code:>>>> #+BEGIN_SRC scheme>>>> (define (thunk)>> (lambda (x)>> x))>>>> (thunk) ;; works ok, I guess.>> (thunk "hello world!\n") ;; runtime error>>>> ;;; <stdin>:1074:0: warning: possibly wrong number of arguments to `thunk'>> ice-9/boot-9.scm:1669:16: In procedure raise-exception:>> Wrong number of arguments to #<procedure thunk ()>>>>> Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.>> #+END_SRC>>>> Guile will compile this program seemingly with no error. Guile will>> correctly report at runtime that procedure '(thunk "hello world!\n")'>> takes no arguments, but it's lambda accepts 1 argument. Would it be>> possible to report this error at compile time? Would that be>> advantageous?>> This is not a bug. What you call “thunk” here is a procedure that> returns a procedure. That’s very common and is often done to delay> evaluation.>> It is in fact an error to call the procedure “thunk” with an argument.> It doesn’t matter that it happens to return a procedure that *can* take> an argument. The procedure it returns is just like any other value,> though, and isn’t inspected any further.>> That said, it is not true that Guile will compile this without a> complaint. I dumped your code snippet in a file foo.scm and> compiled it:>> guild compile foo.scm> foo.scm:6:0: warning: wrong number of arguments to `thunk'> wrote `/home/rekado/.cache/guile/ccache/3.0-LE-8-4.4/home/rekado/dev/gx/gwl/foo.scm.go'>> Isn’t that exactly what you’re asking for?
Gotcha. Thanks for explaining! I suppose what I meant to say is,should guile refuse to compile the above? In other languages, like C Isuppose, writing a function simultaneous with one and two argumentswould refuse to compile. The compiler would make you fix the code.
Should guile do this as well?
When I look at
#+BEGIN_SRC scheme(define (thunk) (lambda (x) x))#+END_SRC
or
#+BEGIN_SRC scheme(use-modules (srfi srfi-9))
(define-record-type <lunch> (make-lunch food duration location) lunch? (food lunch-food) (duration lunch-duration) (location lunch-location))
(define dine-out (make-lunch "pizza" "30 min" "downtown"))
;; maybe this should refuse to compile?(define (list-lunch) (match-lambda (($ <lunch> food duration location ) (list food duration location))))#+END_SRC
My thought is, this is clearly a mistake. This person needs to changethe above code.
Thanks,
Joshua
P.S. I'm not a scheme expert. I'm only reporting this, because Irecently read a blog post about free software users rarely reportperceived issues. I'm just trying to be helpful. :) Thanks for thespeedy response time.
--Joshua Branson (joshuaBPMan in #guix)Sent from Emacs and Gnus https://gnucode.me https://video.hardlimit.com/accounts/joshua_branson/video-channels https://propernaming.org "You can have whatever you want, as long as you helpenough other people get what they want." - Zig Ziglar
J
J
Joshua Branson wrote on 21 Jan 21:11 +0100
(name . Stefan Israelsson Tampe)(address . stefan.itampe@gmail.com)
877do62gpe.fsf@dismail.de
Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes:
Toggle quote (4 lines)> I will note that paying attention to those warnings is super heolpful in programming in guile. I miss these warnings> alot when doing python programming.In a sense with these warnings you get close to static typechecking programming> languages and scheme/guile is really a nice mix of dynamic and static typing
I couldn't agree more! Guile's warning/error messages are superhelpful! Taking the time to read those messages really help you catchissues. Often times before you run the program!
--Joshua Branson (joshuaBPMan in #guix)Sent from Emacs and Gnus https://gnucode.me https://video.hardlimit.com/accounts/joshua_branson/video-channels https://propernaming.org "You can have whatever you want, as long as you helpenough other people get what they want." - Zig Ziglar
R
R
Ricardo Wurmus wrote on 21 Jan 23:27 +0100
(name . Joshua Branson)(address . jbranso@dismail.de)
878s8mkjsk.fsf@elephly.net
Hi Joshua,
Toggle quote (8 lines)> When I look at>> #+BEGIN_SRC scheme> (define (thunk)> (lambda (x)> x))> #+END_SRC
[…]
Toggle quote (3 lines)> My thought is, this is clearly a mistake. This person needs to change> the above code.
How is this clearly a mistake? The definition of “thunk” above isperfectly fine and also common.
The above is equivalent to
(define thunk (lambda () (lambda (x) x)))
And that’s really okay and can be desired. The problem is not withthis definition. If someone calls this wrongly, well, that’s a problemwith the caller. And Guile’s compiler does tell you that you areprobably wrong in calling “thunk” with an argument.
Do I understand you correctly that you would like this warning to be anerror instead?
Toggle quote (5 lines)> Gotcha. Thanks for explaining! I suppose what I meant to say is,> should guile refuse to compile the above? In other languages, like C I> suppose, writing a function simultaneous with one and two arguments> would refuse to compile. The compiler would make you fix the code.
Let me address this separately. In Scheme you *can* define a procedurethat takes a different number of arguments. Here’s one example from themanual:
(define (make-accum n) (case-lambda (() n) ((m) (set! n (+ n m)) n)))
(define a (make-accum 20)) (a) ⇒ 20 (a 10) ⇒ 30 (a) ⇒ 30
“case-lambda” specifies a procedure that can take arguments in as manydifferent shapes as there are clauses. Here there are two clauses: onefor the case where no arguments are provided and another where oneargument (bound to “m”) is provided.
Furthermore, you can see here that this is a higher order procedure, as“make-accum” takes an argument and returns a procedure (thecase-lambda).
Another example, also from the manual, is this:
(lambda* (start #:optional (end (+ 10 start))) (do ((i start (1+ i))) ((> i end)) (display i)))
This procedure takes one or two arguments.
-- Ricardo
J
J
Joshua Branson wrote on 22 Jan 15:47 +0100
(name . Ricardo Wurmus)(address . rekado@elephly.net)
87o8hhyqo3.fsf@dismail.de
Ricardo Wurmus <rekado@elephly.net> writes:
Toggle quote (18 lines)> Hi Joshua,>>> When I look at>>>> #+BEGIN_SRC scheme>> (define (thunk)>> (lambda (x)>> x))>> #+END_SRC>> […]>>> My thought is, this is clearly a mistake. This person needs to change>> the above code.>> How is this clearly a mistake? The definition of “thunk” above is> perfectly fine and also common.
Thanks again for responding. I'm still learning scheme, and it's coolthat this email chain has helped clarify some things. :)
Ahh. I see now that the proper way to call thunk is to do this:((thunk) "the")$1 = "the"
I had assumed that every time one called thunk, it would result in aruntime error. I did not realize that there was a way to properly callthunk. Wow. Scheme is truly impressive.
Interestingly, I had wrongly assumed that
#+BEGIN_SRC scheme(thunk "test\n") ;; I assumed program execution would stop here(display "Hello World\n")#+END_SRC
program execution would stop at (thunk "test\n"). But it actuallycaries on with execution of the program:
#+BEGIN_SRC scheme<stdin>:5:0: warning: possibly wrong number of arguments to `thunk'ice-9/boot-9.scm:1669:16: In procedure raise-exception:Wrong number of arguments to #<procedure thunk ()>
Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.Hello World#+END_SRC
I'm not certain if it is a good or bad thing that scheme continuesprogram execution after a runtime error. I know I've built toy webapplications in guile... Sometimes the input to a form is bad data, andthe web-server emits a runtime error, but keeps running. Maybe it wouldbe better if the program halted on every runtime error. It would be away of saying, "Hey your web-server hasn't really handled dealing withbad data properly. You need to fix it, because I will crash at everyrun time error."
For fun I also thought about how else I could write thunk. Continuereading at your own peril.
#+BEGIN_SRC scheme;; This procedure doesn't work the way I thought it would. The way to;; print a string with this procedure is to do this:;; ((thunk "the") "the")(define (thunk x) (lambda (x) x))
;; obvious. This is equivalent to;; (define (thunk x) x)(define thunk (lambda (x) x))
;; This ones nice because neither (thunk) nor (thunk "the") result in a;; runtime error.(define* (thunk #:optional x) x)
(define* (thunk #:optional x) (lambda* (#:optional x) x))#+END_SRC
Are there some other really weird and convoluted ways of writing thunkthat I'm missing? I'm guessing so.
Toggle quote (15 lines)>> The above is equivalent to>> (define thunk> (lambda ()> (lambda (x) x)))>> And that’s really okay and can be desired. The problem is not with> this definition. If someone calls this wrongly, well, that’s a problem> with the caller. And Guile’s compiler does tell you that you are> probably wrong in calling “thunk” with an argument.>> Do I understand you correctly that you would like this warning to be an> error instead?
No. Not anymore. Before I had assumed that any invocation of thunkwould result in a runtime error. If that was the case, I figured guileshould refuse to compile it. Now I realize that ((thunk "the") "the")works.
Toggle quote (29 lines)>>> Gotcha. Thanks for explaining! I suppose what I meant to say is,>> should guile refuse to compile the above? In other languages, like C I>> suppose, writing a function simultaneous with one and two arguments>> would refuse to compile. The compiler would make you fix the code.>> Let me address this separately. In Scheme you *can* define a procedure> that takes a different number of arguments. Here’s one example from the> manual:>> (define (make-accum n)> (case-lambda> (() n)> ((m) (set! n (+ n m)) n)))>> (define a (make-accum 20))> (a) ⇒ 20> (a 10) ⇒ 30> (a) ⇒ 30>> “case-lambda” specifies a procedure that can take arguments in as many> different shapes as there are clauses. Here there are two clauses: one> for the case where no arguments are provided and another where one> argument (bound to “m”) is provided.>> Furthermore, you can see here that this is a higher order procedure, as> “make-accum” takes an argument and returns a procedure (the> case-lambda).
Oh wow! Man am I going to have fun with case-lambda! Thanks forpointing that out!
Toggle quote (10 lines)>> Another example, also from the manual, is this:>> (lambda* (start #:optional (end (+ 10 start)))> (do ((i start (1+ i)))> ((> i end))> (display i)))>> This procedure takes one or two arguments.
Thanks again for explaining this to me. I've learned a lot from thisinteraction!
Do you think there are some warnings in guile that should be escalatedto errors that refuse to compile? How about this example? (later on Ichanged my mind and realized this example doesn't really prove my point).
#+BEGIN_SRC scheme(use-modules (guix-records))
(define-record-type* <lunch-time> lunch-time make-lunch-time lunch-time? (period lunch-time-period (default "10 min")))
(define-record-type* <lunch> lunch make-lunch lunch? (food lunch-food (default "pizza")) (duration lunch-duration ;; here time should by lunch-time instead (default (time (period "30 min")))))
(lunch)#+END_SRC
When I pasted this into the REPL, the result is:
;;; <stdin>:26:0: warning: possibly unbound variable `time';;; <stdin>:26:0: warning: possibly unbound variable `period'ice-9/boot-9.scm:1669:16: In procedure raise-exception:Unbound variable: time
Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.
This appears to me to be a case where, there is NO way to properly makea lunch record without creating a run time error.
Whoops. Actually there is a proper way to make a lunch record:
#+BEGIN_SRC scheme(make-lunch "sandwich" "one hour")#+END_SRC
I suppose the moral of the story is that scheme is so expressive andflexible that there are ways of creating programs that can fail in weirdways. And it's really hard if not impossible to catch all possibleruntime errors at compile time. This is because scheme values are onlyknow at run-time AND NOT compile time.
I was actually listening to a scheme talk recently about typed racket.The gentleman giving the talk explained that dynamic typing used to beall the rage, but there seems to be some people advocating for statictyping because the compiler eliminates many trivial bugs. However, someelegant and correct dynamic programs would be eliminated by thecompiler as causing errors.
typed scheme | untyped scheme----------------------------------------------------------------- potentially faster | - potentially slower- a procedure's inputs | - more expressive and outputs are obvious | - more concise- catches trivial errors |- helps refactoring |- eliminates "correct" dynamic programs
I suppose that what I am wanting (forcing the compiler to eliminatetrivial bugs) may only be possible in a typed scheme. Is that correct?
What are your thoughts? Typed or un-typed scheme?
Thanks,
Joshua
--Joshua Branson (joshuaBPMan in #guix)Sent from Emacs and Gnus https://gnucode.me https://video.hardlimit.com/accounts/joshua_branson/video-channels https://propernaming.org "You can have whatever you want, as long as you helpenough other people get what they want." - Zig Ziglar
T
(address . bug-guile@gnu.org)
20210122162918.GA27617@tuxteam.de
On Fri, Jan 22, 2021 at 09:47:24AM -0500, jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language wrote:
Toggle quote (41 lines)> Ricardo Wurmus <rekado@elephly.net> writes:> > > Hi Joshua,> >> >> When I look at> >>> >> #+BEGIN_SRC scheme> >> (define (thunk)> >> (lambda (x)> >> x))> >> #+END_SRC> >> > […]> >> >> My thought is, this is clearly a mistake. This person needs to change> >> the above code.> >> > How is this clearly a mistake? The definition of “thunk” above is> > perfectly fine and also common.> > Thanks again for responding. I'm still learning scheme, and it's cool> that this email chain has helped clarify some things. :)> > Ahh. I see now that the proper way to call thunk is to do this:> ((thunk) "the")> $1 = "the"> > I had assumed that every time one called thunk, it would result in a> runtime error. I did not realize that there was a way to properly call> thunk. Wow. Scheme is truly impressive.> > Interestingly, I had wrongly assumed that> > #+BEGIN_SRC scheme> (thunk "test\n") ;; I assumed program execution would stop here> (display "Hello World\n")> #+END_SRC> > program execution would stop at (thunk "test\n"). But it actually> caries on with execution of the program:
What happens is an "exception". It can be handled (then it's upto the exception handler to end the program or do something else).
Toggle quote (9 lines)> #+BEGIN_SRC scheme> <stdin>:5:0: warning: possibly wrong number of arguments to `thunk'> ice-9/boot-9.scm:1669:16: In procedure raise-exception:> Wrong number of arguments to #<procedure thunk ()>> > Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.> Hello World> #+END_SRC
This is the REPL's exception handler talking to you. It's there to helpyou debug the problem.
Were it a standalone program, it would have terminated right away.
(note that I'm not the most appropriate person to explain such things,I can barely wrap my head around them :-)
Cheers
[1] https://www.gnu.org/software/guile/docs/master/guile.html/Exceptions.html
- tomás
-----BEGIN PGP SIGNATURE-----Version: GnuPG v1.4.12 (GNU/Linux)
iEYEARECAAYFAmAK/V4ACgkQBcgs9XrR2kbIxACePKWcPtVfmvitEMIdQnhQOmWIRoQAniSIEmjI/j6/5h+0xP1fHCe+56SW=JAdy-----END PGP SIGNATURE-----

R
R
Ricardo Wurmus wrote on 23 Jan 16:02 +0100
(name . Joshua Branson)(address . jbranso@dismail.de)
87v9bnk87q.fsf@mdc-berlin.de
Hi Joshua,
Toggle quote (19 lines)> Interestingly, I had wrongly assumed that>> #+BEGIN_SRC scheme> (thunk "test\n") ;; I assumed program execution would stop here> (display "Hello World\n")> #+END_SRC>> program execution would stop at (thunk "test\n"). But it actually> caries on with execution of the program:>> #+BEGIN_SRC scheme> <stdin>:5:0: warning: possibly wrong number of arguments to `thunk'> ice-9/boot-9.scm:1669:16: In procedure raise-exception:> Wrong number of arguments to #<procedure thunk ()>>> Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.> Hello World> #+END_SRC
It doesn’t actually carry on. From those Org-mode blocks I cannot tellhow you’re feeding the expressions to Guile. If you’re doing this in afile or in a REPL session manually you’ll see this:
Toggle snippet (12 lines)scheme@(guile-user)> (define (thunk) (lambda (x) x))scheme@(guile-user)> (thunk "test\n");;; <stdin>:3640:0: warning: possibly wrong number of arguments to `thunk'ice-9/boot-9.scm:1669:16: In procedure raise-exception:Wrong number of arguments to #<procedure thunk ()>
Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue.scheme@(guile-user) [1]> (display "Hello World\n")Hello Worldscheme@(guile-user) [1]>
“Entering a new prompt” is what happens. Consider it a special debugmode in which you’re given the option to inspect the current state ofthe environment. Granted, you won’t see much when you type “,bt” or“,bt #:full? 'yup”, because the error isn’t all that complicated; theerror didn’t happen in some deeply nested callee, it happened rightthere when you called “thunk” with an argument.
Toggle quote (3 lines)> For fun I also thought about how else I could write thunk. Continue> reading at your own peril.
I feel the need to point out that the name “thunk” has a conventionalmeaning, but your examples (here and before) don’t correspond to thatmeaning. A thunk is a procedure of no arguments. When called itreturns a value — it does not matter whether that value is anotherprocedure, a record, or a primitive value.
What you seem to be calling “thunk” is really just a higher orderprocedure, i.e. a procedure that returns another procedure. Note thatthis may or may not be a thunk as everybody else calls it. It is athunk when it is a procedure that takes exactly zero arguments.
Toggle quote (6 lines)> ;; This procedure doesn't work the way I thought it would. The way to> ;; print a string with this procedure is to do this:> ;; ((thunk "the") "the")> (define (thunk x)> (lambda (x) x))
You’re making things difficult for you here, because you’re using “x”three times, but it means two different things dependent on where youlook at the value you bound to “x”. This is also not a thunk (neitherthe procedure “thunk” nor the value it returns), so let’s rewrite this:
(define (moo x) (peek 'moo-x x) (lambda (x) (peek 'lambda-x x)))
Nobody cares about the value you pass to “moo”. It is bound to the name“x”, but nobody uses it. Then comes along a lambda and it takes anargument that is also known as “x” inside the body of that lambda. Theyare *not* the same “x”. The “x” bound by the lambda shadows the outer“x”. You could even have yet another “x”:
(define x 100) (peek 'top-level-x x) (define (moo x) (peek 'moo-x x) (lambda (x) (peek 'lambda-x x)))
Excess xes!
Toggle quote (6 lines)> ;; obvious. This is equivalent to> ;; (define (thunk x) x)> (define thunk> (lambda (x)> x))
Correct. Not a thunk, though. It’s just the identity function.
Toggle quote (5 lines)> ;; This ones nice because neither (thunk) nor (thunk "the") result in a> ;; runtime error.> (define* (thunk #:optional x)> x)
This is a procedure that will return #false (when no argument isprovided) or the value of the argument it was given.
Toggle quote (4 lines)> (define* (thunk #:optional x)> (lambda* (#:optional x)> x))
This is again like the “moo” example earlier. Two different values arebound to variables that are known as “x” in their own scope, with thelater “x” shadowing the earlier “x”.
Toggle quote (3 lines)> Are there some other really weird and convoluted ways of writing thunk> that I'm missing? I'm guessing so.
I don’t know what you mean because your definitions above are not alldoing the same thing. A giraffe is not a convoluted variant of a lion.
Toggle quote (3 lines)> […] Now I realize that ((thunk "the") "the")> works.
((thunk 124) "the") has the same return value, because you’re ignoringthe first “x”.
Toggle quote (6 lines)> I suppose the moral of the story is that scheme is so expressive and> flexible that there are ways of creating programs that can fail in weird> ways. And it's really hard if not impossible to catch all possible> runtime errors at compile time. This is because scheme values are only> know at run-time AND NOT compile time.
This is not 100% correct, but perhaps that doesn’t matter. Some typesare in fact known at compile time.
Toggle quote (22 lines)> I was actually listening to a scheme talk recently about typed racket.> The gentleman giving the talk explained that dynamic typing used to be> all the rage, but there seems to be some people advocating for static> typing because the compiler eliminates many trivial bugs. However, some> elegant and correct dynamic programs would be eliminated by the> compiler as causing errors.>> typed scheme | untyped scheme> ----------------------------------------------------------------> - potentially faster | - potentially slower> - a procedure's inputs | - more expressive> and outputs are obvious | - more concise> - catches trivial errors |> - helps refactoring |> - eliminates "correct"> dynamic programs>> I suppose that what I am wanting (forcing the compiler to eliminate> trivial bugs) may only be possible in a typed scheme. Is that correct?>> What are your thoughts? Typed or un-typed scheme?
I learned functional programming with Haskell, which is more type thanlanguage ;) Type systems allow you to encode certain assumptions in away that the compiler can check for you.
Note that “potentially slower” doesn’t mean much unless you look atactual implementations. Types allow the compiler to perform certainoptimizations because it can trust that certain assumptions will hold atruntime. But these optimizations would actually have to be implementedin the compiler; you don’t get them for free just because you have typedeclarations. Likewise, you can have a fast untyped Scheme and a slowuntyped Scheme dependent on the optimizations that are implemented. Youcan also get fast or slow compilers…
The point about types eliminating “correct” dynamic programs isnoteworthy. Types are a constraint and dependent on how strictly theyare enforced they can make it impossible to do things that are sensible.It is, however, possible to declare an “Any” type and write programsthat are transformations of values of the “Any” type, which would becorrectly typed; but the effect is to bypasses the type checker, whichrenders it useless.
So… yeah, it’s not that clear cut.
Sometimes I do miss types in my Scheme code, especially in more complexprograms with lots of higher-order functions where it’s easy to getlost. But most of the time I don’t care for types.
-- Ricardo
J
J
Joshua Branson wrote on 23 Jan 16:07 +0100
closing the bug report...hopefully
(address . 46014@debbugs.gnu.org)
87im7nzo6q.fsf@dismail.de
close 46014
J
J
Joshua Branson wrote on 23 Jan 16:17 +0100
Re: bug#46014: (define (thunk) (lambda (x) x)) should be a compile error?
(name . Ricardo Wurmus)(address . rekado@elephly.net)
87bldfznqy.fsf@dismail.de
Hey Ricardo!
Thanks for taking the time to explain that thunk is a procedure with noarguments, and that the first x is not used in some of those procedures.
Feel free to close this bug report. I don't believe I was able todemonstrate any examples of the compiler misbehaving.
Thanks!
--Joshua Branson (joshuaBPMan in #guix)Sent from Emacs and Gnus https://gnucode.me https://video.hardlimit.com/accounts/joshua_branson/video-channels https://propernaming.org "You can have whatever you want, as long as you helpenough other people get what they want." - Zig Ziglar
R
R
Ricardo Wurmus wrote on 23 Jan 18:23 +0100
(name . Joshua Branson)(address . jbranso@dismail.de)
87sg6rk1o5.fsf@elephly.net
Joshua Branson <jbranso@dismail.de> writes:
Toggle quote (3 lines)> Feel free to close this bug report. I don't believe I was able to> demonstrate any examples of the compiler misbehaving.
Okay, closing!
-- Ricardo
?
Your comment

Commenting via the web interface is currently disabled.

To comment on this conversation send email to 46014@debbugs.gnu.org