unofficial mirror of bug-guile@gnu.org 
 help / color / mirror / Atom feed
From: jbranso--- via "Bug reports for GUILE, GNU's Ubiquitous Extension Language" <bug-guile@gnu.org>
To: Ricardo Wurmus <rekado@elephly.net>
Cc: 46014@debbugs.gnu.org
Subject: bug#46014: (define (thunk) (lambda (x) x)) should be a compile error?
Date: Fri, 22 Jan 2021 09:47:24 -0500	[thread overview]
Message-ID: <87o8hhyqo3.fsf@dismail.de> (raw)
In-Reply-To: <878s8mkjsk.fsf@elephly.net> (Ricardo Wurmus's message of "Thu, 21 Jan 2021 23:27:23 +0100")

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





  reply	other threads:[~2021-01-22 14:47 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87o8hhyqo3.fsf@dismail.de \
    --to=bug-guile@gnu.org \
    --cc=46014@debbugs.gnu.org \
    --cc=jbranso@dismail.de \
    --cc=rekado@elephly.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).