Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIP-46 - Use Scala CLI to implement the 'scala' command #46

Merged
merged 9 commits into from
Oct 21, 2022

Conversation

romanowski
Copy link
Contributor

A proposal to use Scala CLI (or its subset) as the new scala command.

content/scala-cli.md Outdated Show resolved Hide resolved
content/scala-cli.md Outdated Show resolved Hide resolved
Co-authored-by: Jamie Thompson <bishbashboshjt@gmail.com>

### Open questions

The main open question for this proposal is wich commands/features should be included by default in the `scala` command. Another aspect is the release cadence: should the new `scala` command follow the current release cadence for Scala CLI (every 2 weeks) or stick to Scala one (every 6 weeks)?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The main open question for this proposal is wich commands/features should be included by default in the `scala` command. Another aspect is the release cadence: should the new `scala` command follow the current release cadence for Scala CLI (every 2 weeks) or stick to Scala one (every 6 weeks)?
The main open question for this proposal is which commands/features should be included by default in the `scala` command. Another aspect is the release cadence: should the new `scala` command follow the current release cadence for Scala CLI (every 2 weeks) or stick to Scala one (every 6 weeks)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that Scala CLI will dynamically resolve various Scala versions, I don't see the point in tying its release schedule to that of dotc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am also all for the independent release scheme but @julienrf and others shared some concerns about this, and that is why I have included it as an open question.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the setup instructions tell you to run scala -version to test your setup:

Screenshot from 2022-07-20 13-38-30

What do we want scala -version to return when scala is implemented via scala-cli? I thought it could make sense to build a scala command with every release of Scala, and which would default to the Scala version of that release.

Otherwise, we can decide that the version of scala has nothing to do with an actual version of Scala, and in that case, we should document it explicitly.

Copy link
Member

@sjrd sjrd Aug 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, scala -version should show the version of Scala that will be used if I use scala (i.e., scala repl) or scala compile in the current directory (which means taking using clauses into account). The version of the launcher is irrelevant in 99% of use cases, and probably 100% of beginner use cases.

For the Python lovers, compare with py --version/py -3 --version which show "Python 3.10.5" and py -2 --version which shows "Python 2.7.18": I get the version of Python that will be used if I run py/py -3 or py -2. The version of py itself is irrelevant.

Copy link
Contributor

@julienrf julienrf Aug 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a discussion with Sébastien, here is a suggestion about this point: when someone invokes scala -version, simply prints both the version of the runner (ie, scala-cli), and the current version of Scala. The current version of Scala would depend on the working directory (e.g., if there is a Scala project that configures a specific Scala version with a “using” directive, that version should be printed).

Example:

$ scala -version .
Scala code runner version: 1.2.3
Scala version (set in ./my-program.scala:2): 3.1.3

Or:

$ scala -version
Scala code runner version: 1.2.3
Default Scala version: 3.2.0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I created an issue for it: VirtusLab/scala-cli#1250

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a discussion with Sébastien, here is a suggestion about this point: when someone invokes scala -version, simply prints both the version of the runner (ie, scala-cli), and the current version of Scala. The current version of Scala would depend on the working directory (e.g., if there is a Scala project that configures a specific Scala version with a “using” directive, that version should be printed).

Example:

$ scala -version .
Scala code runner version: 1.2.3
Scala version (set in ./my-program.scala:2): 3.1.3

Or:

$ scala -version
Scala code runner version: 1.2.3
Default Scala version: 3.2.0

What is the motivation for mixing up the concerns of the version of scala-cli and "inspecting" a project/file? I suspect having multiple versions displayed in the output would create some confusion for new users.

It would be useful for the default scala version (--scala-version option) to be displayed in the output of --help for the relevant subcommands (e.g., run, compile, etc...). Currently, there's no default shown.

$> scala-cli compile --help | grep scala-version
  -S, --scala, --scala-version version           Set the Scala version

However, a useful error message is displayed if an unsupported value is provided.

$> scala-cli run --scala-version 7 Example.scala
[error]  Cannot find matching Scala version for '7'
You can only choose one of the 3.x, 2.13.x, and 2.12.x. versions.
The latest supported stable versions are 3.1.3, 2.13.8, 2.12.16.
In addition, you can request compilation with the last nightly versions of Scala,
by passing the 2.nightly, 2.12.nightly, 2.13.nightly, or 3.nightly arguments.
Specific Scala 2 or Scala 3 nightly versions are also accepted.

Ideally, the defaults of other command line flags, such as --jvm, would be communicated in the output of --help as well.

I agree with your suggestion that "inspecting" a project would be a welcomed addition. Perhaps this use case would be better as a new subcommand that could provide more information about a project/file. For example, the configured scala version, the --scalac-options used, the resolved dependencies, or a list of main classes. Having an "inspect" functionality decoupled from --version and captured in a subcommand would also enable adding more fine grained information about a project/file over time. Overloading --version with this info would probably not age well.

Currently, I find scala-cli sometimes a little tricky to debug when I've configured it incorrectly (e.g., main class), or for cases where it's unclear what default values are being used by scala-cli. It could be useful to get feedback from the community to evaluate if an "inspect" functionality could improve the overall user experience.

Overall, I'm finding scala-cli to be a very positive addition to the scala ecosystem.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the motivation for mixing up the concerns of the version of scala-cli and "inspecting" a project/file?

I guess someone who installed Scala would be very likely to try scala -version to know which version of Scala is installed. But since scala will be a runner able to run any version of Scala, it makes sense to also show to the user the version of the CLI that is installed.

A similar situation is when someone starts a REPL session. We show both the JDK version and the Scala version because both are useful.


The current scripts are lacking basic features such as support for resolving dependencies, incremental compilation or support for outputs other than JVM. This forces any user that wants to do anything more than just basic things to learn and use SBT, Mill or an other build tool and that adds to the complexity of learning Scala.

We observe that the current state of tooling in Scala is limiting creativity, with quite a high cost to create e.g. an application or a script with some dependencies that target Node.js. Many Scala developers are not choosing Scala for their personal projects, scripts, or small applications and we believe that the complexity of setting up a build tool is one of the reasons.
Copy link
Member

@ckipp01 ckipp01 Jul 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: Not part of the SIP committee, just a passerby with a comment.

We observe that the current state of tooling in Scala is limiting creativity ... we believe that the complexity of setting up a build tool is one of the reasons

Firstly, I really enjoy scala-cli, and I believe it's a much needed tool. I'm really excited to see this here. However, I also think we should try to avoid hyperbole here. This is listed as one of the main points up here in motivation with the crux of the argument being what I quoted up above.

Here is the minimal build tool setup in sbt including a dependency

ThisBuild / scalaVersion := "3.1.3"

lazy val myproject = project
  .settings(
    libraryDependencies += "com.lihaoyi" %% "pprint" % "0.7.3"
  )

A single sbt command can also get you a fresh hello project that a user can just do sbt run and see hello. The same exists in Mill as well, which is arguably even easier.

Here is the same with scala-cli

//> using scala "3.1.1"
//> using lib "com.lihaoyi::pprint:0.7.3"

Is the difference above really what is limiting creativity in Scala? Is learning the basic sbt structure somehow more complex than learning using directives in scala-cli?

You do mention some good points here:

with quite a high cost to create e.g. an application or a script with some dependencies that target Node.js

No doubt cross platform support is confusing in build tools, but seeing that this is a giant change in the ecoystem by changing the way someone first interacts with the language I think the SIP should include a couple things.

  1. Why was this route chosen rather than improving some of these pain points in the existing tooling?
  2. How is learning new concepts introduced by scala-cli such as learning directives and BSP easier to digest than other concepts in tools like sbt or Mill which you mention as a roadblock to creativity.

Mainly because investing time into a brand new tool is also an extremely high cost. Especially in a tooling ecosystem already starved of maintainers and contributors.

None of this means we shouldn't do it, but it just means we should be crystal clear about the why, and seeing that this is listed as one of the main motivations of this SIP I'd expect the questions up above also to be crystal clear in the document, and after reading this SIP they weren't answered for me.

Copy link

@bjornregnell bjornregnell Jul 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ckipp01 I can imagine that we in some future could have an official list of curated libs so that we could write something like:

//> using scala "3.1.1"
//> using pprint "0.7.3"

and that level of simplicity would be really nice from a beginner perspective, and this SIP is taking a big step towards that level of quality UX. (or is the new cool buzzword rather DX now 😄 ) To avoid strange % and %% and : and :: that learners get intimidated by...

Copy link
Member

@ckipp01 ckipp01 Jul 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid strange % and %% and : and :: that learners get intimidated by...

O for sure, but again, this doesn't address the main question I had about the effort going into a new tool, vs addressing these pain points in the existing tools. Take the example you have up above, and there actually are discussions about them both in Mill and in sbt. We shy away from talking about it, but in Scala we have a handful of tools that almost all have single maintainers, and sometimes barely that. A lot of pains points we feel could be addressed given focus and people time. Imagine adding up all the hours of various devs that have gone into making scala-cli, and imagine putting all those hours towards exiting issues and problems. What would have a greater impact on the ecosystem?

Again, I want to reiterate that I'm not saying this necessarily as a reason against scala-cli, I'm happily using scala-cli, but it's just a big glaring question mark still, is all the effort going into scala-cli (which also forces other tooling to put in effort to support this new tool) a net positive vs if all that effort was put into existing problems and tools. Maybe the answer is yes, starting from a clean slate offers us the greatest impact to make a change for the better in welcoming newcomers, addressing exiting problems, and pushing the boundaries of the existing tooling ecosystem. If that's the case, then I'm 110% behind it. Sign me up. For me personally, as someone who spends a lot of my time trying to help maintain other tools, answering the above question is most what I'm curious about.*

If this was just a project some person or company was working on because it was fun, or something they deemed worth it for them, cool. But I'm harping on the above so much because what we're proposing is a fundamental change to how someone is introduced to Scala, both from the command line and the editor. It's a big deal.


*I want to recognize that this isn't an easy question, or a new one. Balancing older stable tools with pain points and addressing them vs pushing the boundaries with new shiny ideas that don't fit within the confines of the existing tools. However I believe this just justifies putting the decision and answer to this question right at the forefront to show that it's really been discussed and thought about.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or is the new cool buzzword rather DX now 😄

😆 I'm so happy to see this being used here.

Copy link
Contributor

@julienrf julienrf Aug 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to emphasize this point with a concrete example of “build definition” for Scala CLI:

https://github.com/VirtusLab/typed-frames/blob/5b6ca450d9c14a0c668283f00e1847298a9af050/publish-conf.scala#L1-L8

I don’t think this is significantly better or simpler than the equivalent with sbt, gradle, mill, etc. It just looks the same: you supply the information to put in the pom.xml that will ultimately be published.

So, my suggestion would be to rephrase the sentence that raised this discussion to position Scala CLI differently. I don’t think it improves much the landscape of build tools, but I think it improves significantly the current Scala interpreter (the one we get with the scala command line tool) because that one can’t be configured with directives.

Copy link

@sideeffffect sideeffffect Aug 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A thought from a humble non-affiliated Scala user:

I don’t think it improves much the landscape of build tools, but I think it improves significantly the current Scala interpreter (the one we get with the scala command line tool) because that one can’t be configured with directives.

I feel that an analogous explanation might be helpful here why/how it's better than Ammonite, which is the incumbent featureful configurable Scala interpreter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, it lacks some features, see e.g. com-lihaoyi/Ammonite#1093

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ckipp01 I can imagine that we in some future could have an official list of curated libs so that we could write something like:

//> using scala "3.1.1"
//> using pprint "0.7.3"

Related: https://contributors.scala-lang.org/t/why-doesnt-scala-have-library-listing/5696

Copy link

@sideeffffect sideeffffect Sep 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May I humbly suggest to extend the section as

Why decided to work on Scala CLI rather then improve existing tools like sbt, Mill or Ammonite?

For similar reasons as with sbt or Mill, Ammonite is an already existing tool that shares some similarities with scala-cli. I'm suggesting this, because I think it would be helpful to the wider Scala community to write down the reasons why it was better to start from scratch instead of building on top of Ammonite. Thank you :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the difference above really what is limiting creativity in Scala? Is learning the basic sbt structure somehow more complex than learning using directives in scala-cli?

Since it is very much a first expression I believe it matters, yes. It's similar to arguing that static public void main(args: String[]) is of so much of an issue, which is true, but since it's the first thing a newcomer sees it matters.

@julienrf julienrf changed the title Scala CLI SIP SIP-46 - Use Scala CLI to implement the 'scala' command Jul 18, 2022
Copy link
Member

@sjrd sjrd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we accept this SIP, then the regular scala command that people install on their machines cannot be built by the release process of scala/scala or lampepfl/dotty anymore. How do you see the release processes evolving to adapt to this?

Also, how can we confidently run the scalac/dotc compiler in standalone mode, without any wrapper around it, to reproduce a compiler issue? Should we still distribute a separate "app" scala-compiler that is only a launcher for the standalone compiler?

scala-cli repl --dep com.lihaoyi::os-lib:0.7.8
```

Compared to Ammonite, default Scala REPLs provided by Scala 2 and 3 - that Scala CLI uses by default - are somewhat limited. However, Scala CLI also offers to start Ammonite instead of the default Scala REPL, by passing `--ammonite` (or `--amm`) option to `scala-cli repl`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it isn't appropriate to include --ammonite in the default scala runner. If we do, it means we commit to supporting it forever, and that means supporting Ammonite itself forever. This is a significant weight.

In the context of Scala CLI, the REPL is not so limited anymore. In particular, it can use dependencies specified through Maven coordinates. So I don't think there is anything fundamental that we need Ammonite for.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good point. That is why we were considering making some of the options non-stable so we can drop them at any point, and ammonite may be such an opinion.


Scala CLI can also be configured with ["using directives"](https://scala-cli.virtuslab.org/docs/guides/using-directives) - a comment-based configuration syntax that should be placed at the top of Scala files. This allows for self-containing examples within one file since most of the configuration can be provided either from the command line or via using directives (command line has precedence). This is a game changer for use cases like scripting, reproduction, or within the academic scope.

We have described the motivation, syntax and implementation basis in the [dedicated pre-SIP](https://contributors.scala-lang.org/t/pre-sip-using-directives/5700). Currently, we recommend to write using directives as comments, so making them part of the language specification is not necessary at this stage. Moreover, the new `scala` command could ignore using directives in the initial version, however we strongly suggest to include comment-based using directives from the start.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the scala command ignores the using directives, then it provides basically no value over the current command. Therefore, I don't see ignoring directives in an initial version as a viable alternative.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the same topic, I will repeat here, in the context of the SIP process, an opinion I have already expressed elsewhere. I believe using directives must be integrated into the language, and not offered as comments.

The reason boils down to: using directives specify the semantics of the program (through Scala version and compiler options at the least, and I would argue through dependencies as well). These things are non-optional. They must be taken into account. Putting them in comments goes against all principles about what comments are.

I know that tooling people don't want to read this, because it means they need to support it. But that is not different from anything else that goes through the SIP process. Moreover, as pointed out above, they will have to deal with those "comments" anyway to respect the program semantics. So I consider that objection as moot.

Comment on lines 123 to 124
- Scala CLI has its own versioning scheme, that is not related to the Scala compiler. Default version used may dynamically change when new Scala version is released.
- By default, Scala CLI manages its own dependencies (e.g. scalac, zinc, Bloop) and resolves them lazily. This means that the first run of Scala CLI resolves quite some dependencies. Moreover, Scala CLI periodically checks for updates, new defaults accessing online resources (but it is not required to work, so Scala CLI can work in offline environment once setup)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate on that? When is Scala CLI allowed to upgrade the version of Scala? You don't want to change the version of Scala under the feet of someone (and that includes from one day to the next) without them explicitly asking for (or at least accepting) an upgrade.

My suggestion would be that, when Scala CLI compiles/runs/tests/whatever a "project", if it doesn't find at least a scalaVersion setting, that it:

  • either loudly warns, with a copy-pastable using line they can put it in their source to fix it, or
  • interactively asks the user to enshrine the currently selection version of Scala as a new using directive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If no version of Scala is provided, Scala CLI will pick the latest supported version, and that can change overnight (usually after the Scala is released). The supported Scala versions per version of Scala CLI are defined here, and Scala CLI periodically checks it.

We do not promise any specific behaviour with regard to dynamic versions so that we can change it. I can an option that once code is incrementally compiled, it will not change the version (so there are some files present indicating that the version was picked). In such a case (when we have an indication that code was once compiled) the warning will be printed if a new version is detected. I am not saying this is a good approach, just one of the options we can adopt if we want to increase stability.

- Scala CLI recognizes tests based on the extension used (`*.test.scala`) so running `scala compile a.scala a.test.scala` will only compile `a.scala`
- Scala CLI has its own versioning scheme, that is not related to the Scala compiler. Default version used may dynamically change when new Scala version is released.
- By default, Scala CLI manages its own dependencies (e.g. scalac, zinc, Bloop) and resolves them lazily. This means that the first run of Scala CLI resolves quite some dependencies. Moreover, Scala CLI periodically checks for updates, new defaults accessing online resources (but it is not required to work, so Scala CLI can work in offline environment once setup)
- Scala CLI can also be configured via using directives. Command line options have precedence over using directives, however using directives override defaults. Compiling a file starting with `//> using scala 2.13.8`, without providing a Scala version on the command line, will result in using `2.13.8` rather than the default Scala version. We consider this a feature. However, technically, this is a breaking change.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it surprising that the SIP describes the command-line arguments as the prime means of configuring it, and using directives as a "fallback", secondary thing. It should be the other way around, IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scala CLI is cmd-first, and that is why cmd args take precedence. For us, a situation when a user tries to compile code providing a given version of Scala and another is picked would be confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I wasn't clear before. Command-line args should definitely take precedence over file configuration. This is a universal good practice among all software.

But using clauses should be presented as the normal way of specifying options. Command-line args should only be used to punctually override the configured using clauses, but not as the regular way of doing things.

Adopting Scala CLI as the new `scala` command, as is, will change some of the behaviour of today's scripts. Some examples:

- `scala repl` needs to be run to start a REPL instead of just `scala`
- with `scala compile` and `scala doc`, some of the more obscure (or brand new) compile options need to be prefixed with `-O`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that this should be addressable. scala compile should forward any argument to the compiler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided to curate the list of options ourselves (with keeping the list of compiler options) instead than fall back on the compiler since we have a lot of options (e.g. --dep) that are not forwarded, and we want to pick a types etc. in such options early especially that not all commands may call a compiler.

So this is a case where we decided that the experience of most users (especially the newcomers) is more important than 100% compatibility, especially in the really obscure cases.


### Other concerns

Scala CLI brings [using directives](https://scala-cli.virtuslab.org/docs/guides/using-directives) and [conventions to mark the test files](https://scala-cli.virtuslab.org/docs/commands/test#test-sources). We are not sure if both can be accepted as a part of this SIP or we should have seperate SIPs for both (we have opened a [pre-SIP for using directives](https://contributors.scala-lang.org/t/pre-sip-using-directives/5700/15))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this SIP should at least specify the using directives that are recognized and applied by the commands available in scala, and that affect program semantics. So that includes using scala, using options, probably the platforms, etc.

Likewise, if we do introduce the test command, then we need to decide about the test files convention. (I am a bit worried about that one regarding the .test.scala since, as you point out above, it flat-out disregards files provided on the command-line of scala compile.)


### Open questions

The main open question for this proposal is wich commands/features should be included by default in the `scala` command. Another aspect is the release cadence: should the new `scala` command follow the current release cadence for Scala CLI (every 2 weeks) or stick to Scala one (every 6 weeks)?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that Scala CLI will dynamically resolve various Scala versions, I don't see the point in tying its release schedule to that of dotc.

@romanowski
Copy link
Contributor Author

Also, how can we confidently run the scalac/dotc compiler in standalone mode, without any wrapper around it, to reproduce a compiler issue? Should we still distribute a separate "app" scala-compiler that is only a launcher for the standalone compiler?

We offer --sever:no to turn off Bloop (and zinc) and the ability to provide a classpath with --jars option. In most cases, scala-cli is an binary so we start a JVM for the compiler, so the classpath etc. is also not affected. In such cases, we are relatively close to the current scalac / dotc so the question is if we really need to be any closer.

Also, I don't mind keeping current scripts as long as they are labelled as advanced and not advertised to average users.

@bjornregnell
Copy link

bjornregnell commented Jul 20, 2022

@sjrd wrote:

Should we still distribute a separate "app" scala-compiler that is only a launcher for the standalone compiler?

Could not the good old scalac command remain as is and co-exist with the new Scala-CLI-based scala-command?


Adopting Scala CLI as the new `scala` command, as is, will change some of the behaviour of today's scripts. Some examples:

- `scala repl` needs to be run to start a REPL instead of just `scala`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason that just scala with no args could not just start the repl and be a shorthand for scala repl?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old/current scala is part of many homepages, teacher docs, printed books etc. It would be valuable if as much as possible of the old way of using scala could still work.

I think it would be good to discuss what can be kept, perhaps even for a limited deprecation period, of the old scala arg behaviour to make the transition easier and help teachers etc phase out published material that need some time to be updated.

And if it is not possible to keep old behaviour e.g. with a deprecation message, then I think there should be a helpful error message about the new way, that is aware of the old way so that error messages are relevant to those who have the old way in mind. I think it would be good if the proposal could include this in an analysis of:

  1. What can be kept of the old scala behaviour without deprecation message
  2. What can be kept of the old scala behaviour with deprecation message
  3. What cannot be kept but with a good error message to help transition.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Forgot to write that I think Scala CLI is awesome!!! ❤️ )

Copy link
Contributor

@odersky odersky Jul 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also wonder why we can't have scala as a shorthand for scala repl. It's very important that the initial experience is a simple and straightforward as possible. Most newcomers would not even know what a "repl" was, that's already expert speak!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have opened an issue to change the default: VirtusLab/scala-cli#1249

There is slight problem with the behaviour of the scala-cli --help but I think we should be able to resolve it.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! I made a comment on the help text in the new issue. (scala help etc should give the help text for the whole tool IMO).

@sjrd
Copy link
Member

sjrd commented Aug 11, 2022

To the best of my understanding, here is a summary of the points that should be addressed in order for this SIP to make progress:

And I will add that, IMO, the SIP should at least propose a list of subcommands (and their options) that would go into the default scala. I understand it's an open question, but we can hardly decide about it without having any proposed list in the first place.

(This summary doesn't mean that the other, localized comments shouldn't be addressed.)

@bjornregnell
Copy link

If the issues above are addressed, including making the scala command as backward compatible as possible/reasonable, with good deprecation/help messages for the things that does not work as before, and keeping scalac (and scaladoc and scalap) as a separate commands as before, and installed by cs, then I'm recommending the committee to vote accept on this SIP.

@chrisandrews-ms
Copy link

I can see big benefits of being able to embed dependency declarations and compiler options in single-file scripts for educational, experimental or bug reproduction use cases. It would also be great to be able to start the repl with libraries automatically resolved from Maven* (the proposed --dep flag). I would support this proposal for those use cases.

However, once we're talking about multi-file or multi-directory codebases I think we're just implementing a new build tool here, as others have mentioned. We will end up having to create syntax to deal with all of the usual problems around dependency and compiler flag management (library version conflicts, inconsistent flags etc.)**. For example, what happens right now if two files specify different compiler flags? They then can't be compiled together, so is that an error condition, or do they compile in two separate compiler runs (which means they cannot be bidirectionally interdependent)? What if one specifies flags but the other says nothing? Do the flags apply to both?

If this proposal is accepted, will the using directives become part of the language and subject to SIP review in future? If so, that's a lot of work for the SIP committee (build tools are complicated!), and if not, it seems weird for them to be in Scala source files. Also, will Scala be expected to apply those using directives when invoked via another build tool? Presumably not, but then will they be ignored or will it be an error?

I also notice that there's already support for directives to configure publishing to Maven, which is very useful, but feels a long way from just being a tool to make scripting easier.


(* One thing which would really help corporate users is easy configuration of internal Maven replicas which need credentials - or is that kind of usage more advanced that we want to support?)
(** I say all of this as someone who contributed to building an internal corporate build tool 😄 )

@bjornregnell
Copy link

bjornregnell commented Aug 19, 2022

Yes, we don't want to re-implement sbt... 😄. As I see it, the scope of this SIP is to make the currently already implemented scala-cli the new scala. And it is not a build tool (if we by that mean the build tool use cases that are out-of-scope of scala-cli as explained under "We do not call Scala CLI a build tool" here https://scala-cli.virtuslab.org/ ).

using directives become part of the language
[...] or will it be an error?

That's why scala-cli a while ago reverted from directives in the language or annotations (all kind of solutions were discussed extensively if I remember correctly) to a "magic" comment //> and thus will not affect other (build) tools. So I don't see an issue here as it is scala-cli "as is" that we are discussing, with some comments above in this thread to be addressed e.g. making it "reasonably" backwards compatible with old scala.

This way the general aim here is to provide a better developer experience compared to old scala for all those who don't need or want a full-fledged build tool to run their code. So I'm very happy to go forward with this as soon as possible.

@romanowski Is my recollection of the scoping discussion summarized ok above, or did I miss something?

@romanowski
Copy link
Contributor Author

I am sorry for such a long radio silence from my side, but recently, some personal and work-related things took pretty 120% of my time, leaving no time for open source. Hopefully, from now on, everything is back to normal.

@romanowski Is my recollection of the scoping discussion summarized ok above, or did I miss something?

Yes, the recollection is really good. I would only add that many projects are somewhere between single-file and corporate projects or open source libraries (e.g. our own tool to validate documentation).

One thing which would really help corporate users is easy configuration of internal Maven replicas which need credentials - or is that kind of usage more advanced that we want to support?

Yes, we would like that Scala CLI be useful for users in more corporate settings, including internal Maven replicas or some specific proxies. For we have a basic a page that describes briefly how to configure proxies, and we plan to have more advance guide in the future (based on an existing feature in Scala CLI and Maven).

As for @sjrd list of points that need to address, I've included the lists of commands, CLI options and directives with a comment in the text of the proposal. Also, next release of Scala CLI should default to REPL when running scala-cli or scala (the PR: VirtusLab/scala-cli#1305).

@romanowski
Copy link
Contributor Author

romanowski commented Aug 30, 2022

I have also realized that I should mention that Scala CLI will go into 'restricted' mode that is described in this SIP not only when run as scala but also when run as scala-cli-sip. The recommended way to test and use Scala CLI, as it will be scala command is to create a link to the existing Scala CLI binary named scala-cli-sip and add it to PATH. Unfortunately, I've just discovered that we do not detect properly if Scala CLI is installed as scala when using coursier. We will fix that in the near future (VirtusLab/scala-cli#1307).

- remote section about scalac and scaladoc
- remote section about defaulting to repl
- fix formatting
@bjornregnell
Copy link

bjornregnell commented Oct 12, 2022

@romanowski Thanks for the update! If you merge your branch with the updates soon (today?) I think we are in time for a vote next friday, or what do you think @julienrf ?

I think the idea from @sjrd was that we will vote on the MUST stuff only, and creating another category "nice to have" will perhaps only complicate things, I think (?). This is the first time in the new SIP process that we vote for a tooling thing and not just a language thing, so forgive us for not being clear on this. We could vote first on the MUST and then on the SHOULD or we could ignore the SHOULD for now. What do you think @sjrd ?

@romanowski I think the shebang stuff should be in the MUST-category as it otherwise will be a regression from Scala 2 if no scripts can be run...

@julienrf
Copy link
Contributor

I think we are in time for a vote next friday, or what do you think @julienrf ?

I would like the team of reviewers (you, @sjrd, and @chrisandrews-ms) to agree on the changes before we can put it on the agenda of the next SIP meeting.

@romanowski
Copy link
Contributor Author

@bjornregnell

If you merge your branch with the updates soon (today)?

The documentation is generated dynamically so its content in Scala CLI master may change (e.g. new option may be added). Moreover, it will not be a part of official doc until the next release (since we update the documentation during the release so it is up-to-date with latest release). That is why I proposed to attach the specification in this proposal, so it is fixed. Before that, I am happy to apply any suggestions.

I have also changed shebang command to MUST have. Do we need any additional for it to be a part of the SIP? (links should reflect that).

@bjornregnell
Copy link

bjornregnell commented Oct 12, 2022

@romanowski Ok if it is not suitable to merge the branch as it has auto-generated stuff, I think you should change these things in the "Specification" section to implement our requests (that were summarized on a high level by @sjrd above):

  • "The sub-commands necessary to include in the scala to match the functionalities of current commands" -> "These sub-commands MUST be included in the scala command:" And I also think you should specify here the default behavior that leaving out the sub-command means starting the REPL etc.

  • "On top of that, we think that the following user-facing sub-commands should also be included:" -> "These sub-commands are RECOMMENDED to be included in the scala command:"

  • "We also suggest to include additional sub-commands by default:" -> I propose to delete this line and just make the subsequent sub-commands part of the recommended commands. But move the shebang-thing and the ability to run scripts with .sc file suffixes to the MUST-part if appropriate.

  • "We can even open a dedicated SIP for each of them." -> I suggest to remove this sentence and instead include some kind of specification of each command, perhaps you can just copy-paste stuff from the generated docs so that we have a fixed and self-contained SIP.

  • "Scala CLI can also be configured with "using directives"" -> As @sjrd asked for above you should include (instead of a link to the docs) some kind of specification here in the SIP of (parts) of the using syntax and semantics so that this SIP becomes more of a self-contained specification that can be a documentation of this new approach for the future, e.g. for tooling vendors etc to read about the syntax and semantics in this SIP.

So the over-all intention of our requests is to remove the "conversation with the committee"-phrases like "we think" etc and instead make this SIP more of a self-contained spec that can be a documentation of (any implementation) of the scala command from now, and potential future SIPS can relate to this version. Are you following my attempt to make this more concrete? @romanowski

@sjrd @chrisandrews-ms Please correct me or add stuff if you think I have made some incomplete/disagreeable suggestions on the implementation proposal above.

@bjornregnell
Copy link

bjornregnell commented Oct 12, 2022

@romanowski And the latest commit that I see here is currently from Sept so perhaps your changes are not live yet or am I missing something?

@lrytz
Copy link
Member

lrytz commented Oct 17, 2022

@romanowski the updates are looking good to me, thanks!

I have some questions about directives vs command-line options. First, which takes precedence?

Some options are also available as directives, others are not - how is that designed?

Would it make sens to have a using runnerOpt [option...] directive? Then the directives could be cut down to the most important ones, like using lib. Some directives like using jsModuleSplitStyleStr seem rather exotic.

On the other hand, there's no directive equivalent for --jvm, is that intended?

Finally I have a few questions about the cli options:

  • The doc page doesn't seem to mention -O / --scala-opt? Could that be included at "options forwarding"?
  • Would it make sense to also forward -deprecation, -feature, -release to the compiler?
  • Could scala-cli support -Dkey=value style java properties?
  • Does scala-cli support argument files (@file in the compiler)?

Copy link
Contributor

@odersky odersky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also recommend accept


The current scripts are lacking basic features such as support for resolving dependencies, incremental compilation or support for outputs other than JVM. This forces any user that wants to do anything more than just basic things to learn and use SBT, Mill or an other build tool and that adds to the complexity of learning Scala.

We observe that the current state of tooling in Scala is limiting creativity, with quite a high cost to create e.g. an application or a script with some dependencies that target Node.js. Many Scala developers are not choosing Scala for their personal projects, scripts, or small applications and we believe that the complexity of setting up a build tool is one of the reasons.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the difference above really what is limiting creativity in Scala? Is learning the basic sbt structure somehow more complex than learning using directives in scala-cli?

Since it is very much a first expression I believe it matters, yes. It's similar to arguing that static public void main(args: String[]) is of so much of an issue, which is true, but since it's the first thing a newcomer sees it matters.

@romanowski
Copy link
Contributor Author

@lrytz

I have some questions about directives vs command-line options. First, which takes precedence?

Command line options. I've included that in the updated text.

Some options are also available as directives, others are not - how is that designed?

We tried to add directives for all options for that it make sense (e.g. I do not see how a directive for --watch should work) but we may miss something.

Would it make sens to have a using runnerOpt [option...] directive? Then the directives could be cut down to the most important ones, like using lib. Some directives like using jsModuleSplitStyleStr seem rather exotic.

I am cannot clearly at this moment see use cases for runnerOpt and I fear it may cause confusion when with multiple main being used. We are open for discussion and I think we can follow up in the Scala CLI repo (as discussion or an issue).

On the other hand, there's no directive equivalent for --jvm, is that intended?

That is something we need to add, there is an issue for it.

The doc page doesn't seem to mention -O / --scala-opt? Could that be included at "options forwarding"?
Would it make sense to also forward -deprecation, -feature, -release to the compiler?

It is included in the latest version of te proposal

Could scala-cli support -Dkey=value style java properties?

I think we could but it may cause some conflicts. Again, I think we can proceed in Scala CLI repo.

Does scala-cli support argument files (@file in the compiler)?

Not now and our idea was to use directives for that. But from technical point of view it could be added.

@romanowski
Copy link
Contributor Author

@bjornregnell

And the latest commit that I see here is currently from Sept so perhaps your changes are not live yet or am I missing something?

I've included the required specification as a comment, which was not ideal. Now, I've included a compact version of the specification in the text of the proposal.

@lrytz
Copy link
Member

lrytz commented Oct 21, 2022

Would it make sens to have a using runnerOpt [option...] directive? Then the directives could be cut down to the most important ones, like using lib. Some directives like using jsModuleSplitStyleStr seem rather exotic.

I am cannot clearly at this moment see use cases for runnerOpt and I fear it may cause confusion when with multiple main being used. We are open for discussion and I think we can follow up in the Scala CLI repo (as discussion or an issue).

Maybe I was not clear and you mis-understood? My idea with runnerOpt is to pass command-line flags to scala-cli, I didn't mean flags passed to the main method of the program. Then you could reduce using directives to the most common ones.


Additionally, all options that start with:
- `-g`
- `-language`
Copy link
Member

@bishabosha bishabosha Oct 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not on the committee here, but I think for convenience -source could also be adopted by default, currently you must do e.g. -O -source:3.2-migration, but -source is still pretty fundamental.

@bishabosha
Copy link
Member

bishabosha commented Oct 21, 2022

Hello, again not on the committee, however I noticed that in the updated spec, it says the --ammonite flag should not be maintained - but ammonite/mdoc style imports are still supported (at least in 0.1.16). e.g.

import $ivy.`com.lihaoyi::fansi:0.4.0` // could also be import $dep.`com.lihaoyi::fansi:0.4.0`

@main def hello = println(fansi.Color.Blue("Hello, World!"))

still compiles and runs fine when using scala-cli under scala-cli-sip/scala modes. To me this seems perhaps a bug as it is not mentioned anywhere in the SIP to support this feature.

@bjornregnell
Copy link

I've included the required specification as a comment, which was not ideal. Now, I've included a compact version of the specification in the text of the proposal.

Ok great, now I see it in the file tab of this PR.

I'll try to present the updated version at the SIP committee meeting in 15 min...

Copy link
Member

@sjrd sjrd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for all the changes, @romanowski. At this point I can recommend it to be Accepted.

@julienrf
Copy link
Contributor

The Committee observed that the specification lacked details (e.g. what the “test” command does is not explained) on the one hand, but was maybe too detailed on the optional “MAY” parts. In order to move forward, the Committee voted to move the proposal to the “implementation” stage, but they expect clearer documentation/specification before moving to the “completed” stage. The next step is to provide a way to ship it to the hands of the users so that they can start experimenting with it and provide feedback.

@julienrf julienrf merged commit 6004a9d into scala:main Oct 21, 2022
@bjornregnell
Copy link

bjornregnell commented Oct 24, 2022

This is good news!! 🎉 Scala SLI as the new scala command is now accepted as an official "thing" in the experimental stage. See my comment/question here on proposed ways forward: VirtusLab/scala-cli#266 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.