In some projects I’ve tried a naming convention where structs are Capitalized. (Similar to how Typed Racket capitalizes types.)
It seemed fine; I didn’t love it or hate it. (I think I might be more likely to use or recommend it, in a project where the struct names are a bigger proportion of the code. But I’m not sure.)
@notjack What do you do for something that is naturally just one word, like “apple”? Add a placeholder word?
Wow I ended up on wikipedia for “lorem ipsum”, which had a link to “metasyntactic variable”, which in turn had a link to “smurf”. I had no idea.
Although I knew what a Smurf looked like, I had no appreciation for their language. TIL. :slightly_smiling_face:
That seems like the right idea to me. cc @hazel
@greg Capitalized type names are also common in the signatures in HtdP.
Did you do anything special with the accessors? For example, if I define a (struct Board (data))
, the default accessor would be Board-data
. On the other hand, I have defined board-ref
as a regular function taking a Board
as first argument, and I’m unsure if having the capitalized names only for the accessors is a “bug” or a “feature.” That said, I guess I’d be ok with using the default naming for the accessors and lowercase names for my own functions that do something with the struct instances.
What do you think?
By the way, if I use a prefix word for the struct, I’d probably be even more confused whether the names of my functions working on the struct instances should have the prefix, too.
I found that capitalized struct names actually helped with accessors when the struct name includes hyphen. e.g. chess-board-width-pixels
. Quick, is struct chess
the struct and board-width-pixels
the field? Or is is chess-board
and width-pixels
? It’s clearer with Chess-Board-width-pixels
. Arguably uglier, but clearer.
Sometimes it’s just a sea of undifferentiated hyphens.
I guess a struct
option to use something other than -
might help more.
Like I said, I don’t have a strong opinion here — I’m getting too old for strong opinions about these things :slightly_smiling_face: — but I think some of these options can be clearer. Ultimately it depends on the audience. If a project is a team, whatever they agree to, is “best”.
> I guess a struct
option to use something other than -
might help more. Totally agreed.
Maybe emdash would be a better struct
default (I’m only half-joking)
@greg In my case it’s a personal project, but I can’t stop thinking about good design nevertheless. :smile: Also, I’m the audience of my software, so it’s important how well I find my way around it. :slightly_smiling_face:
Oh for sure! I’m not belittling your interest in that. I still get picky about that, too. I just can’t justify my choices to someone else, too seriously, anymore. :slightly_smiling_face:
I want to write a for/...
loop and exit it as soon as an expression calculated in the loop body is “true-ish.” The result of the loop should be this calculated expression.
My current approach looks like this: (for/last ([guess (in-range 1 (add1 9))]
#:break candidate-solution)
...
(define candidate-solution
(if ...
something-true
#f)))
but I get a stacktrace complaining that candidate-solution
is an unbound identifier.
Is it possible to write such a loop with any of the for/...
forms and if yes, how?
#lang racket
(for/last ([i (in-range 100)])
(define candidate (* i i))
#:break (> candidate 50)
(list i candidate))
@sschwarzer ^
@samth Aha, I wasn’t even aware I could use #:break
inside the loop body. I always thought it has to be in the “head” of the for
form.
I’ll give it a try.
I can’t tell yet if it works correctly, but at least I don’t get any error messages about how I write the for
loop.
What I needed was #:final
instead of #:break
, but otherwise it worked. :slightly_smiling_face:
Woah. I didn’t know that either. I kept pushing things up into the sequence block using in-value
I think you need to do that for #:when
.
Ahh yes, most of the time I’m using #:when
so doesn’t change my behavior that much.
@samdphillips Can you show an example?
Actually was tweaking this code this morning (define (all-procinfo)
(for*/list ([rel-pid-dir (directory-list "/proc")]
[a-path (in-value (build-path "/proc" rel-pid-dir))]
#:when (pid-path? a-path))
(procinfo a-path)))
My solver works. :tada: https://git.sr.ht/~sschwarzer/sodoku-solver/tree/main/item/sodoku-solver.rkt#L215 (Yes, this can probably made faster, but it was more important for me to have clear code than the fastest possible implementation, in which case I would have done some things differently.)
This was an exercise from an online course I attended last week.
Related: does Racket have anything like Clojure’s reduced? https://clojuredocs.org/clojure.core/reduced Useful when short-circuiting “loops” built out of fold/map/filter idioms, e.g., like this state-machine: https://gist.github.com/benknoble/f6d157217a7a814450d6fc9cf45625ee#file-parens-clj
> @notjack What do you do for something that is naturally just one word, like “apple”? Add a placeholder word?
Suffer
Generally, you can use continuation, like let/ec
or let/cc
.
(let/ec reduced
(foldl (λ (v a) (if (< a 100) (+ a v) (reduced 'big))) 0 (range 10)))
(let/ec reduced
(foldl (λ (v a) (if (< a 100) (+ a v) (reduced 'big))) 0 (range 20)))
Maybe resyntax
should suggest pushing #:break
into the body sometimes?
You could also use reducers, but it would be bulkier
Within for
-like forms, #:final
could potentially work.
(for/fold ([a 0]) ([v (in-range 10)])
(define condition (< a 100))
#:final (not condition)
(if condition (+ a v) 'big))
(for/fold ([a 0]) ([v (in-range 20)])
(define condition (< a 100))
#:final (not condition)
(if condition (+ a v) 'big))
If the advice is appropriate most of the time, this sounds like a good idea. :+1:
I think I’m going with the capitalized types for now. :slightly_smiling_face:
I’ve yet to come up with naming conventions that I like. Sometimes, I’ll use mathematical conventions, using single letters and symbols; sometimes, single words; sometimes, short phrases.
@notjack Don’t suffer. I recommend apple-smurf
. Seems weird? Give it time to grow on you. In fact, maybe start by really leaning in with names like apple- SMURF!
.
Or if the struct has any mutable fields, apple-SMURF!!
Nuances like that are what give a great naming convention that special obsessive frisson.
so a predicate for a mutable struct would clearly be apple-SMURF!?
, correct?
I think actually apple-SMURF!!?
. But we should have a week-long 40-message email thread about it, to be sure.
clearly, community consensus is important
Is the type in there? Company policy says we must use hungarian notation.
Do things like <%>
or /c
count as Hungarian Notation, or are those sigils? Maybe someone should make a Grand Unified Theory of Name Ornaments…
@sschwarzer for/or
also does precisely what you asked
eg. (for/or ([i (in-range 100)])
(define candidate (* i i))
(and (> candidate 50) (list i candidate)))
Do we have an in-map
? (for/or ([c (in-map sqr (in-range 100))])
(and (> c 50) (list i c)))
there’s a sequence-map
Is that “inlined” when used with for?
good question