r/rakulang•
raiph

RFC: `foo = 42`

SYNOPSIS

A new declarator:

foo = 42

Before you go with your immediate gut instinct and start formulating a reply, please take a moment to do something else to clear those initial emotions, and read the rest of this proposal. Thanks!

DETAILS

Currently a program with just:

foo = 42

yields:

SORRY! Error while compiling
Preceding context expects a term, but found infix = instead.
Did you make a mistake in Pod syntax?

What if instead it did an equivalent of this:

constant foo = 42

?

----

In existing Raku code, if foo is already declared in the lexical scope you'll get the same error unless foo has been declared as a term (sub term:<foo>).

In the latter case you'll still get an error (though at run-time) unless the term returns an assignable container.

In the latter case, if someone isn't aware of this foo = ... declarator syntax I'm proposing, it means they might accidentally write foo = 42 thinking they're creating a new foo "variable" when they're actually modifying an existing one.

I currently view this latter case as this proposal's biggest downside.

But:

  • I'm pretty confident it's a rarity -- each of the "latter case" scenarios is a small subset of the previous scenario.
  • If this proposal works as I hope it will, it'll be widely used so ought not lead the above problem/downside scenario to being a surprise.
  • Presuming it's introduced at a language version change (Eid), it'll get widely talked about, again reducing the chance it'll be a surprise.
  • Perhaps it can be semi-mitigated by introducing a warning for a first use of foo = ... where the foo is a term.

Overall I don't currently view this downside as a deal-breaker.

----

I've been mulling this for years as part of thinking about how to introduce better support for immutability into Raku. To the degree this idea is about immutability (it's also about some other things I'll get to later), this part is about ergonomics. I'm proposing this declarator is a "moral" equivalent of this:

constant foo = immutable ...

where immutable is (conceptually at least) a function that does one or other of:

  • Checks its RHS is entirely immutable, for some definition (TBD) of "checks" and of "entirely immutable". And, if the check fails, then something appropriate happens, eg it throws an exception.

or:

  • The same, except that it both coerces and checks its RHS. This might help reduce an awkward problem Raku faces when it "properly" introduces immutable types, to wit, what about literals? If foo = ... coerces, well, maybe that'll help.

Again, please consider keeping your open mind engaged, and reading on and mulling all I say in this comment before starting to formulate your overall response to this proposal / Request For Comments.

----

Brief tangent:

I also have ideas that are the flipside of the mutability coin, ways in which I see sigils becoming a remarkably strong and generally popular positive, even among some Pythonistas by virtue of them conveniently marking mutability.

But I think for now it's better that I keep the focus in this opening proposal comment on identifiers without sigils, without yet discussing how that could elegantly dovetail with generally using sigils to mark mutability.

----

Putting aside the topic of immutability/mutability and its ergonomics, another reason I arrived at this foo = ... syntax is my thoughts and feelings about sigils.

I love (Raku's strong support for) sigils.

I hate (Raku's weak support for high signal / low noise) sigils.

And, vastly more important than my loves/hates, I think and feel that vast swathes of the potential Raku user market dislike them and/or don't see their point.

What about me? More to the point, what about these people?

I've read Rakoons saying that if you don't like sigils you won't like Raku. I don't buy that argument, partly because I am a Rakoon, and partly because, while I see their upsides, I see their downsides too.

I've felt for over 20 years that Raku would best not ignore these problems forever. And indeed, Larry stepped in this direction with my \foo = ... and sub foo (\foo) .... These are much better than nothing. But they fall far short of the radical transformation in perception and reception I imagine Raku can evoke if it introduces a few (I hope) simple "tweaks", with the above described foo = ... being one of three things I have in mind.

----

Another reason I think this simple declarator is worthwhile is use in one liners. No need for no strict, and fighting with shell escaping of sigils -- just write foo = ....

----

A final thought for this introductory comment.

(I think that) all of Raku's identifier declarators are subject to shadowing.

For reasons I'm not going to try rationalize in this opening comment, I'm thinking this foo = ... idea will work best if it's non-shadowing and non-shadowable.

----

Thoughts? Feelings? Intuitions? Problems you see / forsee?

Posted Jan 26, 2022, 1:59 PM UTC

531
b2gills•

The problem is what if it was actually a typo.

my \food = $ = "apple";
food = "orange";
foo = "banana";

The correct course of action would be to produce a compilation error. Even if it was the wrong error.

There is a reason that Raku forces declarations to be explicit. It's because of all the errors caused by them being implicit by default in Perl over the years.

6
raiphOP•

Hi Brad,

Thanks for responding. :)

I'm well aware of that argument, and am happy it's on the table.

Ooc, did you read the whole proposal? If so, and you understood this declarator is designed to display a compile-time error if someone tries to use it to change the value of a variable, do you think people will use it to try to change the value of a variable?

2
b2gills•

Are you planning on removing functionality from the language?

Because you'd have to make it so that only the new feature can be written that way without sigils.

One of the great design features of Raku is that there are relatively few special cases to remember.

By doing the above you are going to force people to have to alias a non-sigilled to a sigilled variable in order to assign to it.

A better option in my opinion would be to make the my optional in my \foo =...

6
raiphOP•

Are you planning on removing functionality from the language?

No.

Because you'd have to make it so that only the new feature can be written that way without sigils.

That's not true.

my \foo = $ = 42;
bar = 99;

would be fine.

Of course, I get that the dangerous and ugly idiom you used would lose typo protection.

But is that such a bad thing?

Indeed, shouldn't we be considering deprecating it?

BTW, did you know:

One of the great design features of Raku is that there are relatively few special cases to remember.

Yes.

But that idiom is absolutely nothing to do with great design, but instead just my warped mind when I invented it.

And to make it threadsafe one has to write:

my \foo = my $foo = 42;

Imo, while my original idiom was bad, that is downright ugly.

Conversely, I like the way non-sigil'd identifiers are generally bound to fixed values, and sigil'd identifiers are generally bound to variable ones, and I'd like Raku to evolve toward further normalizing that rather than maintaining error prone oddities like the idiom I invented.

By doing the above you are going to force people to have to alias a non-sigilled to a sigilled variable in order to assign to it.

Why not just use a sigil'd variable in the first place?

A better option in my opinion would be to make the my optional in my \foo =...

I mulled that for about a year, but that's different semantics than what I proposed in my OP.

What you suggest would still leave it ambiguous whether foo was immutable or not. One could write:

\foo = $ = 42;
\bar = [99];

Both foo and bar would be mutable.

(BTW, I note you haven't said whether you read my OP; I would love it if you did read it and/or ask that you at least reveal if you've read it or not. If it was too long, fair enough, but maybe it was too short?)

2
theangryepicbanana•

I really see this as a non-issue.

All declarations are explicitly and nearly impossible to mix up.

\foo is an alias, not an actual variable, so foo = 1 would actually assign whatever foo is aliasing.

Sigils don't exist just because of Perl, they exist to prevent ambiguity and to help determine the "shape" of a variable/container. Getting rid of them would be a major mistake, as they're one of the best parts about Raku in this regard

3
s-ro_mojosa•

I agree with the OP that this is counterintuitive. But, I also see where you're coming from. Might the best solution be to update the error so that it says, "Hey, did you forget a sigil? Sigils are important because blah blah blah. On the other hand, if you're trying to make a constant try yadda yadda yadda instead.

3
theangryepicbanana•

Yeah I like that idea

3
raiphOP•

But what about:

constant foo = [42];
foo = 99;
say foo; # [99]

Do you not accept that some folk find that surprising?

2
s-ro_mojosa•

Wait, what? That's valid behavior?

3
raiphOP•

Your "Wait, what?" speaks volumes. :)

I think your reaction is the sensible one.

Do you understand how my proposal addresses this insanity? If not (it's long!) how much of my OP did you read?

Also, relative to the main reaction to my proposal here so far, namely that it would inconvenience folk using the my \foo = $ = ... idiom (the claim it could not be used is false), have you caught (my other comments to the effect) that I invented that idiom, and that it's not merely ugly but also not thread-safe? Perhaps more importantly, have you ever seen non-toy code using it?

2
liztormato•

Yes, because in at least all current language versions of Raku, [] is a circumfix operator creating an Array. And Arrays are mutable by design.

And at the moment, constant foo = 42 is just syntactic sugar for:

BEGIN our \foo := 42

without regard to the RHS. One could argue that this should maybe cause a warning and/or deprecation message.

1
vrurg•

A small correction. Any symbol in Raku is an alias. Sigilled ones are no exception.

Twigils with this respect are even more tightly bound to the actual nature of a symbol.

2
theangryepicbanana•

Yeah my bad, I just meant "alias" as in "it directly references the rhs", as opposed to a sigilled variable which creates a container

2
vrurg•

Sorry for nitpicking, but "creates with assignment". 😉 But you're sure correct.

2
raiphOP•

I really see this as a non-issue.

What as a non-issue? Is this a reply to my OP or Brad's comments?

All declarations are explicitly and nearly impossible to mix up.

Exactly!

(So I'm baffled if you're responding to my OP!)

\foo is an alias, not an actual variable, so foo = 1 would actually assign whatever foo is aliasing.

Right.

So don't do that. Problem solved. :)

Sigils don't exist just because of Perl, they exist to prevent ambiguity and to help determine the "shape" of a variable/container. Getting rid of them would be a major mistake, as they're one of the best parts about Raku in this regard.

Why are folk thinking I'm talking about getting rid of sigils?

How is "I love (Raku's strong support for) sigils." being so badly misinterpreted!?!

(Has anyone actually read what I've written? :( )

2
vrurg•

Very briefly, this would has impact on code readability. Most of Raku syntax I can grasp right away. This one is easily confused for an assignment. I would know its semantics without browsing the code or reading docs in order to find out what too is and if it's out there somewhere at all.

What I'd like to have is 'const' as an 'constant' alias. Too often I tore the former, not the later. 😀

3
raiphOP•

Very briefly, this would has impact on code readability.

Yes! Exactly!

foo = ...

As I explained in my OP, following that declaration, within the lexical scope containing it, foo is, at compile-time, immutably bound to the entirely immutable value represented by ....

This combination of syntax and semantics could not get easier to read and understand for about a hundred million devs, and I do not believe there are any Rakoons who would take more than 5 seconds to get it if they'd open their mind for 5 seconds. Really, if it takes more than 10 seconds, tops, to get it, the problem is commun8cation, not the syntax or semantics.

Most of Raku syntax I can grasp right away. This one is easily confused for an assignment.

To a true programming newbie, one used to x = 42 from math class, it is "assignment". And that's ideal.

The notion is that foo = 42 is usually a one-time deal. Before it there was no foo. After it, for the rest of the compunit, foo is 42. If you write put foo you see 42. If you write foo = ... again, you get a compile-time error.

And to the degree is it not assignment, it's an ideal teacher/bridge to more complex syntax and/or semantics that it's appropriate to defer for a newbie. Put another way, if you want more, then use a different declarator for foo:

  1. If you want to be able to reassign to your identifier, then use eg ...

  2. If you want your identifier to be immutably bound to a value that can change, use eg ...

  3. If you want to postpone initializing or finalizing foo till run-time, use eg ...

  4. If you want to interpolate your identifier, use eg ...


How often do you write code in which you assign to a sigil-free identifier?

I invented the my \foo = $ = ... idiom (afaik) and used it a couple times 6-7 years ago, but knew it was dodgy when I invented it, not least because it's ugly. But it's also not threadsafe. So why use it? Why let such an awful idiom stop us even considering with an open mind having the simplicity of foo = 42?

I would know its semantics without browsing the code or reading docs in order to find out what too is and if it's out there somewhere at all.

I don't understand how you can get from such a simple thing to so much complexity. Are you sure you haven't misunderstood either Raku or my OP?

What I'd like to have is 'const' as an 'constant' alias. Too often I tore the former, not the later. 😀

Fwiw it feels to me like Raku's constant is misleading enough without such awfulness as:

const foo = [42];
foo = 99;
say foo; # [99]
2
vrurg•

That's why I'm nor particularly happy about answering from iPad, not mention a phone; and not happy about auto-corrections. :) In this statement:

I would know its semantics without browsing the code or reading docs in order to find out what too is and if it's out there somewhere at all.

It was supposed to say "... what foo is and if ..." My point is when you first meet something like the proposed foo = 42 in a module or a script, would you be able to tell right away, without inspecting any of the preceding code, or documentation of the modules used, or without consulting with other sources of information, wether the statement is a declaration in your proposed way, or an assignment? That's it.

3
raiphOP•

would you be able to tell right away ... wether [foo = 42] is a declaration in your proposed way, or an assignment? That's it.

Yes. Instantly. It's a one time immutable binding of a fully immutable value to foo.

That is, if you mean "would you be able to tell " within reason.

If you don't mean that, well you can't tell what any code means for sure without not only inspecting preceding code etc. but also auditing the compiler, the C compiler or whatever used to compile the compiler, and so on. Or looking at the generated machine code after first auditing the compile of the tool you use to look at the machine code etc.

So I presume you mean within reason.

And within reason, foo = 42 immutably binds a fully immutable 42 to foo. It's extremely simple. It's extremely helpful.

Again, I invented the my \foo = $ = ... idiom and it's nasty. One can't be sure someone isn't trying to attack your code by using it or any of an infinite number of horrible hacks but why let fear of that stop folk even considering evolving Raku sensibly?

Again, how often do you write code in which you assign to a sigil-free identifier? Is it threadsafe?

2
liztormato•

Unfortunately, at one point Larry Wall decided that the lone $ would be the "anonymous state variable". So the reason that the:

my \foo = $ = 42

syntax is not thread-safe, is that any thread using the same closure, will be sharing that state variable.

Unfortunately, there's a lot of code out there abusing the lone $. :-(

3
vrurg•

Yes. Instantly. It's a one time immutable binding of a fully immutable value to foo.

That's because and only because we're currently discussing it.

But in the wild I can tell no difference between the proposed declaration semantics and an assignment. I cannot tell if it's a new symbol or an existing one. It can be a sigilless something exported by another module and then it is an assignment and that what I expect foo to be: an assignable entity.

I wouldn't be able to chose one semantics over another until I get the full context. The latter would take extra time and, worse, would require extra distraction.

2
liztormato•

If I understand your proposal correctly, you want:

foo = 42

to be the equivalent of:

my constant foo = 42

Note the my there. Without, it would be an our:

constant foo = 42;
say OUR::.keys; # (foo)

Observe the behaviour of our:

sub a() { constant b = 42 }
say b;  # 42

Definitely not lexically scoped! :-)

3
liztormato•

I don't know if you realize you can actually do a no strict in Raku:

no strict;
$foo = 42;
say OUR::.keys;  # ($foo)

I doubt if many people actually use this remnant of old times. At one point it was decided that this would be the default for one-liners, then again it was decided it shouldn't. Anyways, the feature stayed.

Your proposal in that respect feels like a step back towards what even in Perl 7 will not be the default.

3
liztormato•

immutable as in the sense of making a data-structure immutable, has entered the Raku ecosystem.

3
FCOSmokeMachine•

Why not adding something like:

immutable foo = 42;

Or

my immutable foo = 42;

Instead of:

foo = 4;

?

3
raiphOPWise Elder Rakoon•

Thanks for commenting. And if you've brought your usual open minded self to discussion, I will be especially grateful!

It's not about immutability, even though that's a vital ingredient. It is specifically about having no declarator, even if that seems anathema.

I'm preparing a new post about this. Sometimes I write really poorly and this is clearly one of those times. Hopefully we can engage in that new thread which I hope to post in the next day or two. Again, thanks for engaging.

2