[SIP 18] New SIP: Modularizing language features

2,549 views
Skip to first unread message

martin odersky

unread,
Mar 17, 2012, 3:48:40 PM3/17/12
to scala...@googlegroups.com
Here's a new SIP which proposes to put some new and existing advanced
language features under an import flag. I expect we'll have an
interesting discussion about this one.
So, please, fire away!

Here's the link to the SIP:

https://docs.google.com/document/d/1nlkvpoIRkx7at1qJEZafJwthZ3GeIklTFhqmXMvTX9Q/edit

Cheers

-- Martin

Jon Steelman

unread,
Mar 17, 2012, 4:51:35 PM3/17/12
to scala...@googlegroups.com
I'm unable to comment within the document. It is View only unlike prior SIPs.

Thanks,
Jon

Heather Miller

unread,
Mar 17, 2012, 4:55:08 PM3/17/12
to scala...@googlegroups.com
Perhaps discussion on the SIPs mailing list is better than in the doc for this SIP, as much discussion is expected. 

(I don't know if this is why Martin didn't enable comments, but I suspect that this might have something to do with it.)

-- 
Heather Miller
Doctoral Assistant
EPFL, IC, LAMP

Rex Kerr

unread,
Mar 17, 2012, 5:07:04 PM3/17/12
to scala...@googlegroups.com
The big problem with this proposal is that it threatens to add a bunch of boilerplate to every single existing Scala file and program and REPL session.  With all these things off by default, I would argue that Scala is severely curtailed; why make everyone in every file and script type in "import language._" in order to enable the features that make you use Scala instead of something else?  And then, you get not only the features of a present-day typical Scala distribution, but early versions of features that are not yet fixed; if you want "full power but stable" Scala, you end up with quite a mouthful:
  import language.{postfixOps, structuralTypes, higherKinded, existentials}

Instead, I propose that, if there is a significant demand for limiting language features, that we flip the sign: instead of requiring import language.structuralTypes to get structural types, import language.disable.structuralTypes if you want them to go away.  If you're in a development environment with strict coding rules anyway, you probably will have half a screen of stuff at the top of every file anyway (copyright notice, imports of a bunch of libraries, etc.), so one more line doesn't really hurt that much.

Features that really are experimental could be kept as an import language.enable._ so that people are alerted that they shouldn't trust how they behave.  For example, macros would be a good candidate here since they're not ironed out.  Furthermore, some things that are compiler flags could be moved to language.enable (such as continuations), where they arguably more sensibly belong.

(Actually, even more sensibly, they'd be annotations on the file.)

  --Rex

On Sat, Mar 17, 2012 at 3:48 PM, martin odersky <martin....@epfl.ch> wrote:

Tom Switzer

unread,
Mar 17, 2012, 5:08:46 PM3/17/12
to scala...@googlegroups.com

+1. Well said.

martin odersky

unread,
Mar 17, 2012, 5:09:40 PM3/17/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 9:51 PM, Jon Steelman <jon.st...@gmail.com> wrote:
> I'm unable to comment within the document. It is View only unlike prior
> SIPs.

That was an oversight. i just turned comments on.

-- Martin

martin odersky

unread,
Mar 17, 2012, 5:40:37 PM3/17/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 10:07 PM, Rex Kerr <ich...@gmail.com> wrote:
> The big problem with this proposal is that it threatens to add a bunch of
> boilerplate to every single existing Scala file and program and REPL
> session.  With all these things off by default, I would argue that Scala is
> severely curtailed; why make everyone in every file and script type in
> "import language._" in order to enable the features that make you use Scala
> instead of something else?  And then, you get not only the features of a
> present-day typical Scala distribution, but early versions of features that
> are not yet fixed; if you want "full power but stable" Scala, you end up
> with quite a mouthful:
>   import language.{postfixOps, structuralTypes, higherKinded, existentials}
>
I believe that depends how important you find these features for daily
(as opposed to specialized) Scala use. To take the Scala compiler with
100K lines as an example: As far as I know, there are no uses of
postfix ops, there is one use of structural types (and we are trying
to get rid of it), there are no uses of higher-kinded types, and any
use of complex existentials, if it exists, I would deem a mistake. So
from that perspective, yes, I would value having to import features
explicitly so that I am warned from using these things accidentally.
For less experienced people I believe the need is even stronger. If
you really have a Scala style that uses all four of these features
regularly then you would be best off just redefining your scalac
command to enable all features by default.

Cheers

-- Martin

Debasish Ghosh

unread,
Mar 17, 2012, 6:13:58 PM3/17/12
to scala...@googlegroups.com
What's the major force towards this ? Is it only to present a smaller surface area to newcomers in Scala ?

Thanks.

Sean Parsons

unread,
Mar 17, 2012, 6:50:49 PM3/17/12
to scala...@googlegroups.com
I wrote a post about this after this idea first went round, all but the first item in the list are still applicable:
http://seantparsons.blogspot.co.uk/2012/01/compiler-flags-in-scala.html

It seems like a fallacy that to make the language "less complex" or easier for users to use, the answer is to make it more complex with this SIP.

Imagine the following situation:
1. Existing code base that uses higher kinded types.
2. A programmer relatively new to Scala creates a new class.
3. Said class doesn't compile even though it looks on the surface to be correct, just because one of these features isn't enabled.
The above to me seems like a much worse situation to be in, than to be presented with a compile error due to the programmer incorrectly using those features.

Sean.

Daniel Spiewak

unread,
Mar 17, 2012, 6:56:55 PM3/17/12
to scala...@googlegroups.com
Color me horrified.

Ok, maybe that was too strong.  Honestly, I don't see anything positive coming out of a change like this.  As Rex pointed out, it just creates import/build-config boilerplate for, well, everyone.  Even for the few who don't use these features (knowingly or unknowingly), these switches have no beneficial effect.  You are hiding a language feature that these people haven't seen.  By definition, this will be a completely invisible change for a few people and a significantly detrimental change for a majority.

It's also worth noting that many people who use these features do so without knowing it.  Existentials and structural types are a particularly strong example of this, but type constructors are also quite common.  People who know what these features entail will have already turned them on, while those who don't know will receive a mysterious warning/error on seemingly-innocuous code.  Consider the sheer volume of Scala snippets and explanations which will be instantly invalidated.

On a more philosophical level, "hiding" language features like this only serves to fragment the community.  It makes life very difficult in venues like mailing lists and Stackoverflow, where users will not only need to specify their language (Scala) but their language "level" (Nerfed Edition).  By definition, newcomers to the language will not understand this kind of fragmentation, given that no other language has anything quite like this, and will thus be extremely confused when correct answers to seemingly-simple questions (like extending collections) lead to warnings, or worse, errors.

Pragmatically, I have to ask the question: who are we trying to benefit with this change, and is it such a large benefit as to merit inconveniencing the largest (and most vested) segment of your user-base?

Daniel

Bernd

unread,
Mar 17, 2012, 7:06:45 PM3/17/12
to scala...@googlegroups.com, dgh...@acm.org
I guess it's because of the recurrent complaints of the "unmanageable scala {complexity/power}".
It has been argued if this is necessary - it's a double edged sword. Removing tools that are a good solution for a given problem will lead to suboptimal solutions. But there is also the perspective that tools used unwisely are also a problem.

The first case will most probably lead to working solutions which are suboptimal and can be enhanced. That's daily business. No big deal.
The second case might lead to tangled or cryptic code, bumpy compiler rides and maybe failure... and another blog post that complains about "scala the complex".

I for my part don't have a problem with an additional line in my source to turn on things I need.
But it gives us the argument "if you turn THAT on, you better know what to do with it". That's better than saying "If you use SCALA, you better know what to do with it".

If scala wants to go mainstream it has to appeal to mainstream developers. Some of the switches certainly are a step towards this end.

Greetings
Bernd

Sean Parsons

unread,
Mar 17, 2012, 7:33:08 PM3/17/12
to scala...@googlegroups.com, dgh...@acm.org
On Saturday, 17 March 2012 23:06:45 UTC, Bernd wrote:
I guess it's because of the recurrent complaints of the "unmanageable scala {complexity/power}".
It has been argued if this is necessary - it's a double edged sword. Removing tools that are a good solution for a given problem will lead to suboptimal solutions. But there is also the perspective that tools used unwisely are also a problem.
Given how unwisely people often use inheritance in code, by this logic the extends keyword should be restricted as well.

The first case will most probably lead to working solutions which are suboptimal and can be enhanced. That's daily business. No big deal.
The second case might lead to tangled or cryptic code, bumpy compiler rides and maybe failure... and another blog post that complains about "scala the complex".
Both of these seem to be negatives unless I'm mistaken. 

I for my part don't have a problem with an additional line in my source to turn on things I need.
But it gives us the argument "if you turn THAT on, you better know what to do with it". That's better than saying "If you use SCALA, you better know what to do with it".

If scala wants to go mainstream it has to appeal to mainstream developers. Some of the switches certainly are a step towards this end.
I can't see any basis for this being true at all, how is it a step towards that end? C# is easily comparable in complexity to Scala but I've _never_ seen any suggestion that it needs compiler flags to turn off LINQ/implicit conversions/extension methods.

Sean.

Derek Wyatt

unread,
Mar 17, 2012, 7:41:23 PM3/17/12
to scala...@googlegroups.com
Yup.  +1 here.

There's no value in explicitly requiring a user to load the gun before shooting it.  If they want to use Macros, they're going to use them... all you're really doing is forcing them to put in some boilerplate first.  It doesn't stop them from using it, it just makes using it annoying.

Flip the sign and now you can "protect" your code against unwanted features (if even that's a desirable thing, which I'm not convinced on).

I love Scala, and I think its creators (all of them) are brilliant... but this is just plain weird.

Daniel Spiewak

unread,
Mar 17, 2012, 7:55:46 PM3/17/12
to scala...@googlegroups.com
I think it's important to separate the complexity of Scala from the complexity it allows you to generate.  The truth is that when people complain about Scala being complex, they're almost always complaining about the complexity of the code Scala allows one to write.  Working under the assumption that this feature is intended to address the "Scala is too complex" claims (which seems like a reasonable assumption, given this SIPs origin), we should be measuring its merits against the benchmark of "will it carrot or require developers to create simpler Scala code".

I think the answer to this is a firm "no".  The features disabled don't appear in many, or indeed most, examples of complex Scala source code.  For example, you can do some crazy, crazy things using libraries like Scalaz without ever touching higher-kinded types, existentials or similar in your client code.  Obviously the library will use these features, but there's nothing we can do about this (see also: collections).  Maybe an even better example are the knots you can tie yourself in with trait linearization and really inheritance in general.  Oh, and let's not forget about implicits!  These are features that yield code that is empirically complex, but of course they are far too intrinsic to be removed or disabled.

People (read: not PLT enthusiasts) don't care about the complexity (or simplicity) of the language.  All they care about is the complexity (or simplicity) of the code that the language carrots them to write.  If we want to address the "Scala is too complex" claims, it should be based on concrete examples of that complexity (code, not vague feature lists) and very careful root-cause investigation.  In the end, addressing such issues at the language level is very nearly a lost cause.  The implications of any language change are far too vast and cross-cutting; and the issues at hand are far too subtle to be resolved by so blunt an approach as disabling language features whole-sale.

Daniel

Rex Kerr

unread,
Mar 17, 2012, 8:10:26 PM3/17/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 5:40 PM, martin odersky <martin....@epfl.ch> wrote:
On Sat, Mar 17, 2012 at 10:07 PM, Rex Kerr <ich...@gmail.com> wrote:
> The big problem with this proposal is that it threatens to add a bunch of
> boilerplate to every single existing Scala file and program and REPL
> session...if you want "full power but stable" Scala, you end up

> with quite a mouthful:
>   import language.{postfixOps, structuralTypes, higherKinded, existentials}
>
I believe that depends how important you find these features for daily
(as opposed to specialized) Scala use.

It's really hard to use higher kinded types and complex existentials _by accident_, and if they're rarely used, then the turn-them-on/off feature seems a waste of time to me; it won't have much of an impact in any direction.  There may be an argument for postfix ops and structural types, if people commonly run into trouble with them that cannot be fixed in any more sensible way than turning them off.

So I still stand by my "boilerplate" critique.

  --Rex

P.S. FWIW, I can't escape higher kinded types given the collections library design unless I'm content to do nothing generic.  Maybe other people have a different experience.

Channing Walton

unread,
Mar 17, 2012, 8:12:21 PM3/17/12
to scala...@googlegroups.com

I really don't like this idea. 

1. Developers and teams can decide whether they want to use features of the language without these flags.They can do so in ways which are much more nuanced than the broad brush strokes these flags offer.

2. Once a feature requires an explicit option to turn it on it may never be turned on in many conservative organisations. The decision will be taken away from developers/teams by architects and technical managers who don't really understand what they are doing and operate from fear caused by their own ignorance.

3. What a sad message this is about the sophistication and intelligence of developers, even patronising, although I hesistate to use such a strong word.

I am working with people in enterprise environments that find these more sophisticated parts of the language challenging. But they really enjoy how scala is teaching them new things way beyond what they currently know (above Java usually). Its exciting for them! Please don't let noisy detractors cause these kinds of changes to the language that many (quieter) developers enjoy.

Channing

On Saturday, 17 March 2012 19:48:40 UTC, Martin wrote:

tpolecat

unread,
Mar 17, 2012, 8:14:37 PM3/17/12
to scala...@googlegroups.com
I think a facility like this will be important, although I have some quibbles about the details.

Per-compilation-unit flags are preferable to global switches, but traditional out-of-band pragmas (as in GHC) make more sense to me than overloading the import syntax. This notion is reasonable for the same use case as in GHC: for enabling experimental or advanced or breaking features that would otherwise change the validity or meaning of existing code.

Some new features like macros and dynamic might be confusing and dangerous enough (respectively in this case) to justify a permanent opt-in switch. But adding them retroactively for fairly mainstream features does not seem justified.

I am not in favor of language levels, although they do have the benefit of better error reporting (see PLT/Racket language levels). In my opinion potential confusion is a small price to pay for the opportunity for discovery; "wow, I didn't know I could do that!" is much more useful than "well crap, I can't do that, this sucks, I'll go back to Python."

Finally, having witnessed a lot of people trying to learn Scala, the existing stuff you're suggesting turning off isn't where people get hung up. The most confusing things by far are implicits, implicits, implicits, Option, variance, implicits, initialization order (the wellspring of NPEs), and implicits. Everything else is down in the noise.

So I would be happy to see (a) opt-in pragmas for experimental stuff and (b) better documentation for existing language features, rather than hiding them.

rob


Simon Ochsenreither

unread,
Mar 17, 2012, 8:20:37 PM3/17/12
to scala...@googlegroups.com
Hi Martin,

a few notes from my first expression:
  • “language” could lead to confusion for Java developers, because of java.lang
  • Would we still have -Xmacro? Or would import language.macro replace it?
  • How would this relate to Predef? Wouldn't the SIP amount to something like a different Predef where more or less is brought into the scope?
  • Any chance to add any2stringadd and the numeric conversions from integer types to floating point to the enum, e. g. all the arcane Java compat stuff?
  • Some of the stuff feels like it could be easier solved by not putting it in a place where it is available by default. E.g. “scala.Dynamic needs import language.dynamic”. Why not put it somewhere like scala.lang.Dynamic to require an explicit import?
  • postfixOps is scary .... we switch the Parser based on an import?
  • structuralTypes looks interesting. So without it new Object { val member = 1 } will generate the same anonymous class, but won't have the structural type? In the end I think performance will be on par when Scala will start targeting Java >= 7, so it feels like an optimization we won't need in the long term. Which platform would suffer from it?
  • higherKinded ... looks more like we need python's import from __future__.
  • In general: How to decide in the future if something should end up as language.foo or as a compiler switch? Is it completely arbitrary?
  • -F ... we already -X, -Y why not use one of them?

Frankly, I'm not sure if we really need that. Maybe helpful in some corporate setting so that superiors can more easily restrict the allowed language features “no imports from language allowed”, but I think just adding an IDE option or a compiler flag would be simpler.

This feels a bit like a PR stunt for the “Scala is so complex” crowd, but imho it will backfire and the mere existence of language.* will serve to proof their point.


Maybe we could have some -Xscary compiler flag instead? Which just emits warnings about the usage of these features without splitting the community into multiple groups ranging from “no language.* allowed”, “only postfixOps” to “no restrictions”.

Thanks and bye,


Simon

Channing Walton

unread,
Mar 17, 2012, 8:25:58 PM3/17/12
to scala...@googlegroups.com
If all one has to do is import something, then those that want to use those features will do so, those that don't, will not. How is that different from simply having all the features 'turned on' and letting people write the code they want to? You can't use those feature by accident! Or can you?

Is the intention to enable automated checking of more sophisticated techniques so that they can be re-written in a more basic way, in teams where a decision has been made not to use certain features?  


On Saturday, 17 March 2012 19:48:40 UTC, Martin wrote:

Josh Suereth

unread,
Mar 17, 2012, 8:49:13 PM3/17/12
to scala...@googlegroups.com
I think that's a good point.  Implicits are by far the most difficult thing to tame when learning scala and *also* the most abused by new scala developers.   I've talked about them a few times, and I think simplifying the use/development of implciits would go a lot further than removing higher kinded types.

Honestly, the language support for higher kinded types is useful enough to do higher-order abstractions, but still too painful for the code to be readable.  I think improving higher-kinded types is a far better solution to removing them.  NOW, as stated in the SIP, if the idea is to deprecate the current higher kinded types in favor of a new system that works better, I'm all for that.   However, I think that new system needs to be (a) in place, or (b) spec'd before we take such a move against higher-kinded types.   I know a *lot* of my personal software directly or indirectly relies on them.

As for enabling scala features with switches, I'm definitely on the fence.   I'd *love* to have the safety for crossing from JVM to other environments.  i.e. on Android I want to avoid *reflection* in its entirety, not just structural types.  It's almost like *that* use case would be better served on the backend of the language.  If you're about to emit bytecode for reflection, issue a warning.

So, I'm personally on the fence here.  I can see the need for disabling features to protect yourself in key situations (writing bytecode intended for dalvik, for example).   However, I don't want this SIP to be guided beyond a technical solution into a political one.  Let's focus on the technical issues that we're solving.   From what I read, here's the list:

(1) Reflection is slow and not allowed on all platforms
(2) Higher kinded types are incomplete and we want to replace how they work.
(3) Macros are new, so they belong behind a flag.
(4) Dynamic typing is dangerous to type safety, so it belongs behind an opt-in "I know better" "asInstanceOf" kind of flag.  Open the box at your own risk.

If these are the *core* reasons for the changes, I can buy solutions to those problems.  However, here's my thoughts:

(1) I think Structural types disable/enabled might not go far enough for #1.   When i want to disable reflection I want to disable any use of it, including getClass or isInstanceOf runtime calls.
(2) I'd rather wait until we have a new higher-kinded system spec'd out and proven before we try to deprecate what we have.  They're too useful and indirectly used to hide behind a flag.
(3) Totally fine with new features having flags to enable before they stabilize (like CPS transforms)
(4) Not sure this should default off or on, but the idea of a flag for dynamic typing is great IMHO.  If I want guaranteed type safety (and the niceties, like refactoring that come with it) in a project, I want this.

Chapin, Peter @ VTC

unread,
Mar 17, 2012, 9:03:26 PM3/17/12
to scala...@googlegroups.com

In general I think modularization of large things (for some definition of “large”) is good. Scala is growing rapidly and new features are being added or proposed at a steady rate. What will happen to Scala if this continues indefinitely? Features will start interacting in surprising ways causing an ever increasing number of “gotchas” that programmers will have to worry about. The problem is increased when compatibility with legacy code is thrown into the mix.

 

Modularization would allow teams to take some control over the expansion of the language. “Feature X is cool, but we don’t need it. We won’t turn it on and we won’t get any ugly surprises due to some subtle backward-incompatible aspect of feature X. Plus the compiler can optimize our code better if it knows it doesn’t have to deal with feature X.”

 

It’s not the complexity of Scala now that concerns me; it’s the complexity of Scala twenty years from now that I’m worried about. What language can endure continuous growth without eventually falling over under its own weight (think C++)? Perhaps Scala can if it supports a language modularization feature.

 

As an aside Ada has a feature that allows programmers to selectively turn off certain features (pragma Restriction). It isn’t used much but it is used, for example, to simplify the language for purposes of static analysis or to reduce the runtime system requirements, etc. There is definitely value in it, although I notice that Ada’s approach is to present the whole language by default and allow the program to contract it when appropriate.

 

Peter

martin odersky

unread,
Mar 17, 2012, 9:37:01 PM3/17/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 11:13 PM, Debasish Ghosh
<ghosh.d...@gmail.com> wrote:
> What's the major force towards this ? Is it only to present a smaller
> surface area to newcomers in Scala ?
>
Definitely not. The selected features are ones which I would prefer to
be explicit about in every codebase I collaborate in. For instance, if
I accidentally use a structural type I want to be warned about it,
mostly because I care about performance. Or, if someone I collaborate
with uses postfix operators I also want to see that upfront. And so
on. So I think the flags will be valuable for most Scala codebases,
with typical exceptions being DSLs.

The main feature left out are implicits. Implicits are probably
misused more often than any other part of Scala, but requiring them to
be put wholesale under a flag would mean we think all type-class
oriented programming is a special case, and that's absurd. So we'd
need a crisp definition what constitutes a problematic implicit
(implicit conversions, maybe?) I could not convince myself of a good
criterion so far, so I left them out.

Cheers

-- Martin

Jean-Laurent Huynh

unread,
Mar 17, 2012, 9:53:23 PM3/17/12
to scala...@googlegroups.com
Hi Martin,

If the intent is to warn users about unintentional feature usages then I think emitting warnings during compilation would work best. If I know what I'm doing I could pass a flag -Wno-structural-types or some such to quiet warnings about using structural types. Additionally a flag could be set to turn these warnings into errors, may be -Eno-structural-types. Since build systems and build configurations are typically set for the group rather than the individual, I think this is good way to enforce code policy at the group or company level. When the nightly fails because it uses -Eno-structural and somebody checked in code that relied on the features that ensures that the usage doesn't get permanently in the code base accidentally. 

On the other hand, allowing is with import language.structuralTypes does not help unless the nightly build is also integrated into checkstyle type of tools which don't exist for scala.

Best regards,

Jean-Laurent

On Saturday, March 17, 2012 6:37:01 PM UTC-7, Martin wrote:
On Sat, Mar 17, 2012 at 11:13 PM, Debasish Ghosh

On Saturday, March 17, 2012 6:37:01 PM UTC-7, Martin wrote:
On Sat, Mar 17, 2012 at 11:13 PM, Debasish Ghosh

Andreas Flierl

unread,
Mar 17, 2012, 9:53:52 PM3/17/12
to scala...@googlegroups.com
I personally see no need to turn any of these features off, but I'd rather have a switch than seeing a feature (like dotless postfix methods *wink*) go completely.

Haskell GHC has these pragmas to activate language features - a concept that seems slightly similar. I am a Haskell beginner but I can safely say those never confused me. On the contrary, they got me to read documentation of that feature to learn why it was needed in that source file.

So my question is, are those feature switches really that horrible? To reduce the boilerplate why not add a scalac switch to simply enable all of the features and ignore the special imports?

Also, I am unsure if imports are really a good way to do this, since the special meaning of those is not immediately obvious (to a beginner).

martin odersky

unread,
Mar 17, 2012, 9:59:11 PM3/17/12
to scala...@googlegroups.com

Imports are inspired from Python where things like

from Future import ...

work well. Imports have the advantage that doc comments can be
attached to the enumeration values, so it's immediately clear where to
look for documentation about a language feature.

Cheers

- Martin

Eugene Yokota

unread,
Mar 17, 2012, 10:03:51 PM3/17/12
to scala...@googlegroups.com

On Saturday, March 17, 2012 9:37:01 PM UTC-4, Martin wrote:
For instance, if I accidentally use a structural type I want to be warned about it,
mostly because I care about performance. Or, if someone I collaborate
with uses postfix operators I also want to see that upfront. 

As others have noted, those who are writing the code does not introduce these features by accident,
so a white list of "advanced" features, especially existing features, would make sense.

If there are needs for warnings, why not introduce compiler warning/error flags for various levels of the languages
including the use of structural types, postfix ops, reflection, implicit conversion etc?
This way, Scala as the language can stay in one shape,
and individuals or organizations can chose to curtail certain aspects of the language on their own.

-eugene

martin odersky

unread,
Mar 17, 2012, 10:06:13 PM3/17/12
to scala...@googlegroups.com

Macros are so easily abused that they definitely belong behind a flag,
even once they are no longer new.

> (4) Dynamic typing is dangerous to type safety, so it belongs behind an
> opt-in "I know better" "asInstanceOf" kind of flag.  Open the box at your
> own risk.
>
> If these are the *core* reasons for the changes, I can buy solutions to
> those problems.  However, here's my thoughts:
>
> (1) I think Structural types disable/enabled might not go far enough for #1.
>   When i want to disable reflection I want to disable any use of it,
> including getClass or isInstanceOf runtime calls.

I think these are actually available on all platforms.

> (2) I'd rather wait until we have a new higher-kinded system spec'd out and
> proven before we try to deprecate what we have.  They're too useful and
> indirectly used to hide behind a flag.

But we do not deprecate them! I think if there is a chance that we
change some aspects of them in the future it's better to put them
under a flag now, so that people can avoid them if they want a
guarantee that their code will last forever without changes.

> (3) Totally fine with new features having flags to enable before they
> stabilize (like CPS transforms)
> (4) Not sure this should default off or on, but the idea of a flag for
> dynamic typing is great IMHO.  If I want guaranteed type safety (and the
> niceties, like refactoring that come with it) in a project, I want this.
>

I think flags should always be opt-in, not opt-out. "Keep simple
things simple and complicated things possible"

Cheers

- Martin

martin odersky

unread,
Mar 17, 2012, 10:14:34 PM3/17/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 11:56 PM, Daniel Spiewak <djsp...@gmail.com> wrote:
> Color me horrified.
>
> Ok, maybe that was too strong.  Honestly, I don't see anything positive
> coming out of a change like this.  As Rex pointed out, it just creates
> import/build-config boilerplate for, well, everyone.  Even for the few who
> don't use these features (knowingly or unknowingly), these switches have no
> beneficial effect.  You are hiding a language feature that these people
> haven't seen.  By definition, this will be a completely invisible change for
> a few people and a significantly detrimental change for a majority.
>
I believe my development experience is different than yours then. In
codebases I contribute to, these features are very rarely used. To a
point, where I would welcome a warning if they are indeed used. So I
believe it will be an invisible change for the majority, a welcome
change for most people on the borderline, and a small nuisance for a
few.

> It's also worth noting that many people who use these features do so without
> knowing it.  Existentials and structural types are a particularly strong
> example of this, but type constructors are also quite common.  People who
> know what these features entail will have already turned them on, while
> those who don't know will receive a mysterious warning/error on
> seemingly-innocuous code.  Consider the sheer volume of Scala snippets and
> explanations which will be instantly invalidated.
>

That's a good point. I actually think it's by far preferable if people
who do not know about using these features are notified. That way they
can look up the documentation for the feature, learn about it, and
then make a conscious decision whether they want to use it.

> On a more philosophical level, "hiding" language features like this only
> serves to fragment the community.  It makes life very difficult in venues
> like mailing lists and Stackoverflow, where users will not only need to
> specify their language (Scala) but their language "level" (Nerfed Edition).
> By definition, newcomers to the language will not understand this kind of
> fragmentation, given that no other language has anything quite like this,
> and will thus be extremely confused when correct answers to seemingly-simple
> questions (like extending collections) lead to warnings, or worse, errors.
>

I don't think this will lead to fragmentation. These are very specific
features. For most discussions about the language it would actually be
very beneficial to rule out from discussion dispatch via dynamic, just
to pick an example. Where people do talk about specific features, it
will become common understanding to assume the import.

> Pragmatically, I have to ask the question: who are we trying to benefit with
> this change, and is it such a large benefit as to merit inconveniencing the
> largest (and most vested) segment of your user-base?
>

I already responded to Debashish on that.

Cheers

- Martin

martin odersky

unread,
Mar 17, 2012, 10:19:13 PM3/17/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 1:25 AM, Channing Walton
<channin...@gmail.com> wrote:
> If all one has to do is import something, then those that want to use those
> features will do so, those that don't, will not. How is that different from
> simply having all the features 'turned on' and letting people write the code
> they want to? You can't use those feature by accident! Or can you?
>
For some things yes. We had several cases where structural types were
slipped in by accident.

Cheers

- Martin

> Is the intention to enable automated checking of more sophisticated
> techniques so that they can be re-written in a more basic way, in teams
> where a decision has been made not to use certain features?
>


>
> On Saturday, 17 March 2012 19:48:40 UTC, Martin wrote:
>>
>> Here's a new SIP which proposes to put some new and existing advanced
>> language features under an import flag. I expect we'll have an
>> interesting discussion about this one.
>> So, please, fire away!
>>
>> Here's the link to the SIP:
>>
>>
>> https://docs.google.com/document/d/1nlkvpoIRkx7at1qJEZafJwthZ3GeIklTFhqmXMvTX9Q/edit
>>
>> Cheers
>>
>>  -- Martin

--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967

martin odersky

unread,
Mar 17, 2012, 10:35:55 PM3/17/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 12:55 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
> I think it's important to separate the complexity of Scala from the
> complexity it allows you to generate.  The truth is that when people
> complain about Scala being complex, they're almost always complaining about
> the complexity of the code Scala allows one to write.  Working under the
> assumption that this feature is intended to address the "Scala is too
> complex" claims (which seems like a reasonable assumption, given this SIPs
> origin), we should be measuring its merits against the benchmark of "will it
> carrot or require developers to create simpler Scala code".
>
> I think the answer to this is a firm "no".  The features disabled don't
> appear in many, or indeed most, examples of complex Scala source code.  For
> example, you can do some crazy, crazy things using libraries like Scalaz
> without ever touching higher-kinded types, existentials or similar in your
> client code.  Obviously the library will use these features, but there's
> nothing we can do about this (see also: collections).  Maybe an even better
> example are the knots you can tie yourself in with trait linearization and
> really inheritance in general.  Oh, and let's not forget about implicits!
> These are features that yield code that is empirically complex, but of
> course they are far too intrinsic to be removed or disabled.
>
It's true that the "import tax" of the proposal is typically levied on
library constructs which can lead to complicated usages (postfix ops
are the only exception). That's a conscious decision. Demanding the
same from users of such libraries would be too cumbersome, I think.

> People (read: not PLT enthusiasts) don't care about the complexity (or
> simplicity) of the language.  All they care about is the complexity (or
> simplicity) of the code that the language carrots them to write.  If we want
> to address the "Scala is too complex" claims, it should be based on concrete
> examples of that complexity (code, not vague feature lists) and very careful
> root-cause investigation.  In the end, addressing such issues at the
> language level is very nearly a lost cause.  The implications of any
> language change are far too vast and cross-cutting; and the issues at hand
> are far too subtle to be resolved by so blunt an approach as disabling
> language features whole-sale.
>

Well, they are not disabled. Just brought out in the open. I am pretty
sure that the concept of explicit feature imports will have a net
beneficial effect on large Scala projects. We can discuss about the
details what should go under a flag and what shouldn't. Those a much
more tentative in my mind than the idea itself.

Cheers

-- Martin

Daniel Spiewak

unread,
Mar 17, 2012, 10:49:10 PM3/17/12
to scala...@googlegroups.com
It's true that the "import tax" of the proposal is typically levied on
library constructs which can lead to complicated usages (postfix ops
are the only exception). That's a conscious decision. Demanding the
same from users of such libraries would be too cumbersome, I think.

This is exactly my point.  The features which enable the most complex uses aren't even touched by the import tax.  In order of significance, I have seen the most complexity in client code enabled by the following features:
  • Traits
    • Leaky linearization semantics (e.g. null vals)
    • Path-dependent types (even concrete, non-existential ones)
  • Implicit resolution (conversions are confusing, but rarely complex)
  • Arcane applications of var (particularly when intersected with function values)
Most uses of type constructor polymorphism I have seen have been extremely straightforward.  Ditto for structural types.  Postfix operators are only a problem because of semicolon inference.  Could we get a compiler switch to turn that feature off?  That's actually something I could get behind…

Existential types are probably a more valid point here.  I find them ridiculously useful, but I doubt many people use them beyond Java interop.  On the plus side, I've never seen a truly complex use of existential types (i.e. where the feature introduced complexity above and beyond the problem domain), but that could be just because it's generally impossible to get a usage of existential types to even compile without really knowing what you're doing.  In short, existential types allow significant complexity in client code, but they're only ever used in cases where such complexity is unavoidable.  So, the language is doing its job as it stands.

Daniel

Daniel Spiewak

unread,
Mar 17, 2012, 11:00:20 PM3/17/12
to scala...@googlegroups.com
I believe my development experience is different than yours then. In
codebases I contribute to, these features are very rarely used. To a
point, where I would welcome a warning if they are indeed used. So I
believe it will be an invisible change for the majority, a welcome
change for most people on the borderline, and a small nuisance for a
few.

Having to mechanically insert a bulky import statement at the top of every single file is not a "small" nuisance.  (regarding bulky, note that "import language._" is insufficient since I don't want things like macros and dynamic by default)
 
That's a good point. I actually think it's by far preferable if people
who do not know about using these features are notified. That way they
can look up the documentation for the feature, learn about it, and
then make a conscious decision whether they want to use it.

On what grounds would they be making that decision?  I can virtually guarantee that the thought process will go as follows:

1. Ask question on Stackoverflow
2. <wait 30 seconds>
3. Read answer by Daniel Scobral, posted 20 seconds ago (page refresh delay)
4. Paste snippet into code base
5. Receive giant scary warnings about some thingy that you don't recognize
6. Google "some thingy" (or possibly ask again on Stackoverflow)
7. Get directed to detailed technical explanation of "some thingy"
8. While skimming the 30 page PDF, encounter first instance of \inferrule*
9. Panic

I don't think the net result here will be enlightenment, nor do I believe this change will encourage people to make an informed decision about certain language features.  Rather, I think the majority of people will hit the scary warning, skim some scary documentation, and decide that it's probably easier to use asInstanceOf.  In other words, it is short-circuiting the learning process, not encouraging its progression.
 
I don't think this will lead to fragmentation. These are very specific
features. For most discussions about the language it would actually be
very beneficial to rule out from discussion dispatch via dynamic, just
to pick an example. Where people do talk about specific features, it
will become common understanding to assume the import.

Experienced Scala developers will simply turn everything on.  Discussions they carry out, articles they post and talks they present will all make this assumption.  Incoming Scala developers (who don't know about the magical switches) will be using a literally different language until they graduate into the elite group.

Currently, we're in a situation where experienced Scala developers understand and leverage certain features that appear magical to newcomers.  Thus, experienced Scala developers have an understanding that newcomers haven't acquired yet (as a rule).  This SIP would put us in a position where not only do experienced Scala developers have additional understanding, they are also in position of the secret keys for unlocking the hidden doors to this magical kingdom of understanding.  It's throwing barriers in the path of those attempting to fully learn the language, and barriers always lead to fragmentation.

Daniel

Paul Phillips

unread,
Mar 17, 2012, 11:04:21 PM3/17/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 7:49 PM, Daniel Spiewak <djsp...@gmail.com> wrote:
> Could we get a compiler switch to turn that feature off?  That's actually
> something I could get behind…

Yeah, I have a whole list of stuff I'd like to turn off, and this SIP
misses my list completely. Auto-coercions between primitives,
any2stringadd, auto-tupling...

The only thing I can see which I have any enthusiasm for is developing
some mechanism to control reflection. But this would not be a
satisfactory mechanism.

We'd be so much better off putting effort into something like checkstyle.

Miles Sabin

unread,
Mar 17, 2012, 11:05:40 PM3/17/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 3:04 AM, Paul Phillips <pa...@improving.org> wrote:
> We'd be so much better off putting effort into something like checkstyle.

Oh yes ...

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
gtalk: mi...@milessabin.com
skype: milessabin
g+: http://www.milessabin.com
http://twitter.com/milessabin
http://underscoreconsulting.com
http://www.chuusai.com

martin odersky

unread,
Mar 17, 2012, 11:06:24 PM3/17/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 4:00 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
>
>> I believe my development experience is different than yours then. In
>> codebases I contribute to, these features are very rarely used. To a
>> point, where I would welcome a warning if they are indeed used. So I
>> believe it will be an invisible change for the majority, a welcome
>> change for most people on the borderline, and a small nuisance for a
>> few.
>
>
> Having to mechanically insert a bulky import statement at the top of every
> single file is not a "small" nuisance.  (regarding bulky, note that "import
> language._" is insufficient since I don't want things like macros and
> dynamic by default)

As the SIP states, import language._ would do nothing; you need
explicit imports. But come on, how many of these do you propose to use
in a single source file at the same time?

>>
>> That's a good point. I actually think it's by far preferable if people
>> who do not know about using these features are notified. That way they
>> can look up the documentation for the feature, learn about it, and
>> then make a conscious decision whether they want to use it.
>
>
> On what grounds would they be making that decision?  I can virtually
> guarantee that the thought process will go as follows:
>
> 1. Ask question on Stackoverflow
> 2. <wait 30 seconds>
> 3. Read answer by Daniel Scobral, posted 20 seconds ago (page refresh delay)
> 4. Paste snippet into code base
> 5. Receive giant scary warnings about some thingy that you don't recognize
> 6. Google "some thingy" (or possibly ask again on Stackoverflow)
> 7. Get directed to detailed technical explanation of "some thingy"
> 8. While skimming the 30 page PDF, encounter first instance of \inferrule*
> 9. Panic

Well, that depends how we structure the docs, no?


>
> I don't think the net result here will be enlightenment, nor do I believe
> this change will encourage people to make an informed decision about certain
> language features.  Rather, I think the majority of people will hit the
> scary warning, skim some scary documentation, and decide that it's probably
> easier to use asInstanceOf.  In other words, it is short-circuiting the
> learning process, not encouraging its progression.
>
>>
>> I don't think this will lead to fragmentation. These are very specific
>> features. For most discussions about the language it would actually be
>> very beneficial to rule out from discussion dispatch via dynamic, just
>> to pick an example. Where people do talk about specific features, it
>> will become common understanding to assume the import.
>
>
> Experienced Scala developers will simply turn everything on.  Discussions
> they carry out, articles they post and talks they present will all make this
> assumption.  Incoming Scala developers (who don't know about the magical
> switches) will be using a literally different language until they graduate
> into the elite group.

I guess I am an experienced Scala programmer :-) and I can guarantee
you I will turn on nothing by default. I know where I need to use
macros and higher-kinded types, and am totally prepared to declare
that explicitly.

Cheers

- Martin

Daniel Spiewak

unread,
Mar 17, 2012, 11:10:14 PM3/17/12
to scala...@googlegroups.com
Well, they are not disabled. Just brought out in the open.

Forgot to reply to this in my earlier email.  Throwing out a warning is almost the same as disabling them.  Issuing an error (as proposed in the SIP) is definitionally the same as disabling them.

Here's my proposal.  There are certain features like macros and dynamic that the whole community (well, almost the whole community) agrees should be off by default.  Maybe this is because these features haven't stabilized yet (like continuations), or maybe it's because these features have far-reaching and surprising implications.  These features should be off by default and enabled by a feature switch (like -Fenable-dynamic).

There are other features that have been identified by some people as being problematic or dangerous (e.g. structural types and existentials) but are not generally accepted to be net negatives.  Likely, this situation is because these features are "advanced", or perhaps have surprising implications, but have a generally neutral or positive impact on most development.  These features should be on by default and disabled by a feature switch (like -Fdisable-existentials).

I don't think anyone has complained about the off-by-default status of dynamic or macros.  Making the other features (higher kinds, existentials, structural types) on by default with a disabling switch gives people the flexibility to opt out at a project level if they really want to prevent the use of some feature.  More granular control could be implemented in the same way that -enable-assertions is handled by the JVM itself (i.e. at the package or compilation unit level).

No magical pragma or import overloading would be added.

I think this proposal actually satisfies all of the cases and objections voiced so far.  Most significantly, it avoids stratifying the Scala language into "levels" based on apparent advancement of certain features.  Perhaps more significantly, this would be an opt-in system.  Nothing would need to change for people who aren't interested in the feature.  Only those who really care would have to put in any effort.  (pay for what you use)

Daniel

Daniel Spiewak

unread,
Mar 17, 2012, 11:11:34 PM3/17/12
to scala...@googlegroups.com
Turning off any2stringadd is something I would absolutely get behind.  Should probably still be opt-in (for the reasons outlined in my other emails), but I would definitely be using that switch on every build I control.

+1 to the checkstyle solution.

Daniel

martin odersky

unread,
Mar 17, 2012, 11:14:20 PM3/17/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 4:04 AM, Paul Phillips <pa...@improving.org> wrote:
> On Sat, Mar 17, 2012 at 7:49 PM, Daniel Spiewak <djsp...@gmail.com> wrote:
>> Could we get a compiler switch to turn that feature off?  That's actually
>> something I could get behind…
>
> Yeah, I have a whole list of stuff I'd like to turn off, and this SIP
> misses my list completely.  Auto-coercions between primitives,
> any2stringadd, auto-tupling...

Feel free to add to the list! Auto-tupling is a good candidate, I
completely overlooked that. any2stringadd, I would love to get rid of,
but that will need to be at some point in the future, now is
premature.

>
> The only thing I can see which I have any enthusiasm for is developing
> some mechanism to control reflection.  But this would not be a
> satisfactory mechanism.
>
> We'd be so much better off putting effort into something like checkstyle.

I was thinking a lot about it, but: checkstyle has not materialized,
and will not materialize in foreseeable time. And the reason is the
same as this proposal: it's probably too hard to develop a consensus
what should go in it. And, anyway, the current proposal does not
preclude a checkstyle later.

Cheers

- Martin

martin odersky

unread,
Mar 17, 2012, 11:19:33 PM3/17/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 4:10 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
>> Well, they are not disabled. Just brought out in the open.
>
>
> Forgot to reply to this in my earlier email.  Throwing out a warning is
> almost the same as disabling them.  Issuing an error (as proposed in the
> SIP) is definitionally the same as disabling them.

How is requiring an explicit import the same as disabling a feature?


>
> Here's my proposal.  There are certain features like macros and dynamic that
> the whole community (well, almost the whole community) agrees should be off
> by default.  Maybe this is because these features haven't stabilized yet
> (like continuations), or maybe it's because these features have far-reaching
> and surprising implications.  These features should be off by default and
> enabled by a feature switch (like -Fenable-dynamic).
>

OK, that's something we agree on then. I still like the import
solution much better then the switch.

> There are other features that have been identified by some people as being
> problematic or dangerous (e.g. structural types and existentials) but are
> not generally accepted to be net negatives.  Likely, this situation is
> because these features are "advanced", or perhaps have surprising
> implications, but have a generally neutral or positive impact on most
> development.  These features should be on by default and disabled by a
> feature switch (like -Fdisable-existentials).
>

I don't like explicit disabling. It violates the principle that simple
things should be kept simple. And it complicates the machinery
considerably. Now you'd have to explain how to resolve an enabling
import that clashes with a disabling flag. I don't want to get into
that!

Cheers

- Martin

Dan Rosen

unread,
Mar 17, 2012, 11:20:52 PM3/17/12
to scala...@googlegroups.com
Hi all,

This SIP comes conspicuously on the heels of several months worth of internet noise, to the effect of "OMG Scala is crazy!"  New terms have been coined, including notably "complainxity" and "peak abstraction."  I personally believe that Scala is a very exciting experiment on two fronts: the implementation of sophisticated type systems, and the reeducation and reinvigoration of a mostly stagnant and commoditized industry.  In other words, Scala is trying to achieve both technological and sociological progress.  It's easy to conflate the two, though, and run afoul of Edwards' law: "you cannot apply a technological solution to a sociological problem," which is what I believe this SIP is mistakenly trying to do.  The document states, "with the increasing adoption of Scala in mainstream programming, we have seen rising demands for better guidance," but real guidance is far from what this proposal provides.

Scala is a powerful programming language, and its expressive power continues to increase.  Existing powerful features, including existential and higher-kinded types, structural types and refinements, implicits and so on are being further augmented with macros.  The argument that these features are only applicable in a narrow range of applications (specifically, library and DSL design) is, in my opinion, predicated on the notion that most people don't know how to learn new things and apply them in clever new ways.  Certainly when people try to learn new things, they may shoot themselves in the proverbial foot a few times, and they'll no doubt blog or tweet their pain.  But taking steps to explicitly discourage use of certain features -- or to delineate where a given language feature is and isn't appropriate -- is counterproductive.  Instead, on the theme of providing "better guidance," those of us who are inclined to blog, publish and talk for the sake of education should do so.  Scala is still young.  Over time, the base level of competency and collective judgment over best practices and design patterns will increase to an acceptable level, as it did for C++ in the early 2000s thanks to folks like Herb Sutter and Andrei Alexandrescu.

Besides trying to keep newcomers "safe," for some definition of the word, this SIP seems to be trying to address several other concerns at the same time:

  - allowing for "mistakes" in the language design to be corrected (e.g. syntactic constructs, higher-kinded types)
  - preventing inadvertent performance bugs
  - sandboxing code that uses reflection
  - keeping type inference decidable, mostly
  - keeping Scala decoupled, hypothetically, from the JVM (if I understand the "reflection is not available on all platforms" comments correctly)

In my mind, this all boils down to "language design is hard."  Which it truly is, as far as I can tell, especially when you're trying to take your language mainstream.  But again, I don't believe this SIP provides good solutions to any of the above problems.  We're not only confusing technological issues with sociological issues here, we're also confusing "advanced", "contentious", "brittle" and "unsound."  Each of the goals articulated by this SIP are worthwhile to pursue, I think, but it takes time to get them all correct and in a form that you're happy with.  A long time.

Okay, the preceding was my overall impressions and thinking about this proposal as a whole.  Now there are a few specific issues I want to raise:

The features controlled by flags are enabled in the whole scope where the import statement is effective.

This seems like it could be either extremely tricky or unimplementable.  Do you have more detail about how this would work?

macros can lead to code that is hard to debug and understand.

Programming can lead to code that is hard to debug and understand.  The only ways I know of to avoid this are becoming an incredibly good programmer, or not programming.  Macros used appropriately can lead to code that is much easier to understand and much harder to screw up than the alternative.  And on a related note, as we've seen with Java, good tool support (IDEs, profilers, etc.) is crucial.

Even where reflection is available, structural type dispatch can lead to surprising performance degradations.

Again, so can programming.  In my experience, the biggest "surprising" performance issues have been because somebody screwed up their DB connection pool configuration, screwed up the design of their network protocol, or worse, simply didn't understand the time/space complexity of the data structures they were using.  And by "somebody," of course I mean "me."  Sure, reflection is slow, but stupidity is slower.  In any case, if the goal of using structural types is just to achieve ad-hoc polymorphism, then Scala has other reasonably elegant facilities (i.e. implicits) that don't use reflection.

Dynamic member selection can undermine static checkability of programs.

Certainly, no argument there.  But I feel like the fact that you're creating or using instances of classes that have "Dynamic" as a base trait is sufficient documentation both for developers and for tools.

Several DSLs written in Scala need [postfix operator] notation.

So anybody using these DSLs would need to "import language.postfixOps" to make idiomatic use of them.  Worse, developers that try to be diligent about avoiding scope pollution would have to declare this import in every bottom-level scope where they are making use of such a DSL.  Yuck.

Best,
dr

Eugene Yokota

unread,
Mar 17, 2012, 11:21:48 PM3/17/12
to scala...@googlegroups.com
Hi Martin,

After reading over the SIP a few times,
I think the general direction of modularizing the language/standard libary is a good one.
This would allow introduction of library-like features that requires changes to parsers
without affecting those who do not need the feature.
For example, XML literals, numerics, actors, is something that comes to my mind for module candidates.

However, I disagree with the motivation stated in SIP:
> I therefore propose a scheme where some of the more advanced and contentious language features have to be enabled explicitly...

The contentions would not magically go away by hiding the feature listed in the SIP. 

I also disagree with hiding any of the types present in Scala 2.9.1. The type system, complex or not, is what makes Scala what it is. Warning/error flags would be more appropriate for restricting the use of structurals/implicits etc.
The current participants of the community have climbed the mountain with you to learn this stuff as Scala grew. So why punish us now?

However, the motivation of controlling the growth of the language going forward, and modularizing standard library, plugins, and experimental features is something I can understand. 
If substituting XML literal implemetation or introducing new plugin were as easy as adding a line in my build.sbt that'll be great. It'll keep the core jar small.
That would satisfy the need for research community's desire to introduce new advanced features, and industry's desire to manage the code base written in Scala.

-eugene

Daniel Spiewak

unread,
Mar 17, 2012, 11:21:39 PM3/17/12
to scala...@googlegroups.com
As the SIP states, import language._ would do nothing; you need
explicit imports. But come on, how many of these do you propose to use
in a single source file at the same time?

So, not only are we overloading import, we're also giving the overloaded import wildcard a silently different semantic?  This is complexity from a linguistic standpoint.

Actually, most of the time when I'm using existentials, I'm also using type constructor polymorphism.  Not always, but mostly.  I'm always using type constructor polymorphism when I use structural types, simply because I primarily use structural types for the type lambda mechanism.  As for postfix operators, I know the style guide says not to use them, but I must confess that I do make use of them on a fairly regular basis, generally without thinking about it.  So, at a minimum, the header of all of my source files would have:

import language.{postfix, existentials, higherKinds}

Given the cognitive speed bump that an error on a "disabled feature" would cause, I would probably fall into the habit of just turning stuff on by default and forgetting about it.

Well, that depends how we structure the docs, no?

Scala doesn't have the greatest track record when it comes to documentation for beginners.  :-)  Granted, things have improved exponentially with Heather at the helm.  It would take some fantastic writing to explain the full potential of existential types in such a way that a complete newcomer would not glaze over and/or run in terror.  Not impossible, but very hard.

I guess I am an experienced Scala programmer :-) and I can guarantee
you I will turn on nothing by default. I know where I need to use
macros and higher-kinded types, and am totally prepared to declare
that explicitly.

It's a bit like a penalty for using those features.  I want to be able to use Scala without any impingement on my train of thought.  Remembering to inject a magical import in order to use a language feature is a significant added overhead, given that import is a mechanism for enabling library features.

I can understand the desire to make the language safer and carrot people to use less "surprising" features.  I'm not sure this accomplishes that task though.  What I am sure it accomplishes is tremendous annoyance in the upper tier of Scala developers, as evidenced by all of the rancor this has stirred up both here and on Twitter.

Daniel

martin odersky

unread,
Mar 17, 2012, 11:22:21 PM3/17/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 1:20 AM, Simon Ochsenreither
<simon.och...@googlemail.com> wrote:
> Hi Martin,
>
> a few notes from my first expression:
>
> “language” could lead to confusion for Java developers, because of java.lang
> Would we still have -Xmacro? Or would import language.macro replace it?

-Xmacro would be replaced.

> How would this relate to Predef? Wouldn't the SIP amount to something like a
> different Predef where more or less is brought into the scope?

No I think it is more helpful to bring everything into scope but issue
errors or warnings
if a flag is required.

> Any chance to add any2stringadd and the numeric conversions from integer
> types to floating point to the enum, e. g. all the arcane Java compat stuff?

I believe that would affect way too many programs. I'd love
invalidating any2stringadd but we need at least have string
interpolation as an alternative in place and then wait until virtually
all code uses that instead of + on strings. That will take a long
time. Numeric conversions: It's one of the areas where we have decided
not to reinvent the wheel and just take what Java has.

> Some of the stuff feels like it could be easier solved by not putting it in
> a place where it is available by default. E.g. “scala.Dynamic needs import
> language.dynamic”. Why not put it somewhere like scala.lang.Dynamic to
> require an explicit import?

Because it would also affect indirect inheritance.

trait MyDynamic extends Dynamic { def applyDynamic(name: String) ... }

trait Dispatcher extends MyDynamic // needs import language.dynamic to work.

> postfixOps is scary .... we switch the Parser based on an import?

No, we just flag postfix ops after the parser with warnings.

> structuralTypes looks interesting. So without it new Object { val member = 1
> } will generate the same anonymous class, but won't have the structural
> type? In the end I think performance will be on par when Scala will start
> targeting Java >= 7, so it feels like an optimization we won't need in the
> long term. Which platform would suffer from it?

I know of Scala-GWT, but that's only experimental. I thought first
Android as well, but that seems to have reflection. So maybe the
problem is not as bad as I thought.

Cheers

- Martin

Paul Phillips

unread,
Mar 17, 2012, 11:23:23 PM3/17/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 8:14 PM, martin odersky <martin....@epfl.ch> wrote:
>
> I was thinking a lot about it, but: checkstyle has not materialized,
> and will not materialize in foreseeable time. And the reason is the
> same as this proposal: it's probably too hard to develop a consensus
> what should go in it.

What's great about checkstyle is that you don't need any consensus.
It's configurable. Turning off the language isn't configuring, it's
splintering.

The thing is, I am more certain than I would like to be (yes, I would
genuinely prefer to be less certain) that none of this will help with
the problem it's presumably trying to address. I think we should
measure ideas like this by comparing "time wasted" to "time saved" and
"confusion added" to "confusion subtracted" and "busywork created" to
"busywork avoided". The wrong side of those scales is going to look
like it just landed on jupiter. And not just for the people who
utilize the features being targeted. For everyone.

Daniel Spiewak

unread,
Mar 17, 2012, 11:31:27 PM3/17/12
to scala...@googlegroups.com
How is requiring an explicit import the same as disabling a feature?

The explicit import isn't an import at all, but a compiler pragma in the syntactic guise of an unrelated language feature.  As with any compiler pragma, the net effect is to change the behavior of the compiler, and thus, the language.

If a feature is disabled by default, then it is not in the language (by definition).  This is why Haskell discussions separate "Haskell" from "Haskell with GHC extensions".

I don't like explicit disabling. It violates the principle that simple
things should be kept simple. And it complicates the machinery
considerably. Now you'd have to explain how to resolve an enabling
import that clashes with a disabling flag. I don't want to get into
that!

I would remove the import mechanism entirely.  Pragma was evil back in the days of C.  Introducing it to Scala, especially when disguised as an orthogonal feature, is just begging for pain (like the pain of disambiguating compiler switches vs imports).

I think the compiler switch is still keeping things simple.  In fact, I think it keeps things simpler than the import mechanism, which introduces a very weird and non-orthogonal feature into the core language semantics.  A compiler switch enables teams to make and control decisions about these features at a high level.  It's much easier to police your build.sbt than it is to police an entire codebase, grepping for a construct that uses the same syntax as another (very commonly-used) one.  Additionally, compiler switches are generally understood to affect the semantics of the compiler.  That is, after all, their purpose.  Thus, they fit precisely within the template concept that already exists.  Using compiler switches doesn't introduce any complexity, but using an "import" does.

How does the explicit "import" interact with scoping?  Can we have certain typer features activated for part of our file but not another part?  What if higher kinds are enabled inside a method but not outside?  What error do we get if features "leak" through type inference?  There's just a whole host of questions that arise when you start introducing language features – you must know this better than I!  Compiler switches are the simpler mechanism, by far.

Daniel

martin odersky

unread,
Mar 17, 2012, 11:31:41 PM3/17/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 4:23 AM, Paul Phillips <pa...@improving.org> wrote:
> On Sat, Mar 17, 2012 at 8:14 PM, martin odersky <martin....@epfl.ch> wrote:
>>
>> I was thinking a lot about it, but: checkstyle has not materialized,
>> and will not materialize in foreseeable time. And the reason is the
>> same as this proposal: it's probably too hard to develop a consensus
>> what should go in it.
>
> What's great about checkstyle is that you don't need any consensus.
> It's configurable.  Turning off the language isn't configuring, it's
> splintering.
>
I see it the other way around. It's forming a standard what idiomatic
Scala usage for general projects is. There's no prejudice against
controlled features except saying and documenting: watch out, here are
some complications, make sure you understand them before you decide to
use the feature. So it's actually the opposite of splintering.

> The thing is, I am more certain than I would like to be (yes, I would
> genuinely prefer to be less certain) that none of this will help with
> the problem it's presumably trying to address.  I think we should
> measure ideas like this by comparing "time wasted" to "time saved" and
> "confusion added" to "confusion subtracted" and "busywork created" to
> "busywork avoided". The wrong side of those scales is going to look
> like it just landed on jupiter.  And not just for the people who
> utilize the features being targeted.  For everyone.

Individual features can be discussed. I am 100% certain that Dynamic
and macros need a feature import. I would dearly like postfix ops to
be under the same regime. I gave reasons for putting in the other
three, but am open to discussions.

Cheers

-- Martin

martin odersky

unread,
Mar 17, 2012, 11:35:12 PM3/17/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 4:31 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
>
>> How is requiring an explicit import the same as disabling a feature?
>
>
> The explicit import isn't an import at all, but a compiler pragma in the
> syntactic guise of an unrelated language feature.  As with any compiler
> pragma, the net effect is to change the behavior of the compiler, and thus,
> the language.
>
> If a feature is disabled by default, then it is not in the language (by
> definition).  This is why Haskell discussions separate "Haskell" from
> "Haskell with GHC extensions".
>

I disagree. As long as a feature is specified in the SLS it is in the
language. The fact that it requires an explicit import does not change
that.

>> I don't like explicit disabling. It violates the principle that simple
>> things should be kept simple. And it complicates the machinery
>> considerably. Now you'd have to explain how to resolve an enabling
>> import that clashes with a disabling flag. I don't want to get into
>> that!
>
>
> I would remove the import mechanism entirely.  Pragma was evil back in the
> days of C.  Introducing it to Scala, especially when disguised as an
> orthogonal feature, is just begging for pain (like the pain of
> disambiguating compiler switches vs imports).
>
> I think the compiler switch is still keeping things simple.  In fact, I
> think it keeps things simpler than the import mechanism, which introduces a
> very weird and non-orthogonal feature into the core language semantics.  A
> compiler switch enables teams to make and control decisions about these
> features at a high level.  It's much easier to police your build.sbt than it
> is to police an entire codebase, grepping for a construct that uses the same
> syntax as another (very commonly-used) one.  Additionally, compiler switches
> are generally understood to affect the semantics of the compiler.  That is,
> after all, their purpose.  Thus, they fit precisely within the template
> concept that already exists.  Using compiler switches doesn't introduce any
> complexity, but using an "import" does.
>
> How does the explicit "import" interact with scoping?  Can we have certain
> typer features activated for part of our file but not another part?

I do not see why not.

> What if
> higher kinds are enabled inside a method but not outside?  What error do we
> get if features "leak" through type inference?  There's just a whole host of
> questions that arise when you start introducing language features – you must
> know this better than I!  Compiler switches are the simpler mechanism, by
> far.

I believe this is explained in the SIP. It's not yet implemented, so
there might still be surprises here. But a priori I think it's doable.

Cheers

- Martin

Paul Phillips

unread,
Mar 17, 2012, 11:41:46 PM3/17/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 8:22 PM, martin odersky <martin....@epfl.ch> wrote:
> Numeric conversions: It's one of the areas where we have decided
> not to reinvent the wheel and just take what Java has.

Nobody wants to reinvent this wheel! They want to TURN THE WHEEL OFF.

Daniel Spiewak

unread,
Mar 17, 2012, 11:49:56 PM3/17/12
to scala...@googlegroups.com
I disagree. As long as a feature is specified in the SLS it is in the
language. The fact that it requires an explicit import does not change
that.

Ok, I'll buy that.  It seems you're viewing the explicit import not as a pragma, but as a lexically scoped flag.  Still, horrifying to contemplate from a formal perspective, but not as horrifying as I initially thought.

For the record, the overloading of import is still really problematic, precisely because overloading anything tends to introduce a lot of complexity and cognitive burden.  By definition, it requires one to consciously consider whether this construct refers to concept A or concept B.  The proposed "language import" is a very different concept from a library import and has very different effects.  Lumping it under the same syntactic construct seems…wrong, to put it mildly.

I do not see why not.

Weren't you the one telling me that the typer is already too complex?  ;-)
 
I believe this is explained in the SIP. It's not yet implemented, so
there might still be surprises here. But a priori I think it's doable.

I still think leaking is going to be a serious problem.  At the very least, it will need to be resolved in a somewhat arbitrary fashion, creating confusion and frustration for those attempting to use the feature.  A compiler switch is much clearer in this area; there is absolutely no uncertainty about where and how its effects will be applied.

Daniel

Daniel Sobral

unread,
Mar 18, 2012, 12:18:50 AM3/18/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 18:07, Rex Kerr <ich...@gmail.com> wrote:
> The big problem with this proposal is that it threatens to add a bunch of
> boilerplate to every single existing Scala file and program and REPL
> session.  With all these things off by default, I would argue that Scala is
> severely curtailed; why make everyone in every file and script type in
> "import language._" in order to enable the features that make you use Scala
> instead of something else?  And then, you get not only the features of a
> present-day typical Scala distribution, but early versions of features that
> are not yet fixed; if you want "full power but stable" Scala, you end up
> with quite a mouthful:
>   import language.{postfixOps, structuralTypes, higherKinded, existentials}
>
> Instead, I propose that, if there is a significant demand for limiting
> language features, that we flip the sign: instead of requiring import
> language.structuralTypes to get structural types, import
> language.disable.structuralTypes if you want them to go away.  If you're in
> a development environment with strict coding rules anyway, you probably will
> have half a screen of stuff at the top of every file anyway (copyright
> notice, imports of a bunch of libraries, etc.), so one more line doesn't
> really hurt that much.
>
> Features that really are experimental could be kept as an import
> language.enable._ so that people are alerted that they shouldn't trust how
> they behave.  For example, macros would be a good candidate here since
> they're not ironed out.  Furthermore, some things that are compiler flags
> could be moved to language.enable (such as continuations), where they
> arguably more sensibly belong.
>
> (Actually, even more sensibly, they'd be annotations on the file.)

I'm fully with Rex here. I've made a number of comments on the
proposal, but just seeking clarification on the exact mechanics of
various parts. But I don't like it. Yes, there are people who'd prefer
to limit the extent to which the language is available, but they can
easily add disable flags to their builds. I think Rex proposal of
having stable features enabled by default and experimental disabled by
default strikes a good balance.

--
Daniel C. Sobral

I travel to the future all the time.

Daniel Spiewak

unread,
Mar 18, 2012, 12:23:37 AM3/18/12
to scala...@googlegroups.com
I'm fully with Rex here. I've made a number of comments on the
proposal, but just seeking clarification on the exact mechanics of
various parts. But I don't like it. Yes, there are people who'd prefer
to limit the extent to which the language is available, but they can
easily add disable flags to their builds. I think Rex proposal of
having stable features enabled by default and experimental disabled by
default strikes a good balance.

In case it was lost in my flurry of emails, I am in favor of this proposal as well.  Unstable (or generally-accepted as "dangerous") features should be off by default with flags to enable.  Stable (and generally-accepted as "safe") features should be on by default with flags to disable.  any2stringadd gets burned in effigy until such time as it can be flag-disabled.

Daniel

Daniel Sobral

unread,
Mar 18, 2012, 12:24:18 AM3/18/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 18:40, martin odersky <martin....@epfl.ch> wrote:

> On Sat, Mar 17, 2012 at 10:07 PM, Rex Kerr <ich...@gmail.com> wrote:
>> The big problem with this proposal is that it threatens to add a bunch of
>> boilerplate to every single existing Scala file and program and REPL
>> session.  With all these things off by default, I would argue that Scala is
>> severely curtailed; why make everyone in every file and script type in
>> "import language._" in order to enable the features that make you use Scala
>> instead of something else?  And then, you get not only the features of a
>> present-day typical Scala distribution, but early versions of features that
>> are not yet fixed; if you want "full power but stable" Scala, you end up
>> with quite a mouthful:
>>   import language.{postfixOps, structuralTypes, higherKinded, existentials}
>>
> I believe that depends how important you find these features for daily
> (as opposed to specialized) Scala use. To take the Scala compiler with
> 100K lines as an example: As far as I know, there are no uses of
> postfix ops, there is one use of structural types (and we are trying
> to get rid of it), there are no uses of higher-kinded types, and any
> use of complex existentials, if it exists, I would deem a mistake. So
> from that perspective, yes, I would value having to import features
> explicitly so that I am warned from using these things accidentally.

Well, here you have me a bit. Yes, I'd prefer to disable postfix
methods, but adding that line to all specs files will be annoying.
Yes, I'd prefer to disable structural types, mostly to prevent
performance issues due to carelessness. And, yes, I'd like to disable
existentials, because people who try to use them are usually people
who shouldn't, because they don't know enough. However, the most
common use of existentials under this proposal is not caught. But...
this is my laundry list, my personal preferences. I don't see any
reason to burden others with it, and I'm not at all sure I should.

Daniel Sobral

unread,
Mar 18, 2012, 12:25:56 AM3/18/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 20:41, Derek Wyatt <de...@derekwyatt.org> wrote:
> Yup.  +1 here.
>
> There's no value in explicitly requiring a user to load the gun before
> shooting it.  If they want to use Macros, they're going to use them... all
> you're really doing is forcing them to put in some boilerplate first.  It
> doesn't stop them from using it, it just makes using it annoying.
>
> Flip the sign and now you can "protect" your code against unwanted features
> (if even that's a desirable thing, which I'm not convinced on).

Oh, yes, it is. A structural type, in particular, can ruin your day
performance-wise. It has happened on the standard library.

Daniel Sobral

unread,
Mar 18, 2012, 12:32:05 AM3/18/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 21:49, Josh Suereth <joshua....@gmail.com> wrote:
> (4) Dynamic typing is dangerous to type safety, so it belongs behind an
> opt-in "I know better" "asInstanceOf" kind of flag.  Open the box at your
> own risk.

> (4) Not sure this should default off or on, but the idea of a flag for
> dynamic typing is great IMHO.  If I want guaranteed type safety (and the
> niceties, like refactoring that come with it) in a project, I want this.

And, on that note, I'd add asInstanceOf to number 4. It can cause just
as much trouble as dynamic types, and it is much more likely to be
used by beginners (because of Java). Pattern matching can deal with
most use cases.

Daniel Sobral

unread,
Mar 18, 2012, 12:44:09 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 00:04, Paul Phillips <pa...@improving.org> wrote:
> On Sat, Mar 17, 2012 at 7:49 PM, Daniel Spiewak <djsp...@gmail.com> wrote:
>> Could we get a compiler switch to turn that feature off?  That's actually
>> something I could get behind…
>
> Yeah, I have a whole list of stuff I'd like to turn off, and this SIP
> misses my list completely.  Auto-coercions between primitives,
> any2stringadd, auto-tupling...

Yes, yes and yes. However, isn't any2stringadd a library feature? Or,
if you are refering to String+Any, wouldn't Any+String still be in the
library? I ask this just because I want it completely gone, not just
halfway. :-) Particularly now that we might well get string templates.

>
> The only thing I can see which I have any enthusiasm for is developing
> some mechanism to control reflection.  But this would not be a
> satisfactory mechanism.
>
> We'd be so much better off putting effort into something like checkstyle.

And yes, but between a tool someone might write someday and something
here and now, I understand why that proposal might not be particularly
attractive to Mr. O. But the presentation compiler ought to be helping
build such tools.

Daniel Sobral

unread,
Mar 18, 2012, 12:49:08 AM3/18/12
to scala...@googlegroups.com

Sounds good to me. Should I bring the fuel or the matches?

RYAN RICHT

unread,
Mar 18, 2012, 12:56:15 AM3/18/12
to scala...@googlegroups.com
As someone alluded to, this would indeed substantially complicate adoption and usage at large firms, like Monsanto (views are my own, not Monsanto's).

Our project, the first Scala project here, has now internally gained substantial support. We make use of all of these proposed "modularized" features, and certainly don't need the stigma of them being "dangerous," "difficult to maintain," "too complicated," "too slow," "impossible to hire for," or anything else.

The stigma associated with using Scala at a large, traditionally Java firm is sufficiently burdensome without this SIP. Please don't frustrate adoption further by implementing this SIP. This isn't helping by making Scala simpler, it is making it scarier to use the very features that make Scala high value (+1 on all Daniel Spiewak's comments).

Given the volume of highly negative feedback on this SIP, and years of complaining about more pressing (and high profile) issues like performance optimization of loops, is this *really* the most important SIP to pursue right now given limited resources?

Thank you for a great language,

ryan richt

Paul Phillips

unread,
Mar 18, 2012, 1:02:55 AM3/18/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 9:44 PM, Daniel Sobral <dcso...@gmail.com> wrote:
> Yes, yes and yes. However, isn't any2stringadd a library feature? Or,
> if you are refering to String+Any, wouldn't Any+String still be in the
> library? I ask this just because I want it completely gone, not just
> halfway. :-) Particularly now that we might well get string templates.

I don't draw that distinction when it's arbitrary. If something is
auto-imported into every scope and either impossible to avoid or close
enough, then those are its relevant qualities. (Technically String.+
is implemented with compiler magic, but could have been an implicit
conversion; Any.+(String) is an implicit conversion, but could have
been compiler magic.)

Debasish Ghosh

unread,
Mar 18, 2012, 1:47:23 AM3/18/12
to scala...@googlegroups.com
If the main intention is for users to be warned about sage of specific features which may have impact on performance, can we not think of some static analysis tools that will do the same ? I am somehow not convinced that making it part of the language will be beneficial to the community as a whole. Plus "implicits" is a typical use case (as u have mentioned) where this will not work out. Implicits are too cross cutting and used to implement something as fundamental as typeclasses. There may be more such candidates in future. And this will create some inconsistency with this approach.

Another impact that this approach will encourage is imposition of *my* preferred subset of the language features from the leadership level. This will create code bases which may not be idiomatic Scala. In other words this will encourage fragmentation of the community as well (as Daniel has mentioned in his post).

Thanks. 

On Sun, Mar 18, 2012 at 7:07 AM, martin odersky <martin....@epfl.ch> wrote:
On Sat, Mar 17, 2012 at 11:13 PM, Debasish Ghosh
<ghosh.d...@gmail.com> wrote:
> What's the major force towards this ? Is it only to present a smaller
> surface area to newcomers in Scala ?
>
Definitely not. The selected features are ones which I would prefer to
be explicit about in every codebase I collaborate in. For instance, if
I accidentally use a structural type I want to be warned about it,
mostly because I care about performance. Or, if someone I collaborate
with uses postfix operators I also want to see that upfront. And so
on. So I think the flags will be valuable for most Scala codebases,
with typical exceptions being DSLs.

The main feature left out are implicits. Implicits are probably
misused more often than any other part of Scala, but requiring them to
be put wholesale under a flag would mean we think all type-class
oriented programming is a special case, and that's absurd. So we'd
need a crisp definition what constitutes a problematic implicit
(implicit conversions, maybe?) I could not convince myself of a good
criterion so far, so I left them out.

Cheers

 -- Martin



--
Debasish Ghosh
http://manning.com/ghosh

Twttr: @debasishg
Blog: http://debasishg.blogspot.com
Code: http://github.com/debasishg

Erik Osheim

unread,
Mar 18, 2012, 2:12:04 AM3/18/12
to scala...@googlegroups.com
(I started writing this earlier today, but noticed that others have
made very similar points. I send this to echo them and add support.)

From my point of view, this seems like something that could be
addressed with finer-grained control over generating warnings, as well
as options to turn warnings into errors.

For instance, if I want to be warned about a certain feature (because
it's "slow" or "dangerous" or whatever) I can enable warnings which let
me know when the thing occurs. If I *really* don't want this feature
(for instance I am a manager at Acme Boxes, Inc), I can make those
warnings (or maybe all warnings) become compile errors. My coders might
hate this but it would enforce the standard.

Meanwhile, it leaves the rest of us alone (or possibly requires us to
add a few compiler flags to build.sbt). I already have a bunch of these
(like -deprecated) so I wouldn't necessarily mind adding some more to
be able to use e.g. higher-kinded types.

This won't solve the problem that many of us in the community are
writing code that is perceived as "confusing" or "complex" or
what-have-you. But if the intention is to effect a real change in the
kind of code the community is writing I think the SIP is trying to
address a "social problem" with technology, which is often not a great
idea.

Basically, I am sympathetic to the idea that given developers (or
teams) will want to be able to limit their "feature exposure" but I
oppose mandating per-file-imports by default.

-- Erik

Dan Rosen

unread,
Mar 18, 2012, 3:03:02 AM3/18/12
to scala...@googlegroups.com
Nobody ever likes my essays, so let me rephrase all that in shorter form...  I believe the following:

  - Trying to engineer a solution to a people problem usually doesn't work.
  - You don't have the power to stop people from doing dumb things; you do have the power to ignore them when they blame you.
  - Imposing a singular view of the "right way" for "most people" to write Scala code (or, for that matter, declaring a hierarchy of skill levels à la http://www.scala-lang.org/node/8610) presumes you know how most people think, learn and work.
  - Corollary: "application" vs. "library" is a false dichotomy.  We should do everything we can to encourage novice developers to learn to structure their code as a loosely coupled collection of libraries and DSLs.  Scala is not Java.
  - When a person approaches a task with the assumption that they won't succeed, they probably won't succeed.  Telling novices that certain aspects of Scala are too advanced or dangerous for them is thus self-fulfilling.
  - We simply need to share what we know, and what we are all continuing to learn, about how to write good Scala code.  People will absorb the knowledge in their own ways, on their own schedules, according to their own needs.

dr

On Saturday, March 17, 2012 8:20:52 PM UTC-7, Dan Rosen wrote:
tl;dr

Jean-Laurent Huynh

unread,
Mar 18, 2012, 3:21:12 AM3/18/12
to scala-sips
Hi Rex,

> Features that really are experimental could be kept as an import
> language.enable._ so that people are alerted that they shouldn't trust how
> they behave.

Features that are experimental should still require a compiler flag.
If using macros only requires

import language.macros

It could give the illusion that the feature is stable. The compiler
flag is an effective deterrent that should be there until something is
no longer experimental.

--Jean-Laurent

On Mar 17, 2:07 pm, Rex Kerr <icho...@gmail.com> wrote:
> The big problem with this proposal is that it threatens to add a bunch of
> boilerplate to every single existing Scala file and program and REPL
> session.  With all these things off by default, I would argue that Scala is
> severely curtailed; why make everyone in every file and script type in
> "import language._" in order to enable the features that make you use Scala
> instead of something else?  And then, you get not only the features of a
> present-day typical Scala distribution, but early versions of features that
> are not yet fixed; if you want "full power but stable" Scala, you end up
> with quite a mouthful:
>   import language.{postfixOps, structuralTypes, higherKinded, existentials}
>
> Instead, I propose that, if there is a significant demand for limiting
> language features, that we flip the sign: instead of requiring import
> language.structuralTypes to get structural types, import
> language.disable.structuralTypes if you want them to go away.  If you're in
> a development environment with strict coding rules anyway, you probably
> will have half a screen of stuff at the top of every file anyway (copyright
> notice, imports of a bunch of libraries, etc.), so one more line doesn't
> really hurt that much.
>
> Features that really are experimental could be kept as an import
> language.enable._ so that people are alerted that they shouldn't trust how
> they behave.  For example, macros would be a good candidate here since
> they're not ironed out.  Furthermore, some things that are compiler flags
> could be moved to language.enable (such as continuations), where they
> arguably more sensibly belong.
>
> (Actually, even more sensibly, they'd be annotations on the file.)
>
>   --Rex

Francois Armand

unread,
Mar 18, 2012, 3:55:04 AM3/18/12
to scala...@googlegroups.com


On Sunday, 18 March 2012 04:04:21 UTC+1, Paul Phillips wrote:
On Sat, Mar 17, 2012 at 7:49 PM, Daniel Spiewak <djsp...@gmail.com> wrote:
> Could we get a compiler switch to turn that feature off?  That's actually
> something I could get behind…

Yeah, I have a whole list of stuff I'd like to turn off, and this SIP
misses my list completely.  Auto-coercions between primitives,
any2stringadd, auto-tupling...

The only thing I can see which I have any enthusiasm for is developing


some mechanism to control reflection.  But this would not be a
satisfactory mechanism.

 

We'd be so much better off putting effort into something like checkstyle.




Thanks for that ! Hope your voice will be loud enough...

Trond Olsen

unread,
Mar 18, 2012, 3:58:16 AM3/18/12
to scala...@googlegroups.com
Given Scala pride itself on a small language specification, I find it strange it needs its own SIP to limit language features. This suggestion would at most give you a warnings about said features. Great! You've learnt why those features are marked as such, but shouldn't you've already learnt this while reading Programming in Scala, just like when you read documentation for any API you rely on? In the end, the import will probably just become a nuisance and you'll throw in a language._ instead anyway.

Last time some criticism hit Scala you responded with the Scala levels which I felt was a rushed response. I feel the same here. This is not something, at a whim, that should be put into 2.10 on such a short notice just to counter criticism of Scala. I don't think it'll help at all. Does macros really exert such a heavy toll on the complexity budget of Scala to warrant this?

Francois Armand

unread,
Mar 18, 2012, 4:37:38 AM3/18/12
to scala...@googlegroups.com

Oh yes please !

Francois Armand

unread,
Mar 18, 2012, 4:48:04 AM3/18/12
to scala...@googlegroups.com


On Sunday, 18 March 2012 02:03:26 UTC+1, Peter C. Chapin wrote:

In general I think modularization of large things (for some definition of “large”) is good. Scala is growing rapidly and new features are being added or proposed at a steady rate. What will happen to Scala if this continues indefinitely?

 

Features will start interacting in surprising ways causing an ever increasing number of “gotchas” that programmers will have to worry about. The problem is increased when compatibility with legacy code is thrown into the mix.

 




Well, start to modularize the standard library, and not the language ? And hidding features is not removing them, you (or the Scala dev) will still have to take care of that. Better deprecating and actually removing features.
 

Modularization would allow teams to take some control over the expansion of the language. “Feature X is cool, but we don’t need it. We won’t turn it on and we won’t get any ugly surprises due to some subtle backward-incompatible aspect of feature X. Plus the compiler can optimize our code better if it knows it doesn’t have to deal with feature X.”


But in that case, why not just use some kind of checkstyle ? Far more intrusive for the vast majority, and it allows each team to fine tune what they really want.
 

It’s not the complexity of Scala now that concerns me; it’s the complexity of Scala twenty years from now that I’m worried about. What language can endure continuous growth without eventually falling over under its own weight (think C++)? Perhaps Scala can if it supports a language modularization feature.


Again, evolving the language to keep it simple is really different than hidding features. If ithat is the goal of the proposal, then better thinking deprecated and removing these feature. And at least, that would send a clear signal about what is not considered "the Scala way".

 
 

As an aside Ada has a feature that allows programmers to selectively turn off certain features (pragma Restriction). It isn’t used much but it is used, for example, to simplify the language for purposes of static analysis or to reduce the runtime system requirements, etc. There is definitely value in it, although I notice that Ada’s approach is to present the whole language by default and allow the program to contract it when appropriate.




Yeah... And we see how well it works, even in extremelly controled environment like, say, Ariane 5 dev ?
What generally happen is that these things are quickly turned on a priori and forgotten. And that quite different than a checkstyle, where team policy are checked at each compilation.
 

 

 

From: scala...@googlegroups.com [mailto:scala-sips@googlegroups.com] On Behalf Of Channing Walton
Sent: Saturday, March 17, 2012 20:26
To: scala...@googlegroups.com
Subject: Re: [SIP 18] New SIP: Modularizing language features

 

If all one has to do is import something, then those that want to use those features will do so, those that don't, will not. How is that different from simply having all the features 'turned on' and letting people write the code they want to? You can't use those feature by accident! Or can you?

 

Ivan Porto Carrero

unread,
Mar 18, 2012, 5:23:54 AM3/18/12
to scala...@googlegroups.com
I had a much longer explanation and then I found this email from Dan.
I second all his arguments.

using opt-in won't make the complexity go away.  I learn a language by reading code from other people, who will still use those language features.  
if it's to support he enterprise and large teams the checkstyle solution is probably a superior one in terms of flexibility and extensibility.

The main problem of scala is documentation and education not so much having 2 versions of scala. it would be great if Josh could write another book that goes even more in depth , I'd gladly pay double for that. 

Francois Armand

unread,
Mar 18, 2012, 5:38:05 AM3/18/12
to scala...@googlegroups.com


I do liked your essay, and second most of it!

Thank you to have articulated what I was struggling to write for hours (the social/technology aspect, chaing several goals with one bullet, the importance of documentation and explanation...)

So thanks again !

Eugene Burmako

unread,
Mar 18, 2012, 5:39:53 AM3/18/12
to <scala-sips@googlegroups.com>
asInstanceOf is at times required for path-dependent stuff.

Sean Parsons

unread,
Mar 18, 2012, 6:29:44 AM3/18/12
to scala...@googlegroups.com
Very recently I've been doing some internal Scala training, so I'm quite sensitive to the complexity argument myself and if I had to add "You'll need to use this import statement, that isn't really an import statement, to use this feature." it would have zero benefit to those people learning Scala at all and would likely confuse people new to the language even more.

As a tool to allow stylistic choices to be made by groups or companies, options in individual files would have to be enforced by some external factor as it is. If this SIP is to provide guidance for a project, then why is it defined per file? How would anyone know without grepping the code base that I've turned on structural types in some .scala file deep within the code base? For an existing example of why such a feature is terrible one need only look at the Option Strict statement from Visual Basic .Net: http://msdn.microsoft.com/en-us/library/zcd4xwzs(v=vs.80).aspx I personally lost a day due to someone changing that setting in just one file in a large project, because it's almost action at a distance, especially for users that have their editors fold up imports.

While there are only 6 options currently, is there any guidance around what should and shouldn't be included in the future? If there are say 15 (which seems optimistically low) in 10 years that sounds like a combinatorial nightmare for the compiler, tools like IDEs and end users.

For library developers (and therefore the whole ecosystem) I can see a few problems and burdens that it creates:
1.) Libraries will have to work with as few features as possible to allow them to be as widely used as possible. This in turn creates complexity over whether or not a library needs to be split into parts and/or how the requirements are communicated. As a result the benefit of said features is minimised as the pressure is for them to be never used, creating a downward pressure spiral between the need and the use of a feature.
2.) Supporting all the new users that go "I tried your sample code and it didn't work." as a result of those features not being enabled.
3.) Testing that libraries work correctly with and without various features being enabled, just in case turning on feature X causes some unexpected result. This one is terrifying to me, having just recently written a JSON library, it would be onerous to add tests for some arbitrary combinations.

At the core of what I think about this, the answer to complexity is _never_ more complexity.

Thanks,
Sean.


On Saturday, 17 March 2012 19:48:40 UTC, Martin wrote:
Here's a new SIP which proposes to put some new and existing advanced
language features under an import flag. I expect we'll have an
interesting discussion about this one.
So, please, fire away!

Here's the link to the SIP:

https://docs.google.com/document/d/1nlkvpoIRkx7at1qJEZafJwthZ3GeIklTFhqmXMvTX9Q/edit

Cheers

 -- Martin


On Saturday, 17 March 2012 19:48:40 UTC, Martin wrote:
Here's a new SIP which proposes to put some new and existing advanced
language features under an import flag. I expect we'll have an
interesting discussion about this one.
So, please, fire away!

Here's the link to the SIP:

https://docs.google.com/document/d/1nlkvpoIRkx7at1qJEZafJwthZ3GeIklTFhqmXMvTX9Q/edit

Cheers

 -- Martin


Miles Sabin

unread,
Mar 18, 2012, 6:47:40 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 10:29 AM, Sean Parsons <seantp...@gmail.com> wrote:
> As a tool to allow stylistic choices to be made by groups or companies,
> options in individual files would have to be enforced by some external
> factor as it is. If this SIP is to provide guidance for a project, then why
> is it defined per file? How would anyone know without grepping the code base
> that I've turned on structural types in some .scala file deep within the
> code base?

Bang on ... even with the SIP-18 proposals in place you would _still_
need an additional external tool to verify that the expected
restrictions were in force.

Cheers,


Miles

--
Miles Sabin
tel: +44 7813 944 528
gtalk: mi...@milessabin.com
skype: milessabin
g+: http://www.milessabin.com
http://twitter.com/milessabin
http://underscoreconsulting.com
http://www.chuusai.com

martin odersky

unread,
Mar 18, 2012, 6:49:02 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 11:29 AM, Sean Parsons <seantp...@gmail.com> wrote:
> Very recently I've been doing some internal Scala training, so I'm quite
> sensitive to the complexity argument myself and if I had to add "You'll need
> to use this import statement, that isn't really an import statement, to use
> this feature." it would have zero benefit to those people learning Scala at
> all and would likely confuse people new to the language even more.
>
I disagree. There's precedent. These kinds of imports work very well
in Python. People don't have a problem with them.

> As a tool to allow stylistic choices to be made by groups or companies,
> options in individual files would have to be enforced by some external
> factor as it is. If this SIP is to provide guidance for a project, then why
> is it defined per file?

You can define it also globally per compiler option.

> How would anyone know without grepping the code base
> that I've turned on structural types in some .scala file deep within the
> code base?

I assume that code is at least cursorily reviewed. So an explicit
import will be noticed.

> For an existing example of why such a feature is terrible one
> need only look at the Option Strict statement from Visual Basic
> .Net: http://msdn.microsoft.com/en-us/library/zcd4xwzs(v=vs.80).aspx I
> personally lost a day due to someone changing that setting in just one file
> in a large project, because it's almost action at a distance, especially for
> users that have their editors fold up imports.
>

I agree that Open Strict is bad, because it changes the semantics of a
language. SIP 18 does not generally do that, it just gives warnings
which go away when you add an import. Or, almost. The structural types
inference would change the semantics and that is indeed something we
have to be careful about.

> While there are only 6 options currently, is there any guidance around what
> should and shouldn't be included in the future? If there are say 15 (which
> seems optimistically low) in 10 years that sounds like a combinatorial
> nightmare for the compiler, tools like IDEs and end users.
>

I would like to keep the options low. I do not see any combinatorial effects.

> For library developers (and therefore the whole ecosystem) I can see a few
> problems and burdens that it creates:
> 1.) Libraries will have to work with as few features as possible to allow
> them to be as widely used as possible. This in turn creates complexity over
> whether or not a library needs to be split into parts and/or how the
> requirements are communicated. As a result the benefit of said features is
> minimised as the pressure is for them to be never used, creating a downward
> pressure spiral between the need and the use of a feature.

And, if you ask me, that's a good thing! Type system surface is a cost
in maintainability and understandability, which is all too happily
ignored by some developers. I won't name names but I have seen several
large codebases that made me rip my hairs out for their needless
complexity. And yes, these tended to use the features I would like to
flag.

> 2.) Supporting all the new users that go "I tried your sample code and it
> didn't work." as a result of those features not being enabled.

An import statement belongs into documentation just like other imports
would. Besides, if the statement was missing, users would get a
warning or an error that explained to them that they have to turn the
import on. Nothing mysterious about it. Then when the import is on,
they can hyerlink on the imported flag to get more documentation about
the feature and its risks.

> 3.) Testing that libraries work correctly with and without various features
> being enabled, just in case turning on feature X causes some unexpected
> result. This one is terrifying to me, having just recently written a JSON
> library, it would be onerous to add tests for some arbitrary combinations.
>

That's a good point, in in light of that point I retract my proposal
to make type inference for structural types be controlled by a flag.
So absence of a flag would only warn about a feature, it would never
change behavior.

> At the core of what I think about this, the answer to complexity is _never_
> more complexity.
>

I think that's wrong. For instance, normal import statements add
complexity to a language, yet they avoid the complexity of a global
namespace that gets too large. In fact, I think in most evolved
systems we contain complexity with complexity. Take guards of
chainsaws as an example.

Cheers

- Martin

martin odersky

unread,
Mar 18, 2012, 7:14:44 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 4:49 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
>> I disagree. As long as a feature is specified in the SLS it is in the
>> language. The fact that it requires an explicit import does not change
>> that.
>
>
> Ok, I'll buy that.  It seems you're viewing the explicit import not as a
> pragma, but as a lexically scoped flag.  Still, horrifying to contemplate
> from a formal perspective, but not as horrifying as I initially thought.
>
> For the record, the overloading of import is still really problematic,
> precisely because overloading anything tends to introduce a lot of
> complexity and cognitive burden.  By definition, it requires one to
> consciously consider whether this construct refers to concept A or concept
> B.  The proposed "language import" is a very different concept from a
> library import and has very different effects.  Lumping it under the same
> syntactic construct seems…wrong, to put it mildly.

I think we disagree here. If we want to put it in the language (as
opposed to a lint or checkstyle tool), then we should control it with
real syntax, not with pragmas or switches (even though I'd allow
switches as an alternative). And import will work very well for that,
I am convinced.


>
>> I do not see why not.
>
>
> Weren't you the one telling me that the typer is already too complex?  ;-)
>

Yes, because of existentials and higher-kinded types and lubs. This is
trivial by comparison. :-)

Cheers

- Martin

martin odersky

unread,
Mar 18, 2012, 7:29:49 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 4:31 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
>
>> How is requiring an explicit import the same as disabling a feature?
>
>
> The explicit import isn't an import at all, but a compiler pragma in the
> syntactic guise of an unrelated language feature.  As with any compiler
> pragma, the net effect is to change the behavior of the compiler, and thus,
> the language.
>
As responded to other mails, I agree we have to be careful not to
change the behavior of the language, except for requiring the flag.
I believe explicit imports will work pragmatically much better than
the alternatives. Python has shown this.


> If a feature is disabled by default, then it is not in the language (by
> definition).  This is why Haskell discussions separate "Haskell" from
> "Haskell with GHC extensions".
>
>> I don't like explicit disabling. It violates the principle that simple
>> things should be kept simple. And it complicates the machinery
>> considerably. Now you'd have to explain how to resolve an enabling
>> import that clashes with a disabling flag. I don't want to get into
>> that!
>
>
> I would remove the import mechanism entirely.  Pragma was evil back in the
> days of C.  Introducing it to Scala, especially when disguised as an
> orthogonal feature, is just begging for pain (like the pain of
> disambiguating compiler switches vs imports).
>
> I think the compiler switch is still keeping things simple.  In fact, I
> think it keeps things simpler than the import mechanism, which introduces a
> very weird and non-orthogonal feature into the core language semantics.  A
> compiler switch enables teams to make and control decisions about these
> features at a high level.  It's much easier to police your build.sbt than it
> is to police an entire codebase, grepping for a construct that uses the same
> syntax as another (very commonly-used) one.  Additionally, compiler switches
> are generally understood to affect the semantics of the compiler.  That is,
> after all, their purpose.  Thus, they fit precisely within the template
> concept that already exists.  Using compiler switches doesn't introduce any
> complexity, but using an "import" does.
>
> How does the explicit "import" interact with scoping?  Can we have certain
> typer features activated for part of our file but not another part?  What if
> higher kinds are enabled inside a method but not outside?  What error do we
> get if features "leak" through type inference?  There's just a whole host of
> questions that arise when you start introducing language features – you must
> know this better than I!  Compiler switches are the simpler mechanism, by
> far.
>
The SIP is explicit about this: Higher kinded types: only explicit
definitions are affected. Existential types: inferred types are also
affected.

-- Martin

Paul Phillips

unread,
Mar 18, 2012, 7:33:12 AM3/18/12
to scala...@googlegroups.com


On Saturday, March 17, 2012, Erik Osheim wrote:
From my point of view, this seems like something that could be
addressed with finer-grained control over generating warnings, as well
as options to turn warnings into errors.

Seems like a good time to point out some things which already exist, such as "-Xfatal-warnings". (Not that it couldn't be more granular.) I always intended to move this stuff into a mostly separate component, controllable by config file.

% scalac -Y |& grep warn
  -Ywarn-adapted-args                 Warn if an argument list is modified to match the receiver.
  -Ywarn-all                          Enable all -Y warnings.
  -Ywarn-dead-code                    Warn when dead code is identified.
  -Ywarn-inaccessible                 Warn about inaccessible types in method signatures.
  -Ywarn-nullary-override             Warn when non-nullary overrides nullary, e.g. `def foo()` over `def foo`.
  -Ywarn-nullary-unit                 Warn when nullary methods return Unit.
  -Ywarn-numeric-widen                Warn when numerics are widened.
  -Ywarn-value-discard                Warn when non-Unit expression results are unused.
 
 % scalac -X |& grep warn
  -Xfatal-warnings               Fail the compilation if there are any warnings.
  -Xlint                         Enable recommended additional warnings.
 

martin odersky

unread,
Mar 18, 2012, 7:45:53 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 5:56 AM, RYAN RICHT <ryan_...@me.com> wrote:
> As someone alluded to, this would indeed substantially complicate adoption and usage at large firms, like Monsanto (views are my own, not Monsanto's).
>
> Our project, the first Scala project here, has now internally gained substantial support. We make use of all of these proposed "modularized" features, and certainly don't need the stigma of them being "dangerous," "difficult to maintain," "too complicated," "too slow," "impossible to hire for," or anything else.

Frankly, if you do indeed use all of these features, that would be a
red flag for me. You'd have to convince me about the long-term
maintainability of your project. An explicit import is a good nail on
which to hang the argument for the inclusion of a feature.

> The stigma associated with using Scala at a large, traditionally Java firm is sufficiently burdensome without this SIP. Please don't frustrate adoption further by implementing this SIP. This isn't helping by making Scala simpler, it is making it scarier to use the very features that make Scala high value (+1 on all Daniel Spiewak's comments).
>
> Given the volume of highly negative feedback on this SIP, and years of complaining about more pressing (and high profile) issues like performance optimization of loops, is this *really* the most important SIP to pursue right now given limited resources?
>

Don't worry. Loops will be optimized in 2.10.

Cheers

- Martin

Sébastien Bocq

unread,
Mar 18, 2012, 7:52:33 AM3/18/12
to scala...@googlegroups.com
Le 18 mars 2012 03:14, martin odersky <martin....@epfl.ch> a écrit :
> On Sat, Mar 17, 2012 at 11:56 PM, Daniel Spiewak <djsp...@gmail.com> wrote:
>> Color me horrified.
>>
>> Ok, maybe that was too strong.  Honestly, I don't see anything positive
>> coming out of a change like this.  As Rex pointed out, it just creates
>> import/build-config boilerplate for, well, everyone.  Even for the few who
>> don't use these features (knowingly or unknowingly), these switches have no
>> beneficial effect.  You are hiding a language feature that these people
>> haven't seen.  By definition, this will be a completely invisible change for
>> a few people and a significantly detrimental change for a majority.
>>
> I believe my development experience is different than yours then. In
> codebases I contribute to, these features are very rarely used. To a
> point, where I would welcome a warning if they are indeed used. So I
> believe it will be an invisible change for the majority, a welcome
> change for most people on the borderline, and a small nuisance for a
> few.
>

My experience match yours. I think the SIP will make the language more
friendly for newcomers and motivate advanced programmers not to overly
use language features where they are not strictly needed.

I'd emit a reservation on restricting the explicit usage of
higher-kinded types because they are to me a core feature of the
language and using them teaches you a lot. if you do it wrong, if you
don't understand what you're doing or if you try to abuse them, your
code will become quickly too complex or difficult to compile. So, I
don't see the necessity to disable them by default. If it is to hide
that they sometime pushes type inference to its limit, then it is for
the wrong reason. And by the time you reach that point you probably
have already a good understanding of what you're doing anyway.

One other small note. The SIP says: "Features that existed in Scala
2.9 and that are now controlled by a feature flag will trigger a
warning when they are used where the flag is not imported. In a future
major Scala version that warning might be turned into an error.". Why
limit this to features of Scala 2.9 only? I would make this a
requirement for any feature flag. Without this, newcomers might not
even know that what they want is possible and that there is actually a
name for it. I'm speaking out of personal experience with pragmas in
Haskell ... it doesn't help with the learning curve.

--
Sébastien

martin odersky

unread,
Mar 18, 2012, 8:00:51 AM3/18/12
to scala...@googlegroups.com
I am open to errors vs warnings. But note that even errors should
clearly state the remedy, that you can make the error go away by
importing such and such feature.

-- Martin

Stuart Roebuck

unread,
Mar 18, 2012, 8:21:28 AM3/18/12
to scala...@googlegroups.com
In the course of reading the SIP and these comments I've gone through a full circle of view on this.

My first though was that this was much preferable to the use of compiler flags as the only way to enable some of the newer features which have, up to now, been talked of as being optional in some way: e.g. macros, dynamic.  The disassociation of code from the settings required to make it compile is unhelpful, in my view.  There is nothing worse than trying to compile someone else's code built with one build system, in another build system and not having a clue why it isn't working.

However, the argument that this requires lots of extra 'boilerplate' in existing code just to make it work felt like a key point. Requiring the dev community to retrofit this into hundreds of source files just to make valid code work seems like a bad move.  Also the idea that you all those examples of short Scala code vs. long Java code would go the other way because of a pile of necessary includes at the top is not appealing either.

But bear with me…

Certainly looking at my own code bases, it is true that I would not require these imports on most files.  So the import tax would be low except for some of my more complex libraries and even there it would take half an hour max to fix this over 50 files.

I would be very concerned if these flags changed compilation other than issuing errors, but Martin has clarified that one - this is about issuing compiler warnings / errors if features are used without the associated feature flags imported into scope.  So anyone trying a feature and not understanding the need for the import could be presented with a compiler warning/error that indicates precisely what needs to be done and what feature is the issue.

Now this last point strikes me as a huge win.  Currently it is very easy for a relatively new Scala developer to start to use (perhaps with consequent difficulty) postfixOps, structuralTypes, higherKinded types and existential types by copying and pasting code from elsewhere.  In so doing they can be happily unaware that they are using these features because, for those new to Scala the syntax of these features is necessarily complex.  But up until this SIP it would have been very difficult for such a developer to actually look up and learn about the feature because they wouldn't know what it was actually called, what its implications where, etc., etc..  With this proposal we provide a feedback loop where developers are able to recognise their use of these language features, and able to understand what those features are called so that they can at least choose to learn about their use before falling foul to some negative side of the power they provide.

So, on balance I think thing the import tax is low and the benefit is high.

I also think that providing a checkstyle plugin for sbt that is bundled by default (with low noise settings) would be really helpful as part of this mix moving forward.  It would also be really good to have a few beginning Scala books / docs that exclusively cover Scala without these imports so that there is a little less temptation for new developers to buy into the latest greatest power tools before they've passed their safety at work course!

Stuart.

PS. What about a feature flag for 'continuations' and how about issuing errors for all features that weren't present by default in 2.9: macros, dynamic and continuations?

Sciss

unread,
Mar 18, 2012, 8:35:00 AM3/18/12
to scala...@googlegroups.com
I read the SIP 18, here is my opinion...

I am strongly opposed to this SIP. While its motivation is to make Scala 'less complex', it achieves quite the opposite. It re-uses an existing keyword, `import`, and "overloads" it with new meaning. It doesn't even adhere to the "normal" behaviour of `import`: "Wildcard imports from language have no effect".

The SIP complicates the language by toggling the addition or removal of keywords from the language. And this on a per file basis. It kind of states itself what it should be: "The values ... are called feature flags" -- so, there is a well defined mechanism for that, which is compiler flags.

I rarely use a specific language feature just in a single source code file, so the need to put an import statement into each and every file arises, whereas it would be transparent as a compiler flag. I don't see much difference between enabling or disabling macros, and doing the same with continuations.

The selection of features is highly heterogeneous. Higher kinded types are an essential feature of a functional programming language, switching it off doesn't make any sense. I am curious why it appears in the list, while implicits do not appear in it. They are also an essential feature of the language, providing the type class analogy in Scala. Disabling the _creation_ of higher kinded types doesn't make any sense, as you will still be using them as soon as you write `List( 1, 2, 3 )`. So while intending to make things less complex, you create a confusion by trying to hide a feature while it still is there.

I don't think there are many serious libraries out there which make no use of implicits and higher kinded types. This is after all why we use Scala and not Java. Hiding those features under an import tax is just a form of castration.

The list is heterogeneous for another reason: Most features described are _explicit_ features, you don't accidentally write a macro or mixin the Dynamic trait. You don't accidentally define a higher kinded function. On the other hand, there is one case which indeed _does_ occur accidentally, and that is structural typing. The example you give:

val v = new Object { val member = 1 }

I think most people have run into this by mistake. But then again, to hide that under an import is making it just more difficult to read -- you would need to look up the source code to see whether a particular declaration is meant as a structural type or not. Another thing is that you are creating a language construct to hide something which has to do with behind-the-scenes performance issues, which may well change in the future -- there may well be a point where using a structural type is not a penalty at all. A language statement should correspond to meaning and not implementation or hardware details.

There are two well known better solutions to protect from accidentally writing structural types:

(1) Rely on the IDE highlighting -- this is a non intrusive form, and I use it quite a bit. I don't know the Eclipse plug-in that well, but the Scala plug-in for IDEA has a powerful set of warning highlights which address typical problems. So it would be really easy to add a warning highlight against accidental usage of structural typing.

(2) Just as you have `@tailrec` as a means to check positively for tail recursion, or `@switch` to make sure a match is optimised, you could have a "negative" or "overriding" annotation (so, more like `@unchecked`!) to say that you _do_ want a structural type. You would have something like

val v: @structural = new Object { val member = 1 }

This is the only place where `@structural` would be needed, because it is the only place where you can have structural types by accident. Consider `def test( abortable: { def abort(): Unit })` instead -- there is no way that the type was introduced accidentally, thus no need for `@structural`.

A statement like the above without `@structural` would produce a compiler warning or error.

And lastly, for the postfix syntax. I use it rarely, so I cannot really comment on it. But disabling it by default means that every user of a particular DSL needs to import a language feature to use the DSL. Doesn't make much sense to me, either.

Summary: Please keep things simple. This SIP doesn't make things any simpler, it just adds more verbosity, patronises the user and nowhere contributes to the goal of making Scala more accessible by Java people.

Best, .h.h.

martin odersky

unread,
Mar 18, 2012, 9:01:09 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 1:35 PM, Sciss <con...@sciss.de> wrote:
> I read the SIP 18, here is my opinion...
>
> I am strongly opposed to this SIP. While its motivation is to make Scala 'less complex', it achieves quite the opposite. It re-uses an existing keyword, `import`, and "overloads" it with new meaning. It doesn't even adhere to the "normal" behaviour of `import`: "Wildcard imports from language have no effect".
>
I think we can spec it so that it makes sense. There is already the
concept of a named import in the spec. So we'd need to say:
Feature X is enabled if the member X of the scala.language object is
available in scope via a named import. That's pretty easy.

> The SIP complicates the language by toggling the addition or removal of keywords from the language. And this on a per file basis. It kind of states itself what it should be: "The values ... are called feature flags" -- so, there is a well defined mechanism for that, which is compiler flags.

Technically, keywords would remain keywords independently of flags.
The only exception is macro, and that only for a transitory period of
one major release. We can't claim macro as un unconditional keyword
right now because code might break. In fact, it was the idea of the
import syntax that convinced me in the end that the proposal might
fly. I think it would be much more problematic if it relied on flags
only because then you guide what's a language rule by an
extra-language feature.

>
> I rarely use a specific language feature just in a single source code file, so the need to put an import statement into each and every file arises, whereas it would be transparent as a compiler flag. I don't see much difference between enabling or disabling macros, and doing the same with continuations.

The current proposal would let you write compiler flags as an alternative.


>
> The selection of features is highly heterogeneous. Higher kinded types are an essential feature of a functional programming language, switching it off doesn't make any sense. I am curious why it appears in the list, while implicits do not appear in it. They are also an essential feature of the language, providing the type class analogy in Scala. Disabling the _creation_ of higher kinded types doesn't make any sense, as you will still be using them as soon as you write `List( 1, 2, 3 )`. So while intending to make things less complex, you create a confusion by trying to hide a feature while it still is there.
>

Not at all. I think we all agree that List(1, 2, 3) is perfectly fine.
It required some serious engineering in the factories to make it
happen. After all that work, I would not mind at all by showing the
secret source of that engineering with an

import language.higherKinded

in the few files that actually define higher-kinded types in the
library. But using these higher-kinded types should be a conscious
decision which should be documented IMO. The SIP gives other reasons
as well.

> I don't think there are many serious libraries out there which make no use of implicits and higher kinded types. This is after all why we use Scala and not Java. Hiding those features under an import tax is just a form of castration.
>

I think that's put a bit too strongly. All that's required is be
explicit about it. Nothing is taken away.

-- Martin

Jorge Ortiz

unread,
Mar 18, 2012, 9:44:08 AM3/18/12
to scala...@googlegroups.com
First of all: this is a tempest in a teacup. The cries of pain from "expert" Scala users that they are being unduly punished ring hollow. Presumably, expert users of Scala are competent users of their build system and can trivially add compiler flags to their heart's content.

Second: people claiming that structural types and existential types can only be used deliberately are mistaken.

It's quite easy for structural types to creep into a public API unintentionally, via type inference. This has happened several times in the standard library. For examples, see SI-879 (https://issues.scala-lang.org/browse/SI-879) and SI-4791 (https://issues.scala-lang.org/browse/SI-4791). In fact, I'd go so far as to say that even if someone explicitly chose to use structural types in a file or project, having a type be inferred as structural would almost always be undesirable.

Likewise, types inferred as existential types are almost never what you want. While debugging foursquare's compilation times recently, I discovered the compiler was inferring a particularly nasty LUB as a very complicated existential type. To give you an idea of the magnitude of the problem, the textual representation of the inferred type was 225kb. Yes, kilobytes. To be fair to the compiler, the inheritance hierarchy involved is incredibly nasty, and the situation did call for a LUB. And to be fair to existential types, it was really all the LUB's fault. However, warning on inferred existential types would have given us a clue that the LUB was going haywire. Though, again, even if I explicitly chose to use existentials here, even then I would almost never want them inferred.

* * *

That said, I do have some concerns about the proposal as it stands.

a) Will warnings/errors be emitted for these features at use-site or at definition-site? In the current state of the world, Dynamic needs -Xexperimental in both places. This makes sense, as the potential unsafety occurs at use-site. I'm not sure about macros, but I would hope the same is true. Emitting warnings/errors only at definition-site would 

b) I welcome a more principled approach to enabling features that will inevitably live behind flags (macros, dynamic, CPS). However, the "import" syntax strikes me as a mistake. I like that it gives features very Googleable names (try searching for "_ <: T" or "T { def foo: Bar }"), but the new meaning of import is too disimilar from what import already means. I know its inspired by Python, but I think Python imports are sufficiently different from Scala imports (they're more about adding an entire library/feature than bringing specific identifiers into scope) that it doesn't make much sense. If language syntax must be used, the only alternative I can come up with is package declarations extending marker traits (e.g., "package foo extends language.dynamic"), but that's also not very satisfying (and sucks if you're not in a package... "package _root_"?).

c) While some of the features proposed to be put behind flags/imports are truly dangerous or experimental enough that they should be opted into, others are "advanced" features but fairly innocuous. As far as I know, higher-kinded types never hurt anyone.

In general, I feel this is better done as a compiler plugin or a style checker than as something baked into the language, at least for now. First, such a tool is needed anyway, regardless of whether this SIP is implemented or not. This SIP doesn't (and can't!) cover things that are truly dangerous (as others have pointed out: any2stringadd, primitive widening, auto-tupling, etc). The only way for those so inclined to eradicate these constructs from their code is via a configurable style checker. Second, people's opinions will naturally vary on which features they consider "dangerous" or "advanced" and which they consider mundane. Giving them the option of turning warnings or errors on or off for particular features will allow for flexibility, and will let a set of "best practices" to arise from the community. I appreciate Scala's willingness to remove features considered dangerous (many of the places where Scala improves over Java are known problems in Java, but they can't be fixed because doing so would break backwards compatibility), but I think such changes at the language-level should only happen once they have been validated as "best practices" by the community. The proposed SIP seems at once to both go too far (no one has gripes with higher-kinded types) and not far enough (many have gripes with any2stringadd).

Foursquare started a compiler plugin to try to address some of the issues that were haunting us. I've open sourced the publicly interesting bits here: https://github.com/foursquare/linter. The project is in a nascent stage, but I hope it will grow to include many more warnings and to be configurable by its users. I've also recently discovered that Matthew Farwell has a similar project here: https://github.com/scalastyle/scalastyle.

In summary: Things currently behind flags (dynamic, macros, CPS) should be kept behind flags (hopefully standardized) or behind new language syntax. Further restrictions should be implemented with a configurable tool first. Once "best practices" emerge in the community, their restriction at the language level can be proposed.

--j

Paul Phillips

unread,
Mar 18, 2012, 10:02:14 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 6:44 AM, Jorge Ortiz <jorge...@gmail.com> wrote:
> having a type be inferred as structural would almost always be undesirable.
>
> Likewise, types inferred as existential types are almost never what you
> want.

As someone who has experimented heavily with modifications to type
inference, I have to say you are wrong on both counts. There is
nothing quite so edifying as implementing a change to what is inferred
and then seeing where the compiler fails to compile itself. And
that's on a single source base which makes no effort to exercise every
bit of the dance floor. Just because you do not intentionally expose
existentials as principal types, that doesn't mean you don't depend on
their being inferred in intermediate expressions.

> To give you an idea of the magnitude of the problem, the
> textual representation of the inferred type was 225kb. Yes, kilobytes.

I just sent a 285 kb inferred type out which no amount of warning
about existentials could have prevented.

http://permalink.gmane.org/gmane.comp.lang.scala/25959

ARKBAN

unread,
Mar 18, 2012, 10:08:45 AM3/18/12
to scala...@googlegroups.com
I've been struggling to take a side in the debate about whether reusing
the word "import" was good or bad, so I decided to see if translating
the discussion from English to Scala might help me:

What we have today:

/** Mimics the work of the "import" statement */
class Importer {
def import( path:Seq[String] ) {
if ( isFullQualifiedPath( path ) ) addAllClasses( path )
else addSingleClass( path )
}
}

def doImports( importer: Importer ) {
importer.import( Seq( "scala", "collections", "immutable" ) )
importer.import( Seq( "scala", "collections", "mutable", "HashSet" ) )
}

doImports( new Importer )

What SIP-18 is proposing

/** Mimics the work of the "import" statement */
trait Importer {
def import( path:Seq[String] )
}

/** Same as previous implementation of Importer */
trait ClassImporter {
def import( path:Seq[String] ) {
if ( isFullQualifiedPath( path ) ) addAllClasses( path )
else addSingleClass( path )
}
}

trait LanguageImporter {
def import( path:Seq[String] ) {
if ( isFullQualifiedPath( path ) ) throw new
IllegalArgumentException("wildcards disallowed by SIP")
else addSingleLanguageFeature( path )
}
}

def doImports( importer: Importer ) {
importer.import( Seq( "scala", "collections", "immutable" ) ) //
fails for LanguageImporter
importer.import( Seq( "scala", "collections", "mutable", "HashSet" )
) // fails for LanguageImporter
importer.import( Seq( "language", "macros" ) ) // fails for
ClassImporter AND LanguageImporter (SIP disallows wildcards)
importer.import( Seq( "language" ) ) // fails for ClassImporter
}

doImports( new ClassImporter )
doImports( new LanguageImporter )

(My translation is not perfect and its surely not the code that exists
in the compiler; creating production-ready code was not the intent of
this exercise for me.)

The new design has two different Importer implementations that are
incompatible. If someone saw this in code they would say that the
implementations and the design violates the Liskov substitution
principle. The LanguageImporter specifically violates the rule about
strengthening preconditions -- wildcards are disallowed by the SIP.

For me this exercise made it clear to me that reusing "import" for class
importing and language features is confusing. I hope this exercise is
useful to others (perhaps I've got it all backward and someone else's
code will show that side).

ARKBAN

P.S.: I imagine those authoring IDE plugins are also going to struggle
with two different behaviors for the same keyword depending on the context.

martin odersky

unread,
Mar 18, 2012, 10:12:33 AM3/18/12
to scala...@googlegroups.com
Please read the spec carefully. Wildcard imports are not disallowed. I
have now added the precise formulation that's needed to the SIP. It
does not touch on the semantics of imports at all; there are no two
kinds of import statements.

Cheers

- Martin

martin odersky

unread,
Mar 18, 2012, 10:15:40 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 3:02 PM, Paul Phillips <pa...@improving.org> wrote:
> On Sun, Mar 18, 2012 at 6:44 AM, Jorge Ortiz <jorge...@gmail.com> wrote:
>> having a type be inferred as structural would almost always be undesirable.
>>
>> Likewise, types inferred as existential types are almost never what you
>> want.
>
> As someone who has experimented heavily with modifications to type
> inference, I have to say you are wrong on both counts.  There is
> nothing quite so edifying as implementing a change to what is inferred
> and then seeing where the compiler fails to compile itself.  And
> that's on a single source base which makes no effort to exercise every
> bit of the dance floor.  Just because you do not intentionally expose
> existentials as principal types, that doesn't mean you don't depend on
> their being inferred in intermediate expressions.
>
Do you have some examples of that? Would be good to see them.

>> To give you an idea of the magnitude of the problem, the
>> textual representation of the inferred type was 225kb. Yes, kilobytes.
>
> I just sent a 285 kb inferred type out which no amount of warning
> about existentials could have prevented.
>
>  http://permalink.gmane.org/gmane.comp.lang.scala/25959

I believe we can get rid altogether of those monstrosities in the
future IF we start curtailing existential types now.

Cheers

-- Martin

ARKBAN

unread,
Mar 18, 2012, 10:29:10 AM3/18/12
to scala...@googlegroups.com
I stand corrected, they "have no effect" per the SIP.


It
does not touch on the semantics of imports at all; there are no two
kinds of import statements.
While I agree that technically it does not change the syntax of import -- you are importing a value of the object "language" -- the semantics of that import is drastically different. (If they weren't different then there wouldn't be an SIP.) There is a side-effect to importing from language as opposed to importing from, say, scala.collections.mutable.HashSet.

Cheers

 - Martin

martin odersky

unread,
Mar 18, 2012, 10:32:16 AM3/18/12
to scala...@googlegroups.com

lt's something else. The semantics of the import is not changed at
all, and there is no side effect. The _visibility of certain imported
identifiers_ then drives features. A feature flag is a proxy for the
availability of that feature. Honestly, I fail to see how it could get
any clearer than this.

- Martin

Paul Phillips

unread,
Mar 18, 2012, 10:52:49 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 7:15 AM, martin odersky <martin....@epfl.ch> wrote:
> Do you have some examples of that? Would be good to see them.

If we don't infer refinements, we turn type members into even
second-classier citizens. See appended. Also, constructs like this
one - which can be very handy, reflection be damned - would cease to
function entirely:

scala> implicit def imbueWithPowers(xs: List[Int]) = new { def bippy =
"I'm bippy!" }
imbueWithPowers: (xs: List[Int])Object{def bippy: String}

scala> Nil.bippy
res2: String = I'm bippy!

When it comes to existentials, I have seen it many times but I don't
have any prefab examples. The pattern matcher is often a major
participant, but not always. The usual manifestation of failure is
something failing to typecheck which used to, due to it no longer
conforming to bounds, because the evidence that it did conform to
bounds was being propagated by one of the less obvious mechanisms,
which was impacted in some subtle way by whatever innocuous-seeming
change I was investigating.

As a general rule, I have noticed that people quite freely take
advantage of very delicate arrangements in the type system - because
they don't know that they're doing so, of course. If something works,
it works! I feel the same way. But it means that in most cases people
don't even know what it is that they depend on, so the degree to which
they can articulate their needs is limited.

And I'm all for making these things more transparent, as I always have
been; I simply want to do that without taxing the most dedicated
users.


// type parameters vs. type members
class X1 ; class X2 extends X1 ; class X3 extends X2

trait A {
type T
def f: T
}
class A1 extends A {
type T = X2
def f = new X2
}
class A2 extends A {
type T = X3
def f = new X3
}

trait B[T] { def f: T }
class B1 extends B[X2] { def f = new X2 }
class B2 extends B[X3] { def f = new X3 }

object Test {
// List[A{def f: X2; type T >: X3 <: X2}]
def f1 = List(new A1, new A2)
// List[B[_ >: X3 <: X2]]
def g1 = List(new B1, new B2)
}

ARKBAN

unread,
Mar 18, 2012, 11:05:30 AM3/18/12
to scala...@googlegroups.com

From a pure language perspective I see now that there is no
side-effect. From a developer experince there is a behavior change,
call it either a direct-effect or side-effect or whatever. That is my
concern with reusing the word "import", I can't think of anyway to
explain it to others except for "but when you import from language..."

Honestly, I fail to see how it could get
any clearer than this.

I'm sorry that I am causing frustration for you. I'm really not trying
to be difficult. I'm trying to understand the distinction so that when I
lead the transition at my company to Scala 2.10 (or which ever version
contains this SIP), I can explain to my co-workers so they understand.
If I screw up and explain the concept poorly I leave many people with a
poorer impression of Scala, and that's not something I want to do.
>
> - Martin
I hope I've made it clear that I think a different keyword should be
used. That was all I was aiming for. I was hoping the Scala code
translation exercise would help with that but I don't think it did, we
seemed to get bogged down in a discussion about the technical nuances.

ARKBAN

Sciss

unread,
Mar 18, 2012, 11:07:16 AM3/18/12
to scala...@googlegroups.com
but I wonder if this is really a few files? when i just superficially glance over all the different libraries i wrote, i think hk appear in around 90% of all files.

so what do you anticipate that happens in a developer's brain -- do you really think they ask themselves: "Oh, wait a second. Higher kinded types are an advanced language feature. Lets evaluate, if they are really necessary here, and it justifies me adding import.higherKindedTypes" --- seriously. I think you make a decision on what the purpose of a library or class is, and that determines whether you need HK or not. I don't think anyone needs the extra 'reminder'.

Erik Osheim

unread,
Mar 18, 2012, 11:14:35 AM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 08:44:08PM +0700, Jorge Ortiz wrote:
> First of all: this is a tempest in a teacup. The cries of pain from
> "expert" Scala users that they are being unduly punished ring hollow.
> Presumably, expert users of Scala are competent users of their build system
> and can trivially add compiler flags to their heart's content.

I largely agree with your email, but this is not a totally correct
characterization.

It seems like we're not talking about compiler flags but adding import
statements, right? Editing build.sbt (or whatever) once is a lot
different than possibly having to add imports to N files. If we're
talking about more fine-grained warning/error options for scalac then
it's a different kettle of fish.

Quibbles aside, your observation that linter is the place to try to
address these issues is a good one.

-- Erik

Sciss

unread,
Mar 18, 2012, 11:31:39 AM3/18/12
to scala...@googlegroups.com
Another thought on SIP-18

Which are the things that make Scala more complex? I very much doubt that the SIP actually comes near its proclaimed target.

Example 1: Higher-kinded types (for me) are much simpler than type members and path dependent types. I struggle a lot with the latter when designing a library.

Example 2: Controlling side-effects is much more difficult that implicits. These are the real 'implicit' problems. Addressing the latter instead of the former just shows that the SIP is motivated by pressure from Java adopters which do not care about side effect and thus don't see it as complexity, while it actually is.

Example 3: Symbols in method names ( |@|, <<, >>=, <*>, ... ). The sbt, scalaz, and lift phenomen. More difficult to understand than postfix syntax.

...

So to make the language simpler, in my opinion, other things need to be addressed. If you manage to make the developer think about how side effects occur and are handled, much more is achieved than making them get annoyed and developing a reflex of adding `import language.{higherKinded, implicitConversions, allowSymbolicMethodNames}` at the top of each new file they create. (i'm going to have that in my IDEA new-file-template i guess).


Seth Tisue

unread,
Mar 18, 2012, 12:23:37 PM3/18/12
to scala...@googlegroups.com
On Sat, Mar 17, 2012 at 11:00 PM, Daniel Spiewak <djsp...@gmail.com> wrote:
> Experienced Scala developers will simply turn everything on.

Nonsense. I am an experienced Scala developer. And like Martin, I
would rarely enable even one of these features, let alone all of them.

--
Seth Tisue | Northwestern University | http://tisue.net
lead developer, NetLogo: http://ccl.northwestern.edu/netlogo/

Daniel Spiewak

unread,
Mar 18, 2012, 12:25:31 PM3/18/12
to scala...@googlegroups.com
> For the record, the overloading of import is still really problematic,
> precisely because overloading anything tends to introduce a lot of
> complexity and cognitive burden.  By definition, it requires one to
> consciously consider whether this construct refers to concept A or concept
> B.  The proposed "language import" is a very different concept from a
> library import and has very different effects.  Lumping it under the same
> syntactic construct seems…wrong, to put it mildly.

I think we disagree here. If we want to put it in the language (as
opposed to a lint or checkstyle tool), then we should control it with
real syntax, not with pragmas or switches (even though I'd allow
switches as an alternative). And import will work very well for that,
I am convinced.

The overloaded import is a pragma, it's just disguised as something else.  Worse, the thing it's disguised as has very different semantics from the thing it is.  So, the mental box into which imports are slotted has to take on another dimension of wrinkles.  A few people have already pointed out that the analogy to Python's import from Future isn't really accurate, since Python imports already have very different semantics from Scala's, semantics more in line with the sort of behavior import from Future provides.

If we must have syntax for this (a conclusion I still strongly disagree with), it should be something that reflects the uniqueness of the construct.  In other words, we shouldn't overload something that's already in the language.  Nothing in the language behaves anything like what you're proposing, therefore new syntax is required if syntax is to be employed.
 
Daniel

Daniel Spiewak

unread,
Mar 18, 2012, 12:30:13 PM3/18/12
to scala...@googlegroups.com
Frankly, if you do indeed use all of these features, that would be a
red flag for me. You'd have to convince me about the long-term
maintainability of your project. An explicit import is a good nail on
which to hang the argument for the inclusion of a feature.

The Precog codebase uses all of the features you propose to flag (except for dynamic and macros).  We're pretty dependent on them, as a matter of fact.  The Novel Vibe code base (may it reset in peace) used type constructor polymorphism and existentials (no structural types).  The gll-combinators codebase uses type constructor polymorphism and existentials, as does the anti-xml code base.  Maybe I just carry complexity with me; I don't know, but code that I work on always seems to leverage these features, and always for good reasons.

Daniel

Daniel Spiewak

unread,
Mar 18, 2012, 12:35:40 PM3/18/12
to scala...@googlegroups.com
Which are the things that make Scala more complex? I very much doubt that the SIP actually comes near its proclaimed target.

As far as I can tell, the point of this SIP is not to address the "Scala is too complex" meme.  Early posts in the conversation assumed that it was and soundly trounced its effectiveness in that direction.  This SIP seems more about explicitly controlling the use of more advanced and (arguably) less fundamental features in the language.

Daniel

martin odersky

unread,
Mar 18, 2012, 12:41:01 PM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 5:25 PM, Daniel Spiewak <djsp...@gmail.com> wrote:
>
>> > For the record, the overloading of import is still really problematic,
>> > precisely because overloading anything tends to introduce a lot of
>> > complexity and cognitive burden.  By definition, it requires one to
>> > consciously consider whether this construct refers to concept A or
>> > concept
>> > B.  The proposed "language import" is a very different concept from a
>> > library import and has very different effects.  Lumping it under the
>> > same
>> > syntactic construct seems…wrong, to put it mildly.
>>
>> I think we disagree here. If we want to put it in the language (as
>> opposed to a lint or checkstyle tool), then we should control it with
>> real syntax, not with pragmas or switches (even though I'd allow
>> switches as an alternative). And import will work very well for that,
>> I am convinced.
>
>
> The overloaded import is a pragma, it's just disguised as something else.
> Worse, the thing it's disguised as has very different semantics from the
> thing it is.  So, the mental box into which imports are slotted has to take
> on another dimension of wrinkles.  A few people have already pointed out
> that the analogy to Python's import from Future isn't really accurate, since
> Python imports already have very different semantics from Scala's, semantics
> more in line with the sort of behavior import from Future provides.
>
Another analogy which is maybe closer is Modula-2's use of import to
access low-level system-oriented features. At the time everybody
really liked that. So, I still think import is the right way to
express this. The beauty of import is also that you can scope it
anyway you like. For instance, say you want to admit 3 reflexive calls
in a method but would otherwise like to be warned about
them. You can write:

def foo(x: { def a(); def b(); def c() }) {
import language.reflect
x.a()
x.b()
x.c()
}

I find that very elegant!

- Martin

Sciss

unread,
Mar 18, 2012, 12:49:49 PM3/18/12
to scala...@googlegroups.com
but you have to have a motivation for "controlling the use of more advanced ... features". control always has a goal -- which would that be other than tackle "complexity" by proposing some sort of hygiene that basically says "higher kinded types are advanced, and do you really want to get your hands dirty?"

the SIP says it wants to make the use of these features "more explicit" -- but how is

import language.higherKindedTypes

trait MyStructure[ A ]

more explicit than

trait MyStructure[ A ]

? more verbose, yes, but not more explicit.

best, -h.h.-

Rex Kerr

unread,
Mar 18, 2012, 1:09:54 PM3/18/12
to scala...@googlegroups.com
On Sun, Mar 18, 2012 at 12:41 PM, martin odersky <martin....@epfl.ch> wrote:
For instance, say you want to admit 3 reflexive calls
in a method but would otherwise like to be warned about
them. You can write:

 def foo(x: { def a(); def b(); def c() }) {
   import language.reflect
   x.a()
   x.b()
   x.c()
 }

I find that very elegant!

I find that bizarre.  First, the structural type appears _before the import_.  So either it's a backwards reference, or people have to explicitly import a second feature to make the only possible valid use of the first (imported) feature, doubling the boilerplate needed for no reason.

Second, isn't this what annotations are often used for?  Now we have two entirely different sets of annotations--ones with @whatever and ones with import language.whatever.  It is almost as if you are proposing a certain type of implicit annotation, except it's not called an annotation (or an implicit) and uses entirely different syntax.  But it acts just like an implicit annotation (e.g. @unchecked automatically applied to all places where it is valid).

I'm not sure this SIP adequately generalizes the concept of what it's trying to achieve.

  --Rex

It is loading more messages.
0 new messages