LESSCSS loop with #import (inline) causes "SyntaxError: Recursive variable definition" - less

I have an array:
#styles: amelia, cerulean, cosmo, cyborg, darkly, flatly, fonts, journal, lumen, readable, simplex, slate, spacelab, superhero, united, yeti;
And I have my loop:
.loopStyles (#index) when (#index > 0) {
#name: extract(#styles, #index);
.nb-#{name} {
#import (inline) 'bower_components/bootswatch/#{name}/bootstrap.css';
}
.loopStyles(#index - 1);
}
.loopStyles(length(#styles));
However this throws an error: SyntaxError: Recursive variable definition for #index.
If I remove the #import or if I change the import option reference to something other than less or inline, it works just fine.
What I'm trying to achieve is a way to prefix these extra styles with a class, so I'd prefer if the stylesheet was imported inline rather than referenced.

Less docs state "...only variables which have been declared in the root or current scope will be considered and that only the current file and calling files will be considered when looking for a variable. This means that this usage is typically limited to when you inject a variable into the compile process or define a variable at the beginning of your root file."
I've gotten a lot of irrelevant errors while trying to get this to work.

Related

Separating operator definitions for a class to other files and using them

I have 4 files all in the same directory: main.rakumod, infix_ops.rakumod, prefix_ops.rakumod and script.raku:
main module has a class definition (class A)
*_ops modules have some operator routine definitions to write, e.g., $a1 + $a2 in an overloaded way.
script.raku tries to instantaniate A object(s) and use those user-defined operators.
Why 3 files not 1? Since class definition might be long and separating overloaded operator definitions in files seemed like a good idea for writing tidier code (easier to manage).
e.g.,
# main.rakumod
class A {
has $.x is rw;
}
# prefix_ops.rakumod
use lib ".";
use main;
multi prefix:<++>(A:D $obj) {
++$obj.x;
$obj;
}
and similar routines in infix_ops.rakumod. Now, in script.raku, my aim is to import main module only and see the overloaded operators also available:
# script.raku
use lib ".";
use main;
my $a = A.new(x => -1);
++$a;
but it naturally doesn't see ++ multi for A objects because main.rakumod doesn't know the *_ops.rakumod files as it stands. Is there a way I can achieve this? If I use prefix_ops in main.rakumod, it says 'use lib' may not be pre-compiled perhaps because of circular dependentness
it says 'use lib' may not be pre-compiled
The word "may" is ambiguous. Actually it cannot be precompiled.
The message would be better if it said something to the effect of "Don't put use lib in a module."
This has now been fixed per #codesections++'s comment below.
perhaps because of circular dependentness
No. use lib can only be used by the main program file, the one directly run by Rakudo.
Is there a way I can achieve this?
Here's one way.
We introduce a new file that's used by the other packages to eliminate the circularity. So now we have four files (I've rationalized the naming to stick to A or variants of it for the packages that contribute to the type A):
A-sawn.rakumod that's a role or class or similar:
unit role A-sawn;
Other packages that are to be separated out into their own files use the new "sawn" package and does or is it as appropriate:
use A-sawn;
unit class A-Ops does A-sawn;
multi prefix:<++>(A-sawn:D $obj) is export { ++($obj.x) }
multi postfix:<++>(A-sawn:D $obj) is export { ($obj.x)++ }
The A.rakumod file for the A type does the same thing. It also uses whatever other packages are to be pulled into the same A namespace; this will import symbols from it according to Raku's standard importing rules. And then relevant symbols are explicitly exported:
use A-sawn;
use A-Ops;
sub EXPORT { Map.new: OUTER:: .grep: /'fix:<'/ }
unit class A does A-sawn;
has $.x is rw;
Finally, with this setup in place, the main program can just use A;:
use lib '.';
use A;
my $a = A.new(x => -1);
say $a++; # A.new(x => -1)
say ++$a; # A.new(x => 1)
say ++$a; # A.new(x => 2)
The two main things here are:
Introducing an (empty) A-sawn package
This type eliminates circularity using the technique shown in #codesection's answer to Best Way to Resolve Circular Module Loading.
Raku culture has a fun generic term/meme for techniques that cut through circular problems: "circular saws". So I've used a -sawn suffix of the "sawn" typename as a convention when using this technique.[1]
Importing symbols into a package and then re-exporting them
This is done via sub EXPORT { Map.new: ... }.[2] See the doc for sub EXPORT.
The Map must contain a list of symbols (Pairs). For this case I've grepped through keys from the OUTER:: pseudopackage that refers to the symbol table of the lexical scope immediately outside the sub EXPORT the OUTER:: appears in. This is of course the lexical scope into which some symbols (for operators) have just been imported by the use Ops; statement. I then grep that symbol table for keys containing fix:<; this will catch all symbol keys with that string in their name (so infix:<..., prefix:<... etc.). Alter this code as needed to suit your needs.[3]
Footnotes
[1] As things stands this technique means coming up with a new name that's different from the one used by the consumer of the new type, one that won't conflict with any other packages. This suggests a suffix. I think -sawn is a reasonable choice for an unusual and distinctive and mnemonic suffix. That said, I imagine someone will eventually package this process up into a new language construct that does the work behind the scenes, generating the name and automating away the manual changes one has to make to packages with the shown technique.
[2] A critically important point is that, if a sub EXPORT is to do what you want, it must be placed outside the package definition to which it applies. And that in turn means it must be before a unit package declaration. And that in turn means any use statement relied on by that sub EXPORT must appear within the same or outer lexical scope. (This is explained in the doc but I think it bears summarizing here to try head off much head scratching because there's no error message if it's in the wrong place.)
[3] As with the circularity saw aspect discussed in footnote 1, I imagine someone will also eventually package up this import-and-export mechanism into a new construct, or, perhaps even better, an enhancement of Raku's built in use statement.
Hi #hanselmann here is how I would write this (in 3 files / same dir):
Define my class(es):
# MyClass.rakumod
unit module MyClass;
class A is export {
has $.x is rw;
}
Define my operators:
# Prefix_Ops.rakumod
unit module Prefix_Ops;
use MyClass;
multi prefix:<++>(A:D $obj) is export {
++$obj.x;
$obj;
}
Run my code:
# script.raku
use lib ".";
use MyClass;
use Prefix_Ops;
my $a = A.new(x => -1);
++$a;
say $a.x; #0
Taking my cue from the Module docs there are a couple of things I am doing different:
Avoiding the use of main (or Main, or MAIN) --- I am wary that MAIN is a reserved name and just want to keep clear of engaging any of that (cool) machinery
Bringing in the unit module declaration at the top of each 'rakumod' file ... it may be possible to use bare files in Raku ... but I have never tried this and would say that it is not obvious from the docs that it is even possible, or supported
Now since I wanted this to work first time you will note that I use the same file name and module name ... again it may be possible to do that differently (multiple modules in one file and so on) ... but I have not tried that either
Using the 'is export' trait where I want my script to be able to use these definitions ... as you will know from close study of the docs ;-) is that each module has it's own namespace (the "stash") and we need export to shove the exported definitions into the namespace of the script
As #raiph mentions you only need the script to define the module library location
Since you want your prefix multi to "know" about class A then you also need to use MyClass in the Prefix_Ops module
Anyway, all-in-all, I think that the raku module system exemplifies the unique combination of "easy things easy and hard thinks doable" ... all I had to do with your code (which was very close) was tweak a few filenames and sprinkle in some concise concepts like 'unit module' and 'is export' and it really does not look much different since raku keeps all the import/export machinery under the surface like the swan gliding over the river...

flowtype definition of Iterable from immutable.js breaks other libs' Iterables

I just added immutable.js as a dependency to my project. I added
node_modules/immutable/dist/immutable.js.flow
to my .flowconfig.
The problem is that immutable exports an Iterable type, which is also a global type used in many other libraries that are in node_modules/, such as fbjs and react-native. For example one of the errors below.
node_modules/fbjs/lib/countDistinct.js.flow:22
22: function countDistinct<T1, T2>(iter: Iterable<T1>, selector: (item: T1) => T2): number {
^^^^^^^^^^^^ type application of identifier `Iterable`. Too few type arguments. Expected at least 2
32: declare class Iterable<K, V> extends _ImmutableIterable<K, V, typeof KeyedIterable, typeof IndexedIterable, typeof SetIterable> {}
^^^^ See type parameters of definition here. See lib: flow/immutable.js:32
In order to fix this I copied immutable.js.flow to my project and removed the .flowconfig line that includes it. In my copied file I rename Iterable to WhateverIterable and the errors are gone.
What is the best way to fix this thing without having to manually edit the immutable definitions?
The main problem is that node_modules/immutable/dist/immutable.js.flow is not written to be a library definition, so using it as one can cause errors.
What is immutable.js.flow
The docs refer to these files as declaration files. immutable.js.flow sits next to a file named immutable.js. Whenever Flow is asked to require immutable.js, it will resolve to immutable.js.flow instead. You can test this with the flow find-module command, which shows which file Flow resolves to when foo.js imports immutable:
$ flow find-module immutable foo.js
/Users/glevi/test/immutable/node_modules/immutable/dist/immutable.js.flow
Declaration files are written a little differently than libdefs. Library definitions declare a bunch of global things. They declare which variables, functions, types, classes, modules, etc are available globally, and declare the types of these things. Declaration files declare only the type of the module that they are shadowing.
A libdef for immutablejs would look like
declare module 'immutable' {
declare class Iterable<K,V> { ... }
...
}
while immutable.js.flow might look like
declare export class Iterable<K,V> { ... }
What should you do
In theory, you should not need to add node_modules/immutable/dist/immutable.js.flow to your .flowconfig. Flow should automatically use it whenever your code imports immutable.
If there is a problem with the immutable.js.flow that immutable ships with, then the best thing to do is to open a pull request or issue against immutable.js.flow or to submit a libdef to flow-typed.
A quick search shows someone working on a immutable libdef, so that might help too!

PostCSS import as reference instead of inline

Less has this handy option whereby the referenced importing file will be only used to resolve variables but it will not be inlined. Is there any way to do the same with postcss-import or any other similar PostCSS plugin?
The below block of code is how this behaviour works in Less. I'd like to achieve similar behaviour with PostCSS.
#import (reference) "foo.less";
/* Content of "foo.less" won't be inlined but variables on this different file will be resolved */
.rules {
width: #big; /* Declared in "foo.less". It will be resolved to 1200px (for example) */
}

Do I need to declare a global variable inside every external typescript module?

I've been using one global variable called system which is defined in index.ts.
When I was using internal modules that went fine, probably because I started compiling in index.ts with --out.
Now I'm switching to external modules the compiler throws errors for the global variable 'system'.
I kept a single in each file with some .d.ts files for external libs, and I tried adding
declare var system:System
in that shared reference file, but that didnt work.
What does work is adding the declare statement to each file that uses the global variable.
So my question is if this is the way I should do it (declaring in every file), or if there's something I'm missing.
Tnx!
In Visual Studio 2013 (Update 3) the mere presence of system.d.ts is enough in the test I set up...
system.d.ts (I made this up)
interface System {
someStuff(): void;
}
declare var system: System;
afile.ts
class Lower {
constructor(private word: string) {
system.someStuff();
}
}
export = Lower
And I could access system.someStuff(); from anywhere.
If you are using a different IDE, you may need to add:
///<reference path="system.d.ts" />
This hints to the compiler that the definition exists, but doesn't actually import system as an external module (you can use import system = require('system'); if you want to load it like a module, but I don't think that's what you want in this case as you've stated that this is a global variable.

Duplicate symbol error — global constant

In the header of the class, outside of interface declaration, I've declared global constants:
NSString * const gotFilePathNotification = #"gotFilePath";
NSString * const gotResultNotification = #"gotResultOfType";
gotResultNotification is used only in this class (yet), but I reference gotFilePathNotificaion in another class implementation. To do it, I import this header.
When I try to compile, I get a duplicate symbol linker error about gotFilePathNotification in this header. Why does it happen?
You have two identifier(s) with same name across two different compilation unit(s) at file scope. This violates One Definition Rule. Instead you need to -
Declare the global variables marking to have external linkage in a header file.
extern NSString * const gotFilePathNotification;
Now provide the definition in only one source file.
NSString * const gotFilePathNotification = #"gotFilePath";
Now where ever you need to use these variables, include the header in the source file.
You need to declare them extern in the header file and define them in implementation file. See this question for clarification. Global Variables in Cocoa/Objective-C? .
The second response provides the clarification that I will reiterate here. The default storage qualifier for variables is static. This means when you try to link two different files with the same variable, as will happen when you import your header file, the linker will construe that the variable is multiply-defined.
Also make sure you're including the h file and not the m file. This was driving me nuts.