maybe i need to re-think my function lol… in short i need to flatten out a variation of lists because my function takes in everything as a rest
Can you use flatten
?
ill check tomorrow
think i tried that before and it didnt cover all the cases i need. honestly im just calling the function in too many werid ways lol
thanks guys
When using classes in racket, is it normal to throw exceptions when an object is created if the initialisation values are invalid?
It’s normal to throw an exception to indicate an unusual situation.
Thanks, I thought it would be sensible.
You can also use contract to do this
Specifically on the “An initialization argument contract”
Ah good thought, thanks.
@mflatt I want to check an existence of a submodule. I know that module-declare?
exists, but it seems that to get it working, I need to set load?
to #t
. Otherwise, it won’t work. Is there an alternative way that doesn’t involve module loading? Thanks!
Found a workaround. I will let it load, but in a new namespace. This way, when I dynamic-require
, it will load again.
Context: I am modifying the compiler to collect some statistics, so when loading happens is kinda important
Weird. I thought (call-with-values (lambda () (void)) list)
would be '()
but in fact it is '(#<void>)
. I thought void meant 0 values.
<void> is the invisible value - the default printer doesn’t print it - except as part of a compound value.
Yeah, AFAIK, (void)
is a single value that is handled specially by the printer to print nothing.
That’s why it’s possible to write (define x (void))
. If it’s multiple values (0 values), then that would be an error
E.g., (define x (values))
fails.
I thought there was supposed to be a correspondence between function parameters and return values. And just like a function can accept zero values, it can return zero values.
using (void)
above is maybe a red herring. (call-with-values (lambda () (newline)) list)
also produces not '()
but '(#<void>)
.
I can think of a couple of reasons. 1. The convention of returning #<void> instead of “no values” is older than the introduction of values
. 2. A single value (#<void>) is probably easier to handle for simple interpreters/compilers.
read-eval-print-loop
is, modulo some continuation prompt handling, simply (call-with-values (lambda () ((current-eval) ___))
(lambda results (for-each (current-print) results)))
(print (void))
prints #<void>
. It does not print nothing.
@sorawee ^
Oh, I meant the top-level printer
Ditto.
((current-print) (void))
((current-print) 1)
> (void)
I mean I thought why the REPL prints nothing is because results
is the empty list
Not because of anything about current-print
.
I thought I “knew” something basic about call-with-values
and multiple values and I’m surprised/confused.
Well, it is surprising when you stumble upon it the first time.
I guess another reason that it’s not done in that way is that, (when #f 1)
evaluates to (void)
, and (when #t 1)
evaluates to 1
. Some people might write (define x (when b 1))
, and this would cause an error if b
is #f
and (void)
is 0 values.
Though, arguably, no one should use the result returning from when
.
Although it is printer related, the page on void
could mention that the value isn’t printed: https://docs.racket-lang.org/reference/void.html
So to summarize my new understanding: (call-with-values (lambda () (values)) list)
is ()
. Substitute anything other than (values)
in that expression, and it will be a non-empty list.
That sounds right.
Things like default-print-handler
or pretty-printer
(some typical values for current-print
) do the (void? _)
check.
DrRacket can be configured to print #<void>
instead of suppressing it; once you do that, you’ll see #<void>
everywhere.
My own impression is that (values)
meaning no values convention is older than using (void)
to mean a non-printed value, but I don’t have any citations to back that up. Over time I’ve gathered that since Racket is primarily an expression-oriented language, having expressions evaluate to no value when they’re embedded in contexts expecting a value create a lot of problems, especially if one is writing macros expanding to expressions within expressions so that lead to the convention of a non-printed value to represent “nothing important to see here”
there’s extensive discussion about this topic in the r6rs-discuss archives
good to know there’s historical documentation available to dig up
Is #<void>
Racket’s null
? :simple_smile:
Depending on what you are doing, you may want to be working at the level of module code instead of module declarations, in which case get-module-code
is the way to go.
ducks
chickens
chicken chicken chicken, chicken chicken.
@greg no we already have a null
:stuck_out_tongue:
uses valuable quarantine time to work on a print-handler that emits things like #<angry void>
and #<undefined goose>
Does it activate the 1st of April?
Yes, 364 days should be enough QA time to prepare the release
A little late, but…
No, that’s not correct. Consider this program:
#lang racket
(define (returns-no-values)
(values))
(call-with-values (λ () (returns-no-values)) list)
@greg If you want my two cents (you probably don’t): values is a neat idea: let’s generalize the notion of “returning a value” to “returning an unknown number of values”. Oh, look: it’s really neat how this works with continuations! A function that returns multiple values corresponds to a continuation that accepts multiple values. Except that… the overwhelming majority of expressions don’t expect multiple values, so using multiple values (including no values) requires special effort on the part of your caller, so in practice we never use multiple values. This is a bit unfortunate, because there are many situations where we wind up building an ephemeral list or vector just to return two values. I think the elegance of the match between continuation arguments and return values wound up blocking a more pragmatic solution that would allow people to return multiple values without allocation in everyday situations without causing headaches for users. Again, random spewage from me; I’d love to hear what more thoughtful people think.
@soegaard2 many thanks for pointer.
Also consider this program:
(define (loop) (loop))
(call-with-values (λ () (loop)) list)
@jbclements this question is a follow up of https://stackoverflow.com/questions/60962884/stepping-back-in-drracket-stepper which asks how to step to the step before the end. The author actually knows how to step to the end already.
Nice. You could also exit with an exception caught above and return something else