On 12/1/2018 7:24 PM, 'John Clements' via Racket Users wrote:
I claim that it’s not quite as simple as that. For instance, consider this 
program:

#lang typed/racket

;; this one type-checks as a Number:
(ann
  (let ()
    (define num (string->number "aoeu"))
    (unless num
      (error "Not a number"))
    (* num 2))
  Number)

;; this one doesn't type-check at all:
(ann
  (let ()
    (define num (string->number "aoeu"))
    (unless num
      (error "Not a number"))
    (define double (* num 2))
    double)
  Number)

The first one type-checks fine, the second one doesn’t. The only difference 
between them is that the first one returns the (* num 2) directly and the 
second one gives it a name.

Note that the ‘for’ loop is not important, I scrapped it. Also, I wrapped them 
in a type annotation using ‘ann’, just to show that they both type-check at 
Number.

Usually when I see something like this I confidently declare that it’s a bug, 
and then Sam explains that it’s not, because a continuation might jump sideways 
into the code… or simply that it’s too complicated a piece of code. In this 
situation, though, I’m not sure how that could be the case.

Finally, in the ‘due diligence’ category, this is DrRacket compiled from head, 
"version 7.1.0.8--2018-12-01(-/f) [3m]."

John

I agree, but it's not simply "giving the value a name" - it has something to do with the internal define.
E.g., this type checks:

   (ann
     (let ()
       (define num (string->number "aoeu"))
       (unless num
         (error "Not a number"))
       (let ((double (* num 2)))
         double))
     Number)


And as I mentioned already, the internal define works inside a COND [below in the quote].

My (maybe flawed) understanding is that internal define and let both create just a local and not a named binding.

George


> On Dec 1, 2018, at 10:40, George Neuner <gneun...@comcast.net> wrote:
> > > > On 12/1/2018 12:28 PM, hashim muqtadir wrote:
>> But this doesn't typecheck:
>> >> > (for ([x (in-list '("123" "432" "234"))])
>>     (define num (string->number x))
>>     (unless num
>>       (error "Not a number"))
>>     (define double (* num 2))
>>     (display (format "~s" double)))
>> . Type Checker: type mismatch
>>   expected: Number
>>   given: (U Complex False) in: num
>> >> Am I missing something here? > > That string->number returns #f if it fails - and if num is #f then (* num 2) is meaningless. > > The type error is telling you where you will run into the problem:
>   expected: Number
>   given: (U Complex False) in: num
> > You know that execution won't reach the multiplication if num is #f, but the compiler doesn't. > > > I'm not any kind of typed Racket wizard, but the type error goes away if you explicitly use a conditional:
>      :
>     (cond
>       ([false? num]
>        (error "Not a number") )
>       (else
>        (define double (* num 2))
>        (display (format "~s" double)) ))
> > If you use LET rather than the internal define, you can use IF instead.
>      :
>     (if num
>       (let ((double (* num 2)))
>         (display (format "~s" double)))
>       (error "Not a number")
>       ))
> > > George

--
You received this message because you are subscribed to the Google Groups "Racket 
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to