I'm parsing some XML, and I'm chaining calls without a dot. All of these methods take no parameters (except \\, which takes one), so it should be fairly possible to chain them without a dot, right?
This is the code that does not work:
val angle = filteredContextAttributes.head \\ "contextValue" text toDouble
The error is: not found: value toDouble
However, it does work like this:
(filteredContextAttributes.head \\ "contextValue" text) toDouble
text returns only a String and does not take parameters, and I don't see any other parameters needed in \\ to cause an issue.
What am I missing? I don't want to hack it out, but to understand what' the problem.
And also I can't use head without the dot. When removing the dot it says: Cannot resolve symbol head
It's because text is a postfix notation - this means a method follows the object and takes no parameters. The trick with postfix is that it can only appear at the end expression. That's why when you add parenthesis it works (the expression is then bounded by the parenthesis and you get two postfix notations, one ending with text and the second one ending with toDouble). In your example that's not the case as you are trying to call a method further in the chain.
That's also the reason why you need to do filteredContextAttributes.head and not filteredContextAttributes head. I'm sure if you do (filteredContextAttributes head) it will work as again the postfix notation will be at the end of the expression!
There are also prefix and infix notations in Scala and I urge you to read about them to get a hang of when you can skip . and () (for instance why you need () when using the map method etc.).
To add on what #Mateusz already answered, this is the because of mixing postfix notation and arity-0 suffix notation.
There's also a great write up in another answer: https://stackoverflow.com/a/5597154/125901
You can even see a warning on your shorter example:
scala> filteredContextAttributes.head \\ "contextValue" text
<console>:10: warning: postfix operator text should be enabled
by making the implicit value scala.language.postfixOps visible.
This can be achieved by adding the import clause 'import scala.language.postfixOps'
or by setting the compiler option -language:postfixOps.
See the Scala docs for value scala.language.postfixOps for a discussion
why the feature should be explicitly enabled.
Which is a pretty subtle hint that this isn't the best construct style-wise. So, if you aren't specifically working in a DSL, then you should prefer adding in explicit dots and parenthesis, especially when mixing infix, postfix and/or suffix notations.
For example, you can prefer doc \\ "child" over doc.\\("child"), but once you step outside the DSL--in this example when you get your NodeSeq--prefer adding in perens.
Related
I want to find all the force unwrapped variables in my Xcode project. For example anything that's similar to:
variableName!.property
or
variableName!,
or
variableName! : otherVariable
or
variableName!)
Or any other similar occurrences of force unwrapped variables. What would be a regex pattern for that that I can use in the Xcode search?
This one will search for only valid variable names (alphanumeric strings starting with a letter) that are followed by an ! which is then followed by a space, tab, newline, or a period, comma, colon, or closing parenthesis . This search also excludes finding instances of try! and as!.
([A-z]+[A-Za-z0-9]*(?<![(try)(as)])![.,:)\n\t\r ])
This next pattern will match try! and as! if you are interested in finding those as well.
([A-z]+[A-Za-z0-9]*![.,:)\n\t\r ])
It should be noted both of these patterns will also match for variable types that are force unwrapped optionals (a common variable to be force unwrapped being #IBOutlets)
A really good resource for writing and testing regular expressions is regexr.com
Not fool-proof (that would require a full reading of the Swift syntax) but good enough for most cases:
\w[\w\d]*!
Of course you can simply search for ! - there are only a couple uses other than force unwrap: negative test (!=) and boolean (!valid). You may scoop up some string literals in the search, but unless you are writing an automatic tool, it hardly matters.
You should search .+!(\.|,| :|\)) using the Find > Regular Expression tool
Quite new to Swift, compared to Java and C++...I'm just wondering why Swift doesn't remove spaces when compiling code as following:
if x!=10 {...} //I have to add space before and after != to get rid of issue.
Increment like increment++ as well can not be act as increment in For syntax if I don't put a space between increment++ and { of loop block.
As in Java or C++, space and Tab do not make sense in terms of compiling. Is Swift just like Python in the way of consider space or tab as part of code?
Swift does not consider spaces as important, however it uses them when separating characters into lexemes.
Consider the following:
a != 1
a! =1
a!= 1
a!=1
The first one can be compiled because the lexical analysis correctly recognizes lexems a, != and 1, != being an infix operator.
In the second one, the lexical analysis recognizes lexem a with a postfix operator ! and a 1 with a prefix operator =.
The third one is lexem a with a postfix operator != and lexem 1.
The last one is ambiguous because it can be either a! = 1 or a != 1. The compiler decided probably based on operator priority to use a! = 1.
Spaces are ignored but they still have a meaning when distinguishing between ambiguous cases. The same is actually valid in many languages. The fact that you can define your own operators limits a bit your coding style.
To compare, try a+++b in Java or C++. Will it be a++ + b or a + ++b?
The exclamation mark is not only used as not for example. It is also used to unwrap an optional variable.
There is more syntactic difference to other languages.
I've been enjoying Swift for a while now, but I found one syntax that is incredibly problematic.
Start with the assumption that:
let foo : String = ""
This is a fairly simple check:
if foo!="value" {
But alas, it won't compile. The compiler complains about trying to unwrap a value that is not an optional. I then change that line to:
if foo != "value {
The compiler is happy and the code behaves as expected. This is a case of significant whitespace, and I'm not content with it. I suspect there are situations that this may compile and behave contrary to my intention. Is there an alternative syntax that I should be using to avoid this type of error?
The alternate syntax is to put spaces around infix operators. They are required. Without spaces, it is treated as a prefix or postfix operator. With spaces it is an infix operator. Swift is very consistent about this. I know you realize this is what's happening; I just don't believe there's any way around it, and any cure would be worse than the disease (I can't come up with any examples where this would likely lead to real-world bugs).
Swift will be forgiving if there is no conflict, and allow 1+1 for instance, but you shouldn't do this, either. I believe good Swift style is to just put the spaces in. Yes, it's a case of significant whitespace. The whitespace here is significant, just as you can't say structFoo when you mean struct Foo.
I have a collection I'm unable to drop, I'm assuming that the "-" in its name is a special character. In MongoDB, what is the best way to escape special characters?
> db.tweets.drop();
true
BUT
> db.tweets-old.drop();
ReferenceError: old is not defined (shell):1
I've tried to escape with quotes (both single and double) and a slash, but nothing works.
The following works:
db["tweets-old"].drop();
It's called the square bracket notation, which allows you to use special characters in property names.
So does:
db.getCollection("tweets-old").drop()
And that has been around for a while now.
In addition, the method call also mimics what is the general "get a collection" accessor method in all officially supported MongoDB drivers. So the suggestion here is that you get used to using it this way, since the "named collection" accessor is how it is generally done.
I'm working on a system that uses M4 to expand some files out, but I'm getting a problem with the expansion in certain cases. The convention for definition / macro naming (which I'd rather not change if possible) is __<name>__ (i.e. double leading and trailing underscores.) So this expands correctly:
define(`__ROOT__', `/home/mydir')
...
__ROOT__/bin
gives
/home/mydir/bin
but,
define(`__PREFIX__', `App_Mnemonic')
...
__PREFIX___some_service
should give:
App_Mnemonic_some_service
but gives
__PREFIX___some_service
(i.e. it missed the expansion)
I presume the lack of space between the trailing underscore of the macro and the valid underscore of the underlying text is confusing m4. Is there anything I can do about this? Can I delimit the macro with silent braces, for example, like enviromnment variables?
Deceptively simple really, all I had to do in the underlying text was change this:
__PREFIX___some_service
for this:
__PREFIX__()_some_service
It looks a bit clunky perhaps, but it is a macro after all and there's no need to change the macro definition. So this can stay as it is:
define(`__PREFIX__', `App_Mnemonic')