* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? @ 2021-01-21 2:04 jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-21 13:56 ` Ricardo Wurmus 2021-01-23 15:07 ` bug#46014: closing the bug report...hopefully jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 0 siblings, 2 replies; 12+ messages in thread From: jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language @ 2021-01-21 2:04 UTC (permalink / raw) To: 46014 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 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? I personally can consider one time where reporting this error at compile time would be advantageous. Here's how I found out about this error. (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 code to discover it. I don't know if this is a silly bug report. If it is, sorry for the noise. Thanks, Joshua P.S. Guile's error messages at compile time and runtime are super well written. Thanks! ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? 2021-01-21 2:04 bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language @ 2021-01-21 13:56 ` Ricardo Wurmus 2021-01-21 18:16 ` Stefan Israelsson Tampe 2021-01-21 20:09 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-23 15:07 ` bug#46014: closing the bug report...hopefully jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 1 sibling, 2 replies; 12+ messages in thread From: Ricardo Wurmus @ 2021-01-21 13:56 UTC (permalink / raw) To: Joshua Branson; +Cc: 46014 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 ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? 2021-01-21 13:56 ` Ricardo Wurmus @ 2021-01-21 18:16 ` Stefan Israelsson Tampe 2021-01-21 20:11 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-21 20:09 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 1 sibling, 1 reply; 12+ messages in thread From: Stefan Israelsson Tampe @ 2021-01-21 18:16 UTC (permalink / raw) To: Ricardo Wurmus; +Cc: 46014, Joshua Branson [-- Attachment #1: Type: text/plain, Size: 2238 bytes --] 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 On Thu, Jan 21, 2021 at 2:58 PM Ricardo Wurmus <rekado@elephly.net> wrote: > > 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 #2: Type: text/html, Size: 2799 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? 2021-01-21 18:16 ` Stefan Israelsson Tampe @ 2021-01-21 20:11 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 0 siblings, 0 replies; 12+ messages in thread From: jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language @ 2021-01-21 20:11 UTC (permalink / raw) To: Stefan Israelsson Tampe; +Cc: 46014 Stefan Israelsson Tampe <stefan.itampe@gmail.com> writes: > 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 super helpful! Taking the time to read those messages really help you catch issues. 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 help enough other people get what they want." - Zig Ziglar ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? 2021-01-21 13:56 ` Ricardo Wurmus 2021-01-21 18:16 ` Stefan Israelsson Tampe @ 2021-01-21 20:09 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-21 22:27 ` Ricardo Wurmus 1 sibling, 1 reply; 12+ messages in thread From: jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language @ 2021-01-21 20:09 UTC (permalink / raw) To: Ricardo Wurmus; +Cc: 46014 Ricardo Wurmus <rekado@elephly.net> writes: > 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 I suppose, writing a function simultaneous with one and two arguments would 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 change the above code. Thanks, Joshua P.S. I'm not a scheme expert. I'm only reporting this, because I recently read a blog post about free software users rarely report perceived issues. I'm just trying to be helpful. :) Thanks for the speedy 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 help enough other people get what they want." - Zig Ziglar ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? 2021-01-21 20:09 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language @ 2021-01-21 22:27 ` Ricardo Wurmus 2021-01-22 14:47 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 0 siblings, 1 reply; 12+ messages in thread From: Ricardo Wurmus @ 2021-01-21 22:27 UTC (permalink / raw) To: Joshua Branson; +Cc: 46014 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. 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? > 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). 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 ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? 2021-01-21 22:27 ` Ricardo Wurmus @ 2021-01-22 14:47 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-22 16:29 ` tomas 2021-01-23 15:02 ` Ricardo Wurmus 0 siblings, 2 replies; 12+ messages in thread From: jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language @ 2021-01-22 14:47 UTC (permalink / raw) To: Ricardo Wurmus; +Cc: 46014 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: #+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 continues program execution after a runtime error. I know I've built toy web applications in guile... Sometimes the input to a form is bad data, and the web-server emits a runtime error, but keeps running. Maybe it would be better if the program halted on every runtime error. It would be a way of saying, "Hey your web-server hasn't really handled dealing with bad data properly. You need to fix it, because I will crash at every run time error." For fun I also thought about how else I could write thunk. Continue reading 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 thunk that I'm missing? I'm guessing so. > > 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 thunk would result in a runtime error. If that was the case, I figured guile should refuse to compile it. Now I realize that ((thunk "the") "the") works. > >> 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 for pointing that out! > > 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 this interaction! Do you think there are some warnings in guile that should be escalated to errors that refuse to compile? How about this example? (later on I changed 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 make a 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 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. 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? 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 help enough other people get what they want." - Zig Ziglar ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? 2021-01-22 14:47 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language @ 2021-01-22 16:29 ` tomas 2021-01-23 15:02 ` Ricardo Wurmus 1 sibling, 0 replies; 12+ messages in thread From: tomas @ 2021-01-22 16:29 UTC (permalink / raw) To: 46014 [-- Attachment #1: Type: text/plain, Size: 2141 bytes --] On Fri, Jan 22, 2021 at 09:47:24AM -0500, jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language wrote: > 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 up to the exception handler to end the program or do something else). > #+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 help you 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 [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 198 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? 2021-01-22 14:47 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-22 16:29 ` tomas @ 2021-01-23 15:02 ` Ricardo Wurmus 2021-01-23 15:17 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 1 sibling, 1 reply; 12+ messages in thread From: Ricardo Wurmus @ 2021-01-23 15:02 UTC (permalink / raw) To: Joshua Branson; +Cc: 46014 Hi Joshua, > 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 tell how you’re feeding the expressions to Guile. If you’re doing this in a file or in a REPL session manually you’ll see this: --8<---------------cut here---------------start------------->8--- 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 World scheme@(guile-user) [1]> --8<---------------cut here---------------end--------------->8--- “Entering a new prompt” is what happens. Consider it a special debug mode in which you’re given the option to inspect the current state of the environment. Granted, you won’t see much when you type “,bt” or “,bt #:full? 'yup”, because the error isn’t all that complicated; the error didn’t happen in some deeply nested callee, it happened right there when you called “thunk” with an argument. > 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 conventional meaning, but your examples (here and before) don’t correspond to that meaning. A thunk is a procedure of no arguments. When called it returns a value — it does not matter whether that value is another procedure, a record, or a primitive value. What you seem to be calling “thunk” is really just a higher order procedure, i.e. a procedure that returns another procedure. Note that this may or may not be a thunk as everybody else calls it. It is a thunk when it is a procedure that takes exactly zero arguments. > ;; 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 you look at the value you bound to “x”. This is also not a thunk (neither the 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 an argument that is also known as “x” inside the body of that lambda. They are *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! > ;; 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. > ;; 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 is provided) or the value of the argument it was given. > (define* (thunk #:optional x) > (lambda* (#:optional x) > x)) This is again like the “moo” example earlier. Two different values are bound to variables that are known as “x” in their own scope, with the later “x” shadowing the earlier “x”. > 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 all doing the same thing. A giraffe is not a convoluted variant of a lion. > […] Now I realize that ((thunk "the") "the") > works. ((thunk 124) "the") has the same return value, because you’re ignoring the first “x”. > 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 types are in fact known at 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 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 than language ;) Type systems allow you to encode certain assumptions in a way that the compiler can check for you. Note that “potentially slower” doesn’t mean much unless you look at actual implementations. Types allow the compiler to perform certain optimizations because it can trust that certain assumptions will hold at runtime. But these optimizations would actually have to be implemented in the compiler; you don’t get them for free just because you have type declarations. Likewise, you can have a fast untyped Scheme and a slow untyped Scheme dependent on the optimizations that are implemented. You can also get fast or slow compilers… The point about types eliminating “correct” dynamic programs is noteworthy. Types are a constraint and dependent on how strictly they are enforced they can make it impossible to do things that are sensible. It is, however, possible to declare an “Any” type and write programs that are transformations of values of the “Any” type, which would be correctly typed; but the effect is to bypasses the type checker, which renders it useless. So… yeah, it’s not that clear cut. Sometimes I do miss types in my Scheme code, especially in more complex programs with lots of higher-order functions where it’s easy to get lost. But most of the time I don’t care for types. -- Ricardo ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? 2021-01-23 15:02 ` Ricardo Wurmus @ 2021-01-23 15:17 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-23 17:23 ` Ricardo Wurmus 0 siblings, 1 reply; 12+ messages in thread From: jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language @ 2021-01-23 15:17 UTC (permalink / raw) To: Ricardo Wurmus; +Cc: 46014 Hey Ricardo! Thanks for taking the time to explain that thunk is a procedure with no arguments, 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 to demonstrate 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 help enough other people get what they want." - Zig Ziglar ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? 2021-01-23 15:17 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language @ 2021-01-23 17:23 ` Ricardo Wurmus 0 siblings, 0 replies; 12+ messages in thread From: Ricardo Wurmus @ 2021-01-23 17:23 UTC (permalink / raw) To: Joshua Branson; +Cc: 46014, 46014-done Joshua Branson <jbranso@dismail.de> writes: > 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 ^ permalink raw reply [flat|nested] 12+ messages in thread
* bug#46014: closing the bug report...hopefully 2021-01-21 2:04 bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-21 13:56 ` Ricardo Wurmus @ 2021-01-23 15:07 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 1 sibling, 0 replies; 12+ messages in thread From: jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language @ 2021-01-23 15:07 UTC (permalink / raw) To: 46014 close 46014 ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2021-01-23 17:23 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-01-21 2:04 bug#46014: (define (thunk) (lambda (x) x)) should be a compile error? jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-21 13:56 ` Ricardo Wurmus 2021-01-21 18:16 ` Stefan Israelsson Tampe 2021-01-21 20:11 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-21 20:09 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-21 22:27 ` Ricardo Wurmus 2021-01-22 14:47 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-22 16:29 ` tomas 2021-01-23 15:02 ` Ricardo Wurmus 2021-01-23 15:17 ` jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language 2021-01-23 17:23 ` Ricardo Wurmus 2021-01-23 15:07 ` bug#46014: closing the bug report...hopefully jbranso--- via Bug reports for GUILE, GNU's Ubiquitous Extension Language
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).