Raku / problem-solving

🦋 Problem Solving, a repo for handling problems that require review, deliberation and possibly debate
Artistic License 2.0
70 stars 16 forks source link

What does the absence of a `use v6.x` mean? #383

Open lizmat opened 1 year ago

lizmat commented 1 year ago

Note: this is NOT about naming versions. That is another discussion. To avoid that discussion, I'll be using ONE to indicate 6.c, TWO to indicate 6.d, THREE to indicate what is now 6.e.PREVIEW, and FOUR for what will be 6.f.PREVIEW if we stick to the current language level scheme. For the record: this (1,2,3) is now the internal numbering scheme that is used in the Rakudo compiler.

If there is no explicit version specified in code, we assume the current "standard" version (which is now TWO). I think it could be argued that this is wrong.

  1. If there is no indication of a language version (or a bare use v6), it can not be determined in which version the code is supposed to run. We therefore recommend people to specify the required language version in their code. But many people don't. Which either indicates a lack of interest, or the assumption that it will run on any version, as the code is maybe just using very basic functionality.

  2. Specifying use v6.d currently, does not fixate a set of semantics and capabilities, sadly. Since the release of TWO, many features have been added. Which has led people to having to specify a Rakudo compiler release in their code to ensure proper functioning. I think we should not make that mistake with the release of THREE again.

  3. If you want your code to use capabilities of THREE, then you will have to specify use v6.e.PREVIEW. This means that your code will start producing warning whenever it runs with a released version of THREE, because the PREVIEW part has become obsolete on that language version. It would be an option to be silent about this, but that feels like covering up.

  4. Specifying a language version in your code should indicate a fixed set of semantics and capabilities. Let's at least make sure we don't add semantics and capabilities to THREE once it has been released, and make sure that all developments take place in FOUR.

I think it is a good idea to force people to be explicit about the semantics that they want. I think that therefore we should make the FOUR the default language version when THREE is released. This will make sure that we have a fixed set of capabilities and semantics if someone specifies a required version in their code. If they do not, they get the bleeding edge. Which most likely will do what is expected anyway.

lizmat commented 1 year ago

It has been argued that not specifying a language version would be confusing for newbies, as the exact semantics of the language could be shifting.

I think this argument can only hold true for a very insignificant part:

  1. Most newbies will have way more trouble grokking general Raku Language concepts, so will mostly stick to simple Raku anyway, of which the semantics wouldn't be changing much anyway.

  2. Newbies should be told to specify the language level that they expect for their code as soon as possible. As that is what will guarantee their code working in the long run.

tbrowder commented 1 year ago

Does specifying it in the META6l.json alone and not in module code satisfy that requirement?

I suppose that could be construed as confusing or bad practice by new Rakuer.

lizmat commented 1 year ago

I think that specifying it in the META6.json should be enough for the language version, but also for the module version / auth / api

2colours commented 1 year ago

I think the proposal addresses a long-anticipated issue but it does so the wrong way around.

It has been argued that not specifying a language version would be confusing for newbies, as the exact semantics of the language could be shifting.

I think this argument can only hold true for a very insignificant part

I think actually that is the right direction. First I'm going to counter-argue with the points here, then roll out the whole argument.

Most newbies will have way more trouble grokking general Raku Language concepts, so will mostly stick to simple Raku anyway, of which the semantics wouldn't be changing much anyway.

First, it's hard to decide what "simple Raku" even is (let alone when none of us are really "simple Raku users"), or generalize over "most newbies" (let alone when none of us are newbies). Let me just say one example: truthiness of Ranges. Lately, it has been discovered that infinite Ranges are False-y for a banal technical reason but it cannot be brought to existing versions. This illustrates that some user code already depended on it, and it is pretty simple. The irony is that it was pretty old code that specified "perl": "latest" in the META and nothing in the compunit so it will break anyway, except we can say "it broke rightfully" when it finally does.

Newbies should be told to specify the language level that they expect for their code as soon as possible. As that is what will guarantee their code working in the long run.

This is part of my core argument actually: if it's universally accepted that new users should be told to specify the language level, why not be proactive and warn about the lack of it? That is something we can control, unlike what individual users are told. And even if they are told about it but forget it or don't estimate the importance of it correctly: do they deserve a landmine in their code? It feels like such an unnice thing, to make the wrong thing the easiest thing and then blame them when it explodes on them.


So, my way of thinking can be compiled into the following points.

  1. by not specifying the version, the behavior of code changes from the time it was written to the time it was run, with every new release available (actually, lizmat's proposal would urge changes to happen even sooner)
  2. this change of behavior that isn't under the author's control at the point of authoring, is never what the author would want
  3. at this point, we have two choices: a) changing the default behavior to something more stable b) avoiding the default behavior altogether
  4. changing the default behavior is the worse choice because there may be features that won't be supported forever, in which case the same breakages still happen, just less often
  5. there is already incentive to educate people about avoiding the default behavior but it looks more like gossiping. If we are serious about educating people, there is no better way than to enforce it in code. This is what language design is about.
  6. Outright erroring out without a use version pragma seems overboard, especially for a transition. Since the education process is similar to deprecations (e.g .pm extension recently), "worries" seem to be the way to go.

Anyway, I think even just locking the inferred version is better than the current behavior, and even the current behavior is better than the proposed "bleeding edge" behavior, saving a couple of characters for the well-informed and inviting to do something fragile for all the others.

lizmat commented 1 year ago

After reading the responses so far, I realized I've conflated two issues in here, that potentially muddy the arguments. Since most of the responses so far have been about the behaviour of Raku in absence of a version statement, I'll rename this issue accordingly and start another issue about how we develop FOUR further.

lizmat commented 1 year ago

See also: https://github.com/Raku/problem-solving/issues/385

codesections commented 1 year ago

My ¢2: use v6x statements are strongly encouraged and are likely to be absent in only two main places: very short scripts and code by very new Raku users (perhaps users trying Raku out for the first time).

Thus, in my view the best way to answer the question "What should the absence of a use v6x statement mean?" is to answer the question "What language version do we want to be used by short scripts and new users?". And my answer to that question is "a reasonably recent but stable version of Raku". In particular, I wouldn't want either of those use cases to miss out on a huge number of Raku features (as they would with an especially old Raku version) or to run into not-yet-caught bugs (as they might with a preview Raku version).

But others might answer that second question differently, and I'll be interested to hear other's views. Nevertheless, I think that scripts/new users are the use case that should drive our decision about how to act in the absence of a use v6x statement.

lizmat commented 1 year ago

I would argue that newbies generally would not build their own Rakudo, and thus would be using 1. a language level release, or 2. maybe a (monthly) Rakudo release. 1. would ensure very stable, and 2. would ensure some level of stability which bleed would not give.

2colours commented 1 year ago

use v6x statements are strongly encouraged and are likely to be absent in only two main places: very short scripts and code by very new Raku users (perhaps users trying Raku out for the first time).

Genuine question: have you ever checked the ecosystems to confirm this statement? Or where do you get this impression from?

Honestly, I'm just checking code that I released (more often I just maintain them rather than initiated them but still, it's mostly my responsibility at this point): Template6 has no use v statement (and "perl": "6.*" in the META file, uh-oh), HTML::Tag just spams use v6 and has no META-level versioning whatsoever, Int::Polydiv has no use v and weirdly for 2022, it has "perl": "6.d" - I surely didn't type this one out, where did I get it from...

Now, of course I can walk around and fix this issue for a lot of packages but the point is still that quite easily the majority of code out there has no use v indication, and quite often not even a sensible META field. Encouraging people to add it doesn't seem to be enough, especially considering that the lack of it is basically wrong for any released code.

lizmat commented 1 year ago

FWIW, in the case of modules, a language version specification in the META6.json should be leading for the modules in that distribution.

codesections commented 1 year ago

Even with a monthly Rakudo release, use v6.e.PREVIEW gives a very different feature set than use v6d and, if I understand correctly, we (Raku/Rakudo) generally don't promise the same level of bug-checking/stability guarantees with the PREVIEW build.

Maybe part of the problem is that we're actually not at all explicit about what backwards compatibility guarantees we make, and thus aren't clear at all what the difference between release and PREVIEW guarantees are?

0rir commented 1 year ago

Lack of a specific version should indicate the latest version up 6.e. Afterwards Raku should complain about that lack. After 6.e dieing. The timeline is subject to dispute; I favor not letting the problem grow.

In this context, PREVIEW is part of 6.*.PREVIEW.

vrurg commented 1 year ago

I'm still musing about it, but have some thoughts.

  1. No version should be a warning. Any entry level tutorial in the future better begins with words like: 'Put use v6.<something>; at the start of your code. We'll get back to it later, but for now just remember this simple rule.'
  2. Until we get to strict measures about the pragma, the default must stick to the current 6.d. We already have some code in the wild with no explicit version and that code works somehow. This may change if the default shifts to 6.e. Not sure many would vote for broken backward compatibility.
  3. Long ago I had a discussion about deprecation cycle for the PREVIEW suffix. It was decided that code using it must work with a released language version as if nothing has changed. Having written some code with actively used v6.e.PREVIEW I now see a good point in that approach. It would barely make anybody happy about their code start generating warnings simply because a dependency hasn't got time to get rid of the suffix.

Another big point: compiler version dependency can't be avoided altogether.

First of all, even though we are far from being there yet, but imagine an alternative to Rakudo implementation of Raku which doesn't offer the same set of implemented features, as Rakudo does. Any code wishing to work for any compiler would either have to stop using "controversial" features or check what compiler it's being compiled by.

BTW, the latter paragraph could spur a big discussion about Roast. There are still a lot of tests that are supposed to be part of 6.c but are not implemented by Rakudo so far. We would have to address this matter too because otherwise the meaning of 'language version semantics' is fuzzy and kind of a moving target. But this subject alone is so big that I would just mention it and do no more.

Second, when it comes down to bug fixing then compiler version test is something unavoidable sometimes too. It is no so uncommon to misinterpret a bug as an intended semantics and rely on it. Fixing such bug would create a dilemma: either drop support for older compilers, or make sure we support both broken and fixed versions.

And, in the conclusion, let me find a fly in the ointment. Sometimes it is not possible to implement a feature for a specific Raku CORE. There no single reason why. For example, implementing it may require reliance on a lexical variable available in a scope of an older CORE. Not a very common situation, but not impossible. In such case it might turn out that implementing something new within older core would prove to be more efficient than any kind of workaround.

I don't have a solution for the problem whatsoever. Best if it is entirely pulled out of thin air. But I'm cannot convince myself that it is.

2colours commented 1 year ago

Another big point: compiler version dependency can't be avoided altogether.

Welcome to the team...

niner commented 1 year ago

On Tuesday, 26 September 2023 05:46:37 CEST Vadim Belman wrote:

  1. No version should be a warning.

That would suck for shell one-liners. I think there's a reasoable compromise though. No version should be a warning when precompiling, i.e. for modules. Chances of those getting published/used in the long term are much higher than for one-liners or scripts, so it makes sense to be more strict with those.

codesections commented 1 year ago

No version should be a warning … for modules.

I like that. Maybe also a warning for bin scripts in when uploading a distribution (though I guess that's more of a fez issue than a Raku one).

0rir commented 1 year ago

@vrurg, I am with @niner regarding one-liners, a possible solution below.

That 6.d should be the default when the version is unspecified is great assuming a timely decision.

PREVIEW is problematic as @lizmat (IIRC) stated: What does PREVIEW promise?

My assumption was that it is unstable. So it is reasonable that any script which is without version or is not v6.*.PREVIEW dies upon useing a PREVIEW. That v6x.PREVIEW means v6x at some point in time seems bad because the action of the PREVIEW is variable over time. If the behavior of PREVIEW is to change, the name should change. I endorse ALPHA.

The compiler executable's name could dictate some behavior. Rakudo seems to usually install a binary raku. To me that implies that no rakudoisms should be enabled by default. That that default be applied to all rakudo binaries would partly address some of @vrurg's concerns, by showing a line between Raku and Rakudo -- a clearer starting point.

Some name could designated for one-liners disabling the unspec-ed error.

I agree with @codesections that fez is a good tool to address this. But the definition of best practices for code distribution should be defined here, and best by some koalatee tool.

rcmlz commented 9 months ago

I am a beginner and from a starters perspective it shall be as easy as possible, avoiding as much boilerplate code as possible. Requiring a use v... is IMHO boilerplate.

I learned that I shall inject custom module paths by using raku -I path/to/lib ... instead of hardcoding use lib '/path/to/lib' inside my script. So why not use the same approach for specifying a specific Raku version, IF required at some point in the future by users of a script? This would allow users to omit use v6.whatever in scripts but ensure at the same time that IF a script, that was ment to be used for 5 minutes is still in use after years, CAN be used, without changing it, just by simply setting some environment variable or adjusting the call (in you crontab or wherever you start the script) by a simple parameter like raku --use 6.old.version.WHATEVER quick-and-dirty-that-lasted.raku

For modules the depreciation warning "... change to .rakutest" worked IMHO quite well, so why not do the same to get rid of missing and wrong version statements in META6.json. This is also in line with the approach of encouraging developers to specify specific <auth> and/or <version> and/or <api> in the META6.json for the dependencies they use in their module - if a developer bothers/needs to do so.

JM2C