@end #1013

Closed
northborndesign opened this Issue Nov 13, 2013 · 15 comments

Comments

Projects
None yet
7 participants

Apologies if this has been covered in one way or another.

I'd like to propose an @end keyword, which at file scope will end the parsing of that file. In the scope of an imported file, the @end keyword will return the parser to after the point of inclusion.

An example:

@if $condition 
{
    @end;
}
// here be imports

The reasoning is, at the time of this writing, @import cannot be performed conditionally, ( IIRC for the purpose of static analysis ) which makes the "import once" practice difficult to implement without hacking the Sass core.

@if not $condition 
{
    // here be imports... boom
}

This keyword would only be valid at file-scope, and should be an error in @mixin or @function scope.

My Ruby-fu is not quite black-belt, but I'm working on a POC/patch.

lolmaus commented Nov 13, 2013

Sounds like the despicable GOTO.

@lolmaus Definitely not. It's a file-scoped @return. There is no jumping; at least, nowhere but out of the file.

Is there any language that does anything like this?

I don't know that we should be encouraging bad practices when it comes to writing Sass. Partials should be written in such a way that they are safe to include multiple times in the project if need be. Mixing functions/mixins with non-function/non-mixin content is not a good idea.

lolmaus commented Nov 13, 2013

@bracketworks, you're right, but it's still kinda hacky. Ain't it more reasonable to request proper @import-once implementation rather than a hack?

Does this proposed feature has any applications other than a workaround for conditional importing?

@cimmanon Definitely similar support elsewhere.
PHP ( yea, I know, PHP ) allows one to return from a file, resulting in similar behavior.
ASP.NET C# Razor templating allows the same ( the templates are processed to native C# methods, so the return keyword simply returns from a void method )

@lolmaus Off-hand the immediate use case is conditional imports, but it could be used in lieu of deeply nested @if blocks, to linearize the conditional output of a given file:

@if $condition-1 { @end }

// more sass

@if $condition-2 { @end }

// more sass

// wash rinse repeat
Contributor

Snugug commented Nov 13, 2013

If we look at the @import once feature request, we can see that the maintainers are interested in offering this functionality in an upcoming release, and as they stated at SassConf, they are looking to move to a more rapid release cycle, pushing out features when they're ready instead of holding a bunch of features back for a huge release. This sounds like a hack for a hack for something that will be deprecated.

As for implementing @import once now, it's actually very easy to do mimic right now with literally no hacking of Sass proper. Take a look at sass-import-once. That's all that's needed to effectively have it working now.

As for the suggestion that it'd linearize conditional output, let's use @chriseppstein's yardstick for introducing new vocabulary to the Sass lexicon: does the new vocabulary significantly improve the clarity of code for someone who has never seen the language before, or is it just a "nice to have". How does @EnD improve the clarity over @else if? It doesn't even save any characters.

@Snugug The linked sass-import-once seems to be the de facto solution, copied, pasted, and reinvented regularly, however the drawback is:

@include exports(what-happens-if-i) {
    @import "hes-dead-jim";
}

I'm very much looking forward to native @import once, don't get me wrong.

As far as it's measure of improvement; it is "nice to have", perhaps "very nice to have" ( though I'll concede, not's not "required" ). Code clarity is improved because the mental overhead of nested conditions is reduced.

A more familiar keyword, such as @return may assist those coming to the language, I'm not sure. I know that, given it were named @return, it would behave rather predictably based on my experience with other environments, namely templating languages. I assume because both PHP and ASP.NET ( with Razor ) are ubiquitous, it wouldn't be a far stretch.

Contributor

Snugug commented Nov 13, 2013

We already have a @return method, it's for functions.

I still don't see how:

@if ($foo) {
   …
   @end;
}

@if ($bar) {
  …
  @end;
}

Is inherently more clear and has less of a mental overhead than

@if ($foo) {
   …
}
@else if ($bar) {
  …
}

The former requires more code and breaks out of our file before the second @if is called from inside the first @if, which is a huge break in the current mental model for sequential @if statements, which in every other language (and in Sass as it exists now) are both expected to get evaluated. The mental model around @else if is precisely "I want this or this or this".

As for the suggestion that it's in PHP and therefore it's okay, to quote @chriseppstein:

[W]e do not take any inspiration from the language design of PHP and most programmers view PHP as the quintessential example of bad language design

Moreover, returning from an include file in PHP is considered bad coding style, even for PHP.

Owner

hcatlin commented Nov 13, 2013

@else seems to solve this issue pretty cleanly and in a predictable way.

On Wednesday, November 13, 2013, Snugug wrote:

We already have a @return method, it's for functions.

I still don't see how:

@if ($foo) {

@EnD;}
@if ($bar) {

@EnD;}

Is inherently more clear and has less of a mental overhead than

@if ($foo) {
…}@else if ($bar) {
…}

The former requires more code and breaks out of our file before the second
@if is called from inside the first @if, which is a huge break in the
current mental model for sequential @if statements, which in every other
language (and in Sass as it exists now) are both expected to get evaluated.
The mental model around @else if is precisely "I want this or this or
this".

As for the suggestion that it's in PHP and therefore it's okay, to quote
@chriseppsteinhttps://github.com/nex3/sass/issues/626#issuecomment-27711024
:

[W]e do not take any inspiration from the language design of PHP and most
programmers view PHP as the quintessential example of bad language design

Moreover, returning from an include file in PHP is considered bad coding
stylehttp://stackoverflow.com/questions/1314162/return-from-include-file#comment1147017_1314198,
even for PHP.


Reply to this email directly or view it on GitHubhttps://github.com/nex3/sass/issues/1013#issuecomment-28407205
.

We've digressed a bit. The reason behind my suggestion was that @end allows one to escape from a file primarily for the @import once use case. Since we cannot conditionally @import files, we can achieve the desired behavior by conditionally leaving the file preemptively.

I haven't followed the discussion on @import once as intently as others have, however the longevity of the discussion lacking implementation reinforces the difficulty of implementing it. I have suggested this as an alternative that may or may not have less implementation overhead.

The condition linearization was merely icing.

Also @Snugug, note:

PHP ( yea, I know, PHP ) [...]

As a PHP developer, I'm very aware of the ... problems. I participate in discussion with core contributors to improve the "rat's nest" that is PHP. I assure you this idea arose in isolation, with no inspiration from PHP. It was merely an example of another language exhibiting similar behavior ( along with ASP.NET Razor )

Owner

chriseppstein commented Nov 13, 2013

If we do something like this, it would probably be to expose @return to mixins to provide an early exit. Definitely not going to add a bare return from a file.

Furthermore, I'd rather make imports allowed in conditional contexts as I've outlined in #739 so that the file doing the import can simply decide to import or not import other partials.

@chriseppstein Fair enough. Looking forward to conditional imports then.

lolmaus commented Nov 13, 2013

@Snugug
As for the suggestion that it's in PHP and therefore it's okay, to quote @chriseppstein:

[W]e do not take any inspiration from the language design of PHP and most programmers view PHP as the quintessential example of bad language design

How about require_once? It appears to me as a feature that Sass would benefit from.

Consider the situation: two separate modules both depend on Toolkit, and Toolkit unconditionally emits some CSS when required. An @import-once could resolve the issue without a need to manually implement it in every Compass extension (you didn't do it for Toolkit, so...).

Contributor

xzyfer commented Dec 6, 2013

@bracketworks @lolmaus fwiw import-once semantics have now landed in compass/master chriseppstein/compass#1463

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