Quick Q: In Typed Racket, is it possible to specify a type of non-empty string?
There’s probably a better way, but this seems to work:
#lang typed/racket/base
(module non-empty-string racket/base
(provide
make-non-empty-string
non-empty-string?)
(define (make-non-empty-string s)
(cond
[(string=? s "") #f]
[else s]))
(define (non-empty-string? s)
(not (string=? s ""))))
(require/typed 'non-empty-string
[#:opaque NonEmptyString non-empty-string?]
[make-non-empty-string (String -> (Option NonEmptyString))])
so the only way to construct a NonEmptyString
is by calling the make-non-empty-string
constructor.
I came up with a similar solution, one of the downsides is that you cannot call any string-*
functions with a NonEmptyString. One possibility is to use define-new-subtype
but that wasn’t quite working for me.
does racket have an equivalent of the pass statement in python?
Are you referring to: https://www.tutorialspoint.com/python/python_pass_statement.htm
yes
Racket is expression based, so there is no “skip statement”. However inside a begin
-form you can use (begin)
to produce an expression that will be skipped.
Sometimes (void)
is used as a dummy expression. It’s depends on the context what the right solution is.
Thanks for the answers. I like the first idea but not being able to use the string functions in my case would be a deal breaker. I’ll look more into define-new-subtype
You can export renamed versions of the string functions that you need that can safely operate on NonEmptyStrings from the submodule.
I would think it’s desirable for NonEmptyStrings not to automatically be usable with normal string functions since some of them have the potential to break the invariant (eg. substring
)
alternatively, you could rename values
to non-empty-string->string
and import it from the submodule as (NonEmptyString -> String)
and explicitly convert before using the string functions, assuming you don’t care about preserving strings’ non-emptiness
To follow up on @soegaard2’s answer, begin
can be a bit confusing because it behaves differently depending on the context. In contexts that allow for mixed definitions and expressions, begin
is spliced into the surrounding context, so an empty (begin)
is effectively spliced as “nothing”. This is mostly useful as a form for macros to expand into. In an expression context, though, begin
forms an expression that evaluates to the value of its last subexpression, and (begin)
is not allowed: so, for example, (println (begin))
is a syntax error. If you specifically want an expression that does nothing, (void)
is the canonical choice, mostly because the void value is ignored by the default printer: otherwise, you could just as well write #t
. Really, though, if you find yourself in a situation where you are looking for an expression that does nothing, it’s usually a sign that there’s probably a more idiomatic way to write your code. For example, rather than write (if (condition) (void) (do-work))
, you could instead write (unless (condition) (do-work))
.
thanks for the insight I’ll keep it in mind
What’s the easiest way to run a function every n minutes I tried using sleep to run it every 5 mins but it didn’t run until 9 minutes later
sleep
should do it, provide that your function runs quickly and not like several seconds
If the function takes long time to run, you can also use threads to help
#lang racket
(define (long-computation)
(printf "Running at ~a\n"
(- (current-seconds) start-time))
(sleep 5)
(printf "foo bar at ~a\n"
(- (current-seconds) start-time)))
(define start-time (current-seconds))
(let loop ()
(thread long-computation)
(sleep 10)
(loop))
Outputs:
Running at 0
foo bar at 5
Running at 10
foo bar at 15
Running at 20
foo bar at 25
Running at 30
foo bar at 35
the the function i want to calls two other functions if I use sleep on it it ends calling the other two functions multiple times
That doesn’t sound correct. Can you provide your code?
Or a minimal code that exhibits the issue.
I removed the sleeps
I see. This is very helpful thanks a lot! :slightly_smiling_face: