hazemalhalabi
2020-2-29 16:00:49

Quick Q: In Typed Racket, is it possible to specify a type of non-empty string?


popa.bogdanp
2020-2-29 17:55:44

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))])


popa.bogdanp
2020-2-29 17:56:12

so the only way to construct a NonEmptyString is by calling the make-non-empty-string constructor.


samdphillips
2020-2-29 18:01:32

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.


brentgordon146
2020-2-29 18:45:00

does racket have an equivalent of the pass statement in python?


soegaard2
2020-2-29 18:46:27

brentgordon146
2020-2-29 18:48:22

yes


soegaard2
2020-2-29 18:48:38

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.


soegaard2
2020-2-29 18:49:46

Sometimes (void) is used as a dummy expression. It’s depends on the context what the right solution is.


hazemalhalabi
2020-2-29 20:32:08

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


popa.bogdanp
2020-2-29 22:22:31

You can export renamed versions of the string functions that you need that can safely operate on NonEmptyStrings from the submodule.


popa.bogdanp
2020-2-29 22:23:16

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 )


popa.bogdanp
2020-2-29 22:27:48

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


philip.mcgrath
2020-2-29 22:31:49

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)).


brentgordon146
2020-3-1 01:08:27

thanks for the insight I’ll keep it in mind


brentgordon146
2020-3-1 02:11:07

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


sorawee
2020-3-1 02:18:35

sleep should do it, provide that your function runs quickly and not like several seconds


sorawee
2020-3-1 02:19:28

If the function takes long time to run, you can also use threads to help


sorawee
2020-3-1 02:25:17

#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))


sorawee
2020-3-1 02:25:26

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


brentgordon146
2020-3-1 02:39:10

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


sorawee
2020-3-1 02:43:54

That doesn’t sound correct. Can you provide your code?


sorawee
2020-3-1 02:44:07

Or a minimal code that exhibits the issue.


brentgordon146
2020-3-1 02:51:39

brentgordon146
2020-3-1 02:52:13

I removed the sleeps


hazemalhalabi
2020-3-1 03:20:43

I see. This is very helpful thanks a lot! :slightly_smiling_face: