notjack
2021-2-4 12:46:07

Does anyone else wish that DrRacket indented this: (some-function (expression1 ...) (expression2 ...) (expression3 ...)) like this: (some-function (expression1 ...) (expression2 ...) (expression3 ...))


sorawee
2021-2-4 12:47:12

Why 3 spaces? (Or however many spaces you typed there?)


spdegabrielle
2021-2-4 12:48:03

Do you mean; tab, 4 characters, or aligned to the ‘-‘.?


spdegabrielle
2021-2-4 12:48:34

I agree it looks easier to read


mark.warren
2021-2-4 12:48:37

I don’t see why


notjack
2021-2-4 12:48:41

4 spaces (no tabs). My thinking: 1. 2 spaces for indenting nested blocks (things with internal definition contexts) 2. 4 spaces for indenting nested expressions


notjack
2021-2-4 12:51:24

@mark.warren hard to tell what the structure is when code is indented like this: (some-function (some-other-function (another-function ...) (yet-another-function ...)) (another-function ...) (you-guessed-it-another-function ...))


mark.warren
2021-2-4 12:52:29

Is it?


notjack
2021-2-4 12:53:15

yes, in my experience, especially when lots of code like that is mixed with nested lets and when the function arguments themselves take multiple lines


laurent.orseau
2021-2-4 12:56:06

I agree that 1 space only not enough, but I’m okay with 2 spaces in all cases. Syntax color does the rest to distinguish what kind of block this is


laurent.orseau
2021-2-4 12:56:23

4 spaces means you will drift much faster to the right


mark.warren
2021-2-4 12:56:46

2 spaces has always been my preference


notjack
2021-2-4 12:58:51

it goes to the right way slower than the usual racket approach does: (some-function (some-other-function (another-function ...) (yet-another-function ...)) (another-function ...) (you-guessed-it-another-function ...)) and I’m kind of alright with expression nesting going rightwards faster than block nesting does, since deeply nested expressions are harder to understand IMO (because fewer variable names and they can be nested in arbitrary ways rather than the relatively limited ways blocks are typically nested)


notjack
2021-2-4 12:59:58

if an expression I’m writing gets complicated the first thing I usually do is name some subexpressions and extract them into definitions


sorawee
2021-2-4 13:00:24

To be fair, the code you have shown above probably should really be rewritten as:

(some-function (some-other-function (another-function ...) (yet-another-function ...)) (another-function ...) (you-guessed-it-another-function ...))


mark.warren
2021-2-4 13:01:00

I hope this doesn’t sound abusive, but I tend to find if there is too much indentation then a function needs splitting up.


laurent.orseau
2021-2-4 13:01:19

and with 2 spaces: (some-function (some-other-function (another-function ...) (yet-another-function ...)) (another-function ...) (you-guessed-it-another-function ...))


mark.warren
2021-2-4 13:01:57

Looks good to me


notjack
2021-2-4 13:02:00

no I think that’s a totally reasonable statement, I just think there’s more ways to split things up than into separate functions. splitting up one expression into an expression and some definitions is a handy way to split things too.


laurent.orseau
2021-2-4 13:03:00

My hobby: Nesting for/fold in #:results


spdegabrielle
2021-2-4 13:04:07

Aside/ I like the idea of tabs - I recently read an article that argues they were better for the sight impaired as they allowed adjusting indentation at high magnifications. I don’t know if this is true? And in any case if you can adjust the reformat indentation you can get the same outcome with spaces


laurent.orseau
2021-2-4 13:04:55

Yeah, Racket should be more like makefiles :stuck_out_tongue:


notjack
2021-2-4 13:05:23

Tabs do have some useful accessibility features yeah. You can definitely get the same thing with spaces though as long as you aren’t using horizontal alignment.


sorawee
2021-2-4 13:07:15

I totally agree with @notjack on this one. The usual argument that people advocate for tab is that you can change tab size to fit reader’s need. But with a formatter, you can do the same with spaces.


sorawee
2021-2-4 13:08:10

It does require you to have more domain knowledge about the language.


laurent.orseau
2021-2-4 13:08:10

Tabs could be useful for alignement after the initial spaces, i.e.: <space>*[:code:]+\tab[:code:]+\tab[:code:] would tell that the next lines should indent on the tabs after the first code


mark.warren
2021-2-4 13:08:26

I’m a Java programmer by day and the tabs vs spaces argument is constant, as well as the indentation and bracket placement.


notjack
2021-2-4 13:08:51

I’m one too and luckily do not have to have that argument at all anymore


sorawee
2021-2-4 13:09:21

Not everyone works at Google lol


laurent.orseau
2021-2-4 13:09:38

@notjack hand over your webpages about all these to @mark.warren, they are nice rules


notjack
2021-2-4 13:09:53

the rectangle rule one?


laurent.orseau
2021-2-4 13:10:01

in particular, but the rest too


laurent.orseau
2021-2-4 13:10:07

(for java I mean)


spdegabrielle
2021-2-4 13:10:07

It was more about the sight impaired. Tabs are verboten in DrRacket


notjack
2021-2-4 13:10:12

struggling to think of what the others would be


spdegabrielle
2021-2-4 13:10:35

Style guide 6.3


laurent.orseau
2021-2-4 13:10:40

Can’t recall just now, but there are other pages


laurent.orseau
2021-2-4 13:11:16

Oh yeah, variable naming and such


notjack
2021-2-4 13:11:35

anyway this is the rectangle rule, it’s part of what google-java-format uses to figure out what formatting makes sense https://github.com/google/google-java-format/wiki/The-Rectangle-Rule


spdegabrielle
2021-2-4 13:11:47

There is a quickscript that does that! (With spaces)


mark.warren
2021-2-4 13:11:52

Hmm.. I just wish I could open a source file from someone else and it actually was readable.


laurent.orseau
2021-2-4 13:12:50

hehe, yes, but I used double spaces because it’s complicated to type tabs in DrRacket :wink:


sorawee
2021-2-4 13:13:06

My hypothesis is that with tabs, you will find that more source files will be unreadable


notjack
2021-2-4 13:13:31

the other useful guidance that formatter follows is “prefer to line-break at the highest level of syntactic nesting”, so instead of this: (some-function (some-other-function (another-function ...))) it would do this: (some-function (some-other-function (another-function ...)))


laurent.orseau
2021-2-4 13:14:19

I think indentation should require that every odd character is a non-breaking space, and the rest are tabs


spdegabrielle
2021-2-4 13:14:56

Is a double space a space that is as wide as two spaces but still a single character?


laurent.orseau
2021-2-4 13:15:07

it’s just two spaces


notjack
2021-2-4 13:15:11

big brain time


mark.warren
2021-2-4 13:15:43

@notjack I had a look at that guide and it looks even more unreadable than some of my colleagues code :grin:


laurent.orseau
2021-2-4 13:15:53

there’s a gui option if you want to choose a different separator


notjack
2021-2-4 13:16:18

it is deliberately showcasing difficult-to-format code :p


laurent.orseau
2021-2-4 13:16:24

but if everyone uses the same unreadable format, then suddenly it becomes readable :wink:


spdegabrielle
2021-2-4 13:17:09

Someone please stop @laurent.orseau :rolling_on_the_floor_laughing:


notjack
2021-2-4 13:17:12

there’s a lot more to readability than formatting. but it’s an easy-to-automate part, so.


mark.warren
2021-2-4 13:18:42

It would be nice if your IDE formatted the code in your preferred way but saved it in a non-formatted way, does that make sense?


notjack
2021-2-4 13:19:06

yes


laurent.orseau
2021-2-4 13:19:27

although sometimes (rarely) I open my code files with nano


notjack
2021-2-4 13:19:44

and I do like being able to read code in github with a browser


laurent.orseau
2021-2-4 13:19:46

So saving it in a ‘standard’ way would be best


mark.warren
2021-2-4 13:19:56

yes


sorawee
2021-2-4 13:20:25

I thought a tab in nano is 8 spaces?


sorawee
2021-2-4 13:20:35

Can it be adjusted?


mark.warren
2021-2-4 13:20:47

That’s terrible


laurent.orseau
2021-2-4 13:21:02

yeah, everyone knows 7 is ideal


notjack
2021-2-4 13:21:09

lucky nano isn’t your preferred editor I suppose


mark.warren
2021-2-4 13:21:11

indeed


yilin.wei10
2021-2-4 13:21:33

I think the ELisp if indentation is the weirdest.


laurent.orseau
2021-2-4 13:21:35

@notjack nah, it’s just convenient when CRD breaks :wink:


notjack
2021-2-4 13:22:04

what’s elisp if look like?


yilin.wei10
2021-2-4 13:22:14

(if nil 1 2)


notjack
2021-2-4 13:22:19

wh


notjack
2021-2-4 13:22:21

what


yilin.wei10
2021-2-4 13:22:29

lol


laurent.orseau
2021-2-4 13:22:34

(if if-false test if-true)


mark.warren
2021-2-4 13:22:34

?


sorawee
2021-2-4 13:22:39

It’s because the else position can have multiple forms


yilin.wei10
2021-2-4 13:22:43

chaotic neutral


sorawee
2021-2-4 13:22:51

(if nil 1 2 3)


notjack
2021-2-4 13:23:03

well that’s


laurent.orseau
2021-2-4 13:23:09

oh it’s because the else part is multi-expr


notjack
2021-2-4 13:23:12

an approach, certainly


laurent.orseau
2021-2-4 13:23:41

my my


laurent.orseau
2021-2-4 13:25:14

How about: (if test e1 ... #:else e3 ...)


laurent.orseau
2021-2-4 13:25:44

When I have a block in the if-true I often write ; else anyway


notjack
2021-2-4 13:26:18

y’know. cond lets you write else without it being a comment :p


notjack
2021-2-4 13:26:28

or do you mean in elisp specifically


laurent.orseau
2021-2-4 13:27:17

(if test (filter (...) auieauie) ; else ...)


laurent.orseau
2021-2-4 13:27:27

even for one-expr cases


laurent.orseau
2021-2-4 13:27:40

I’m not an unconditional fan of cond either


laurent.orseau
2021-2-4 13:28:04

unnecessary parentheses


notjack
2021-2-4 13:28:17

guard? :wink:


laurent.orseau
2021-2-4 13:28:33

if #:else ? :p


notjack
2021-2-4 13:28:52

if #:ELSE


laurent.orseau
2021-2-4 13:29:19

(if ... fi:# #:ELSE ... esle) ?


laurent.orseau
2021-2-4 13:29:52

(consistency is hard!)


notjack
2021-2-4 13:30:02

(if … #:ELSE … esle … fi)


laurent.orseau
2021-2-4 13:30:18

yah, that’s the one


laurent.orseau
2021-2-4 13:31:17

With nice error messages: missing esle in fi counterpart (also: missing fi in esle counterpart)


notjack
2021-2-4 13:34:24

call them categorical duals instead of counterparts, to really get the angry blog posts flowing


laurent.orseau
2021-2-4 13:35:16

good idea: missing esle in fi categorical dual (also: missing fi in esle outer disjunction)


laurent.orseau
2021-2-4 13:37:52

Did you mean: 'printf' instead of 'if'?


sorawee
2021-2-4 13:40:25

If we have a form that enumerates all bound identifiers at a position, we could write #%top that finds the closest id (via edit distance) and generates Did you mean: ....


laurent.orseau
2021-2-4 13:45:30

namespace-mapped-symbols?


sorawee
2021-2-4 13:45:43

That’s only for top-level symbols


sorawee
2021-2-4 13:45:52

Doesn’t include local binding


laurent.orseau
2021-2-4 13:45:52

that’s a start


laurent.orseau
2021-2-4 13:46:11

for this you can use read-syntax after the fact


laurent.orseau
2021-2-4 13:47:27

or even just (remove-duplicates (filter symbol? (flatten (read))) eq?)


greg
2021-2-4 14:09:51

@notjack IIUC one Lisp tradition is that there’s a distinction between function application and macro invocation.

Indentation for plain old function application is always the same style (that you dislike).

Whereas macros can define custom indentation.

I think this roughly maps to your 1 and 2 but I’m not sure?


greg
2021-2-4 14:10:49

I think there’s some value to letting macros define their indentation? Like say if or for/fold.


greg
2021-2-4 14:11:44

In some Lisps there’s a way for a macro’s indent metadata to be available for editors.


greg
2021-2-4 14:12:03

In Emacs Lisp I think it’s via the declare form, but I try really really really hard to avoid writing macros in Emacs Lisp. :slightly_smiling_face:


ben.knoble
2021-2-4 14:12:29

I’m not sure how I would go about transforming the mpi’s into that form, though.

Hm, I might give that a look. I have limited control; students submit a file (ostensibly beginning with #lang racket) which I dynamic-require to get certain vars (reasons). If require transformers need me to actually adjust the student code, that probably won’t work.


greg
2021-2-4 14:12:58

In other Lisps, users need to set this in their editor. Which is the case for Racket. Things like DrRacket and Racket Mode just come with a set of defaults for common macro forms. Which you can customize.


greg
2021-2-4 14:13:22

Racket could probably have a better story for this (for macros telling tools their indent).


greg
2021-2-4 14:14:45

TL;DR I think there are team and tool challenges to changing the indent style for plain old function application, but if people want to configure that, it’s a possibility. OTOH I think there’s some value to letting macros have the last word for how they get indented, or at least a strong suggestion.


ben.knoble
2021-2-4 14:20:33

If I understood that write, if I could change require to use my require-transformer, I could do… something… My use-case is just to collect all the things being required. sigh back to the drawing board.


shu--hung
2021-2-4 15:49:58

Yes. require transformers needs to be added to the code. If you don’t have control over the code, like #lang your-own-lang, what I have in mind is a hack is to modify the submitted code from: #lang racket .... to: #lang racket + (require your-library) .... where your-library shadows the require form and the module, module*, module+ forms: ;; your-library #lang racket (provide (rename-out [my-require require])) ;; my-require transforms (require &lt;req-spec&gt; ...) to (require (record-import-path &lt;req-spec&gt; ...)) then record-import-path is a require transformers saving the import paths.


shu--hung
2021-2-4 15:51:41

I don’t understand what happens to the module path index of submodules. A guess is that resolving the module path index turns it into the module path of its enclosing module, therefore module-&gt;imports returns the same list


capfredf
2021-2-4 16:00:11

@greg, If I kill 50+ racket buffers with racket-mode and racket-xp-mode on, is the memory footprint of the backend server expected to drop down?


ben.knoble
2021-2-4 16:01:33

Hm, that’s pretty clever. (Of course, I have to figure out how to record-import-path in such a way that I can get to it again later :thinking_face: )

Why shadow module/module*/module+? To insert the (require my-hack) again?


shu--hung
2021-2-4 16:03:22

Alternatively, if getting the list of all transitively required modules instead of just the immediately required ones also work for you, then intercepting current-load/use-compiled is yet a different hook. https://gist.github.com/shhyou/726d0542aef45b13981173a334a0202c


shu--hung
2021-2-4 16:04:18

Yes. Without shadowing module, module*, and module+, requires that indirectly goes through submodules won’t be tracked



ben.knoble
2021-2-4 16:10:17

Yeah, we’ve used sandboxes before. I’m hoping to avoid that here; it would require some infra changes I don’t want to deal with. I’ll take a look at that gist, thanks.


greg
2021-2-4 16:13:20


greg
2021-2-4 16:14:08

Do you have that yet?


greg
2021-2-4 16:17:13

Keeping in mind that, after a major GC, Racket doesn’t necessarily immediately release memory back to the OS, if you’re looking at ps or htop etc.


greg
2021-2-4 16:17:38

But also, with that commit, I expect the footprint would not grow nearly so large in the first place.


greg
2021-2-4 16:18:32

I was testing by opening a few dozen files in the typed-racket-more source, and I definitely improved that scenario.


greg
2021-2-4 16:18:58

But of course I don’t know for sure if you’re exercising something else that I don’t yet know about or understand.


greg
2021-2-4 16:19:07

@capfredf ^


shu--hung
2021-2-4 16:20:32

> shu—hung [9:51 AM] > I don’t understand what happens to the module path index of submodules. (For this issue, people on the Racket mailing list may be able to offer help)


greg
2021-2-4 16:22:16

Oh, to clarify: As of that commit, I wouldn’t expect killing the buffers, per se, to release memory. Instead I’d expect it to have been released long before that. Merely having the buffer open isn’t any kind of strong reference. Instead it’s the act of invoking check-syntax by e.g. editing a buffer, or other commands that need fully-expanded syntax.


greg
2021-2-4 16:22:39

A buffer just sitting there, existing, isn’t doing that. so killing it won’t change anything.


soegaard2
2021-2-4 16:23:54

Issue 512 involved quite some detective work, I see!


capfredf
2021-2-4 16:31:10

Ah I see. Thank you for the hard work


greg
2021-2-4 19:33:25

@capfredf Thanks for the thanks! Even so, with that commit, if you still see memory use that seems excessive, please don’t hesitate to let me know.


sorawee
2021-2-4 23:56:06

I think it’s worth trying out 2 spaces in actual code and see how it looks. What I fear is that it could cause confusion with existing forms that have 2 spaces indentation.

(lambda (foo) abc) (something bar)


sorawee
2021-2-4 23:58:42

Also, two spaces from where? It should already be taken for granted that inner forms must be indented by at least one space to align with the left parenthesis. So when you said two spaces, should it actually be three?


wanpeebaw
2021-2-5 04:54:12

Are there any tutorials on how to write embedded DSL syntax different from S-expressions?


samth
2021-2-5 05:00:40

Beautiful Racket talks about this


wanpeebaw
2021-2-5 05:52:23

I mean, an embedded SDL with syntax different from S-expression which can still be embeded into a S-expression language, let’s say Racket.


laurent.orseau
2021-2-5 07:13:52

I mean one more space, like your example above


laurent.orseau
2021-2-5 07:57:59

Different syntax in different files or in the same file?


laurent.orseau
2021-2-5 07:58:21

If the former, do look at Beautiful Racket


laurent.orseau
2021-2-5 07:59:16

If the latter, do that anyway and you’ll also need to change the reader locally (don’t recall what the name is right now)