How to convert String to Integer

89 views
Skip to first unread message

Alain De Vos

unread,
Feb 11, 2020, 5:34:16 AM2/11/20
to Racket Users
I tried the following function to conver a String to an Integer.

#lang typed/racket
(: myconversion (-> String Integer))
(define (myconversion str)
  (string->number str))

The error given is :
Type Checker: type mismatch
  expected: Integer
  given: (U Complex False) in: (string->number str)

I guess this is because a number is not an Integer.

How to proceed?

I found the following code on internet , but this looks like a real overkill for this simple problem ,

(: numerical-char->integer (-> Char
                               Integer))
(define (numerical-char->integer char)
  (let ([num (- (char->integer char) 48)]) ; 48 = (char->integer #\0)
    (if
     (or (< num 0) (> num 9))
     (raise 'non-numerical-char #t)
     num)))

(: string->integer (-> String
                       Integer))
(define (string->integer str)
  (let ([char-list (string->list str)])
    (if (null? char-list)
        (raise 'empty-string #t)
        (foldl
         (λ([x : Integer] [y : Integer])
           (+ (* y 10) x))
         0
         (map numerical-char->integer char-list)))))

Alain De Vos

unread,
Feb 11, 2020, 5:45:05 AM2/11/20
to Racket Users
Or is it they idea to write own conversion functions to learn the language.

Ryan Culpepper

unread,
Feb 11, 2020, 6:02:46 AM2/11/20
to Alain De Vos, Racket Users
What should `(myconversion "apple")` return?
What should `(myconversion "12.3")` return?
What does `string->number` do in each of those cases?

Ryan


--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/4a13bb2e-3107-4c5f-aee6-6d29e493c040%40googlegroups.com.

Alain De Vos

unread,
Feb 11, 2020, 6:43:14 AM2/11/20
to Racket Users
Indeed good question, but the following code works,

#lang typed/racket
(require typed/racket/gui)

(: fib (-> Integer Integer))
(define (fib n)
  (if (< 2 n)
      n
      (+ (fib (- n 1))
         (fib (- n 2)))))

(: numericalchar2integer (-> Char Integer))
(define (numericalchar2integer char)

  (let ([num (- (char->integer char) 48)]) ; 48 = (char->integer #\0)
    (if
     (or (< num 0) (> num 9))
     (raise 'non-numerical-char #t)
     num)))

(: string2integer (-> String Integer))
(define (string2integer str)

  (let ([char-list (string->list str)])
    (if (null? char-list)
        (raise 'empty-string #t)
        (foldl
         (λ([x : Integer] [y : Integer])
           (+ (* y 10) x))
         0
         (map numericalchar2integer char-list)))))

And the following code fails , just one the first line difference,
#lang sweet-exp typed/racket
(: fib (-> Integer Integer))
(define (fib n)
  (if (< 2 n)
      n
      (+ (fib (- n 1))
         (fib (- n 2)))))

(: numericalchar2integer (-> Char Integer))
(define (numericalchar2integer char)

  (let ([num (- (char->integer char) 48)]) ; 48 = (char->integer #\0)
    (if
     (or (< num 0) (> num 9))
     (raise 'non-numerical-char #t)
     num)))

(: string2integer (-> String Integer))
(define (string2integer str)

  (let ([char-list (string->list str)])
    (if (null? char-list)
        (raise 'empty-string #t)
        (foldl
         (λ([x : Integer] [y : Integer])
           (+ (* y 10) x))
         0
         (map numericalchar2integer char-list)))))

Error, unbound identifier y.
Has sweet-exp a problem with lambda functions ?
To unsubscribe from this group and stop receiving emails from it, send an email to racket...@googlegroups.com.

Ben Greenman

unread,
Feb 11, 2020, 9:25:42 AM2/11/20
to Racket Users
You may want `exact-integer?`

Alain De Vos

unread,
Feb 11, 2020, 9:50:27 AM2/11/20
to Racket Users


On Tuesday, February 11, 2020 at 3:25:42 PM UTC+1, Ben Greenman wrote:
You may want `exact-integer?`
True , i should use exact-integer.

Alain De Vos

unread,
Feb 11, 2020, 10:04:40 AM2/11/20
to Racket Users
No exact-integer is a check it is not a type.
The error described above remains

Philip McGrath

unread,
Feb 11, 2020, 11:33:37 AM2/11/20
to Alain De Vos, Racket Users
Others have tried to be more Socratic in pointing you this way, but here's an attempt at being more explicit.

As you note, the result of `string->number` has the type `(U Complex False)`. If we try to think about about this in a version of the HtDP design recipe, we have a few cases:
  1. `string->number` produces an `Integer` when given an argument like `"42"`.
  2. `string->number` can also produce a value of any of the various `Number` types that aren't integers, as with `"3.2+6.0i"` or `"2/3"`.
  3. If the given string can't be parsed as any kind of number, like `"apple"`, `string->number` returns `#false`.
If you want to write a function with the type `(-> String Integer)`, you are going to have to handle all of those cases, whether you use `string->number` or not! What behavior makes sense in cases 2 and 3 (or maybe it makes sense to break 2 into smaller cases) is going to depend on your particular use case. Maybe it makes sense to return a default value. Maybe you just want to raise an exception.

If we write a version of your `myconversion` function with a placeholder (again in the spirit of HtDP), we might do something like this:
#lang typed/racket
(: myconversion (-> String Integer))
(define (myconversion str)
  (define rslt (string->number str))
  (cond
    [(exact-integer? rslt)
     rslt]
    [else
     ;; TODO
     ...]))

This is where Ben's suggestion of `exact-integer?` is useful: thanks to Typed Racket's occurrence typing, the type system knows that, in the "then" branch of the conditional, `rslt` must have the type `Integer` because it satisfied the `exact-integer?` test. (Note that the `Integer` type corresponds to `exact-integer?`, not `integer?`.)

We still need to fill in the "else" branch to handle the case that the string didn't represent an integer. In your latter example, you raised an exception, which is a sensible choice. Here's an idiomatic way to do that:
#lang typed/racket
(: myconversion (-> String Integer))
(define (myconversion str)
  (define rslt (string->number str))
  (cond
    [(exact-integer? rslt)
     rslt]
    [else
     (raise-argument-error 'myconversion
                           "a string representing an integer"
                           str)]))

One thing to observe is that this is exactly the way you would have implemented such a function in untyped `#lang racket`: only the single type annotation is different. Much of the reason is that Typed Racket works hard through features like occurrence typing to be able to typecheck the kinds of programs you would idiomatically write in untyped Racket. In this particular case, though, it also reflects the fact that there isn't a type for "strings that can be parsed as integers." There's a potential for dynamic failure here that the static type system may help you to manage, but ultimately can't escape. (Ignoring for the moment fancier type systems that are mostly still research projects.)

Your problem with `sweet-exp` is a different one. I'm not familiar with `sweet-exp`, so I can't really help you, but it looks like either a bug or a known limitation in the concrete syntax `sweet-exp` supports. I will note that the lambda function you use in that example would be a syntax error in `#lang racket`.

-Philip


--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/89f338be-f574-44b5-82d4-23f833ec14ac%40googlegroups.com.

Alain De Vos

unread,
Feb 11, 2020, 2:09:31 PM2/11/20
to Racket Users
To unsubscribe from this group and stop receiving emails from it, send an email to racket...@googlegroups.com.

Alain De Vos

unread,
Feb 11, 2020, 2:15:18 PM2/11/20
to Racket Users
Philip,
For the last part,
I will make my work through,
convert a string to collection/list of characters,
this to a collection/list of numbers with a value 48 subtracted i think,
this to the correct end value base10.
I have no complex numbers to deal with.
But at each step I should raise , this is not ok.
Otherwise the GUI just keeps eating memory ...

Alain De Vos

unread,
Feb 11, 2020, 2:50:33 PM2/11/20
to Racket Users
Very basic question, first step first, how do i convert a string astring to a list of characters,
#lang typed/racket
(require typed/racket/gui)
(: astring String)
(define astring "1234567890")

Alain De Vos

unread,
Feb 11, 2020, 3:28:11 PM2/11/20
to Racket Users
In C I would would do some very simple pointer arithmetic, but racket leaves me into the blue.
Documentation, which is fine, compared to other lisps, fyi chez, leaves me into the blue.
0) Given a string,
1) convert to  a list of characters,
2) allow me to iterate,
3) convert a character to an int ,
4) subtract corresponding value of zero,
5) allow me to some positional stuff and addition.
But first i need a list of characters. :)
Does the language has a conversion operator ?

Sorawee Porncharoenwase

unread,
Feb 11, 2020, 3:49:50 PM2/11/20
to Alain De Vos, Racket Users

You can convert a string to a list of characters by using string->list. The code snippet that you presented in your very first post also uses this function.

> (string->list "abc")
- : (Listof Char)
'(#\a #\b #\c)

What I want to ask you though is what is wrong with the code that Phillip suggested? The code is the most standard way to write a function to convert a string to an integer. Have you tried it?

(: myconversion (-> String Integer))
(define (myconversion str)
  (define rslt (string->number str))
  (cond
    [(exact-integer? rslt)
     rslt]
    [else
     (raise-argument-error 'myconversion
                           "a string representing an integer"
                           str)]))

--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/54b2884c-6d93-44ad-b34a-d68c110b73ec%40googlegroups.com.

Philip McGrath

unread,
Feb 11, 2020, 3:50:50 PM2/11/20
to Alain De Vos, Racket Users
On Tue, Feb 11, 2020 at 3:28 PM Alain De Vos <devosa...@gmail.com> wrote:
But first i need a list of characters. :)
Does the language has a conversion operator ?

On Tue, Feb 11, 2020 at 3:28 PM Alain De Vos <devosa...@gmail.com> wrote:
0) Given a string,
1) convert to  a list of characters,
2) allow me to iterate,
3) convert a character to an int ,
4) subtract corresponding value of zero,
5) allow me to some positional stuff and addition.

If you really want to implement the algorithm you described, here's one way to do it:
#lang typed/racket

(: string->integer (-> String Integer))
(define (string->integer str)
  (define base (char->integer #\0))
  (for/fold ([acc : Integer 0])
            ([char (in-string str)])
    (+ (* 10 acc) (- (char->integer char) base))))

Again, I actually would do this with `string->number`, as I illustrated earlier, unless this arithmetic with Unicode scalars is really what you want to compute. For example, what about "-"?

On Tue, Feb 11, 2020 at 2:15 PM Alain De Vos <devosa...@gmail.com> wrote:
But at each step I should raise , this is not ok.
Otherwise the GUI just keeps eating memory ...

I don't understand what you mean here. Raising an exception should not cause a memory leak. If you mean that it makes the GUI non-responsive, then you should catch the exception and show a message to the user (or do the equivalent using a designated "bad value" instead of an exception).

-Philip

Alain De Vos

unread,
Feb 12, 2020, 7:43:47 PM2/12/20
to Racket Users
I came to the following result as conversion function :

#lang typed/racket
(: string2value (-> String Integer))
(define (string2value astring)
  (define (fun [val : Char] [res : Integer])
    (+ (* 10 res) (- (char->integer val) 48)))
  (foldl fun 0 (string->list astring))
)
(print (string2value "12345"))




On Tuesday, February 11, 2020 at 11:34:16 AM UTC+1, Alain De Vos wrote:

John Clements

unread,
Feb 15, 2020, 1:37:19 PM2/15/20
to Alain De Vos, Racket Users
??

> (string2value "-1234")
- : Integer
-28766
> (string2value "abcd")
- : Integer
54562
>

Is this your desired behavior?
> --
> 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...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/3e58a927-c05a-4688-984c-1750fb014624%40googlegroups.com.



John Clements

unread,
Feb 15, 2020, 1:40:53 PM2/15/20
to John Clements, Alain De Vos, Racket Users
Did anyone suggest this code to you? Apologies if I’m re-treading an old conversation.

#lang typed/racket
(: string2value (-> String Integer))
(define (string2value str)
(define maybe-integer (string->number str))
(cond [(exact-integer? maybe-integer) maybe-integer]
[else (error 'string2value
"expected a string convertible to an integer, got: ~e"
str)]))


Best,

John Clements
> To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/f6d3c6ef-8779-4e91-956f-d82eb11bbbbb%40mtasv.net.



Reply all
Reply to author
Forward
0 new messages