Dealing with functions which may return values of different types


I mean such functions like regexp-match. Here's a fragment of my code:

  (let ([o-neal (regexp-match #px".*?'([^']{1})" str)])
    (if (not (equal? o-neal #f))
        (list-ref o-neal 0)

It works, but I'd be surprised to learn that this is the right and idiomatic way do it.

If you really want to use pure regexp-match, then what you have is pretty reasonable, though I would have written it as:

(define o-neal (regexp-match #px".*?'([^']{1})" str))
  [o-neal (first o-neal)]
  [else ...handle-failure...])

As the style guide recommended:

  • Prefer define to let.
  • Prefer cond to if.

And (not (equal? o-neal #f)) can be simplified to just o-neal.

You can “improve” this a bit by using pattern matching:

(match (regexp-match #px".*?'([^']{1})" str)
  [#f ...handle-failure...]
  [(list v _ ...) v])

But in that case, you might as well just use the regexp pattern in match:

(match str
  [(pregexp #px".*?'([^']{1})" (list v _ ...)) v]
  [_ ...handle-failure...])


Beautiful! Thank you very much!

It's even overwhelming a bit... How would you refactor the whole function?

(define (initial-create str)
  (let ([o-neal (regexp-match #px".*?'([^']{1})" str)])
    (if o-neal
        (car o-neal)
        (let ([stub (name-prefix str)])
          (if (equal? stub (string-replace str "'" "")) (string-upcase (substring str 0 1)) stub)))))

Not @sorawee, obviously, but since you asked about the #; in another thread, I thought it might be interesting to show off some of Racket's other interesting "reader magic":

(define (initial-create str)
  (define o-neal (regexp-match #px".*?'([^']{1})" str))
  (cond [o-neal (car o-neal)]
         (define stub            (name-prefix str))
         (define |str without '| (string-replace str "'" ""))
         (cond [(equal? stub |str without '|)
                (string-upcase (substring str 0 1))]
               [else stub])]))

The interesting part here, is |str without '|, which is a delimited sequence of characters which can be referenced, for example, like any other identifier.


Yet another nice surprise! Unfortunately, too good for the editor, which looses its bearings (VScodium) :joy: .