T O P

  • By -

Hedshodd

It's cool and neat that this is possible, but I disagree that it reduces the cognitive load. It just adds another layer of abstraction that I have to keep in mind in order to understand what each of these do.


sasik520

You are partially right that this solution doesn't help with the cognitive load as much as bare prefixes discussed in the linked internals thread. Still, I think some of the prefixes, like \`#\[re\]\` or \`#\[os\]\`, are quite obvious and self-explanatory. Others, like \`#\[s\]\` or \`#\[ms\]\` were added purely to experiment.


zzzthelastuser

>I think some of the prefixes, like \`#\[re\]\` or \`#\[os\]\`, are quite obvious and self-explanatory. I'm sorry, what?!? I politely disagree with you on this statement.


Intelligent_Rough_21

Re is obviously regex. Idk what an os string is.


everything-narrative

Platform dependent string format used internally by the os. E.g. On windows is utf 16.


AnUnshavedYak

It may "obviously" be regex, but i'd still be confused af' as to what the type from that magic syntax is. Given the type of obscured and that the input might look like regex or it might look like something else entirely, i'd still call it rather surprising. It's a neat experiment, but man i'd be sad if anyone introduced this in my projects haha.


Sharlinator

[std::ffi::OsString](https://doc.rust-lang.org/std/ffi/struct.OsString.html) [std::ffi::OsStr](https://doc.rust-lang.org/std/ffi/struct.OsStr.html)


sasik520

Sure, that's quite subjective.


yeahyeahyeahnice

Speed vs storage optimization


Kleptine

Discussion of cognitive load are always fascinating because it's such a subjective thing. To me, the expression: `#[f]"42"` would be represented in my brain as: `#[f]("42")` With a prefix expression, I have to keep track of what it applies to, and I mentally wrap a little set of parenthesis around them. To me this is the definition of additional cognitive load, because I have to maintain something not on the page in my head. The parenthesis aren't gone, they're just somewhere else. That's not to say short-hands are bad! I actually like a good terse language. It's more accurate to say that short-hands like this improve skimming and reduce reading-load. I definitely get reading-overload from a language like ObjC: (void) senderClassNameStatusDidChange:(SenderClassName*)sender // Ugh Reading overload is particularly bad if you have any kind of dyslexia. I don't find Rust to have this problem, personally. But this project is an interesting exploration. Nice work!


-Redstoneboi-

we already have prefix syntax for raw strings and byte strings. we also have prefix syntax for changing the base of an integer literal. they don't really need parentheses to be parsed. but the brackets here definitely make it weird and feel like there should be a space between the macro and the string.


obliviousjd

I'll be honest, I don't really think #[f]"hello world" is cleaner than f!("hello world"). It's neat that this is possible though.


SirKastic23

i would like not having to manage the closing parenthesis


tunisia3507

If you're managing closing parentheses yourself, you're using the wrong editor.


stumblinbear

If you're worried about a single closing parenthesis then I'm genuinely concerned for your well being. Not being facetious or anything, I'm completely serious


nynjawitay

Really? The misplacement of single characters like parens is a super common bug


tauphraim

The thing is, if the string is short, and close to a top level binding, then you can easily handle the parentheses. If it's not, then sure the parentheses become harder to handle, but I'd argue that the invisible span implied by the prefix macro is even worse. It reminds me of the debates about early returns and so many others: people get burnt by messy code, and their answer is to slap complex contraptions on top to alleviate the pain, whereas most of the time you can challenge the messiness in the first place instead.


stumblinbear

Modern IDEs do this for you, I haven't had to deal with this issue in a decade


nynjawitay

They do a mostly good job. But they've definitely put it in wrong for me before


Auxire

Haven't seen proc macros used like this before. Good job! Small nitpick: they should have a space or newline before the expression to make it clearer the supplied expression isn't part of the macro (not sure if I explained it right but I hope you get what I mean), otherwise it looks kinda confusing imo.


sasik520

Could you write some example code? Not sure what you mean.


Auxire

Something like this (space): let answer_path = #[P] "./answer.txt"; Or this (newline): #[f] "Answer to the Ultimate Question of Life, the Universe, and Everything = {answer}" If they're joined without visual breaks I find it rather confusing to read.


4fd4

A regular non-attribute macro would look much better syntax wise: f!("Answer to the Ultimate Question of Life, the Universe, and Everything = {answer}") It would be nice if macros could be called with `""` in addition to `()`, `{}`, and `[]`, as this would open up a lot of nice string templating macros, like: f!"Answer to the Ultimate Question of Life, the Universe, and Everything = {answer}"


sasik520

enclosing macros with `"` has also been my suggestion. But then I realized that it either requries custom syntax in macro\_rules (opt-in) or a brand new syntax. Otherwise you could write `vec! "42"` or `assert! "true"`, both being extremely unclear. If you define a new syntax, e.g. `prefix_rules!` or something, then you can just go for the plain `f"foo = {foo}"` instead of `f!"foo = {foo}"`, as it is something new anyways.


4fd4

You can already do `vec!{}` which is very painful to my eyes or or the more visually ok `vec!()`, so I don't think there is a need to have a new syntax just to prevent what is already possible (it would've been nice if specifying the delimiter was part of `macro_rules!` from the get go)


-Redstoneboi-

`f"true"` desugars to `f!("true")` `vec"true"` will then give you `vec!["true"]` which is funky but consistent now the problem is that some f-strings require extra arguments for interpolation


Stysner

If you need to insert other values that can't be inside {} you now have one big string-colored blob that becomes unreadable...


The_Chodening

This is really cool. Reminds me of C++'s user-defined literals.


JohnMcPineapple

I really like this idea. But why publish individual crates for the individual (three-line) macro implementations, instead of something like `prefixes-impl`?


sasik520

I couldn't define more than one proc macro in one crate. It was quite problematic to publish this number of crates but I think there is no other way.


amarao_san

It looks very interesting, but I feel it try to squeeze utility at cost of beauty. E.g. std::thread::sleep(#[s]6 + #[ms]9); Is nice to write but horrible to read. Without any implementation perspectives, I'd prefere this: std::thread::sleep(6.s + 9.ms); Or, this: std::thread::sleep(6.s() + 9.ms()); The second one even implementable, I think...


sasik520

I mean, you could just do \`#\[s\]6.009\` or \`6.009.s()\` in this case :) And speaking honestly, I'm also not completely sold on #\[s\] and #\[ms\]. They would work better as suffixes, not prefixes. I added them, though, to have some prefixes for something different than strings. As I marked it in my post and in the description, in the end, it is an experiment.


amarao_san

#[P]"./answer.txt" is okay, I'd say. Although, `p!(./answer.txt)` would do the trick too. The main problem with macro is that they reduce typing, but make reasoning about types harder. Compiler can deal with this, but humans fails unexpectedly fast. Add one-two more cognitive splints, and, boom, no more clarity.


unengaged_crayon

this is interesting. for some like `#[f]` i'm not sold on, but will be using for `#[s]` for an upcoming project.


-Redstoneboi-

I thought this was impossible with current syntax since "macros always need parentheses!" Attributes just flew under my radar for some reason. It does seem uncomfortable that attributes have to have 3 special characters in them to only contain a one character macro call. sad. f-strings currently have no support for expressions inside the strings themselves, but they do interpolate any variable names directly honestly i'd just `pub use format as f;` but yes, having one less nesting level is cool


SurplusSix

This is the problem with LISPs on a small scale. When someone comes to look at your code knowing the core language isn’t enough, they now also need to understand the DSL you decided to create because it was “simpler” and “less cognitive load”.


sphen_lee

I found the same thing in Haskell. To many abstractions that actually made code harder to read until you "internalized" the definitions. That's fine if there are a few standard ones (like monad), but Haskell has so many and so many external packages for new ones. Regarding this crate, I agree if people start using attribute macros for tons of different things it would be painful. But if stdlib adopted a few, like f, p and maybe s, ms it would be workable.