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.
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.
Our application relies on lots of equations, which, to correspond with the standard scientific names, use variable names like mu_k, (if the standard is $\mu_k$). (We could debate whether scientists should switch to CS style descriptive variable names, but often the terms don't really describe anything, they are just part of equations, and, more over, we need our code to match the known literature.)
In C this is easy to name vars this way: int mu_k. We are considering porting our code to Scala, but I know that val mu_k is discouraged in Scala, because underscores have special meanings.
If we use underscores only in the middle of the var name (e.g. mu_k) and not beginning or end (e.g. _x or x_), will this present a problem in Scala?
What is the recommended naming convention for Scala in this case?
You are right that underscores are discouraged in variable names in Scala, which implies that they are not forbidden. In my opinion, a convention should be followed wherever sensible.
In the case of mathematical formulae, I disagree that the Greek letters don't convey a meaning; the meaning is not necessarily intuitively descriptive for non-mathematicians, but as you say, the reference to the usage in a paper may be meaningful and important. Therefore, sticking with the underscore won't hurt, although I would probably prefer a more Scala-style way as muX when possible and meaningful. If you want a perfect answer, you might need to perform a usability test with your developers. In the specific example, I personally find mu_x more readable than muX, but that might differ among individuals.
I don't think the Scala compiler has a problem with underscores in the examples you described. Presumably, even leading and trailing underscores are fine, but should indeed be avoided strictly because they have a special meaning: http://docs.scala-lang.org/style/naming-conventions.html#methods.
Underscores are not special in any way in identifiers. There are a lot of special meanings for the underscore in Scala, but not in identifiers. (There is a special rule in identifiers that if you want to mix alphanumeric characters and operator characters in the same identifier, they have to be separated by an underscore, e.g. foo? is not a legal identifier, but foo_? is.)
So, there is no problem using an identifier with an underscore in it.
It is generally preferred to use camelCase and PascalCase for alphanumeric identifiers, and not mix alphanumeric and operator characters in the same identifier (i.e. use maxBy instead of max_by and use isFoo instead of foo_?) but that's just a coding convention whose purpose is to reduce the number of "unspecial" underscores, so that you can quickly scan for the "special" ones.
But in your case, you are using special naming conventions anyway, so you don't need to adhere to the community naming conventions as strictly.
However, I personally would actually prefer the name µ_k over mu_k.
That's as far as it goes with Scala, unfortunately. The Fortress programming language by Sun/Oracle did allow boldface, overstrike, superscripts and subscripts in identifier names, so something like µk would have been possible as a legal identifier, but sadly, Fortress was abandoned a couple of years ago.
I'm not stating this is the correct way, and myself would be rather discouraged to do this, but you can use full string literals as identifiers:
From: http://www.scala-lang.org/files/archive/spec/2.11/01-lexical-syntax.html
id ::= plainid
| ‘’ stringLiteral ‘’
Finally, an identifier may also be formed by an arbitrary string
between back-quotes (host systems may impose some restrictions on
which strings are legal for identifiers). The identifier then is
composed of all characters excluding the backquotes themselves.
So this is valid:
val ’mu k‘
(sorry, for formatting)
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.
Is it a good idea to quote keys when using a hash in Perl?
I am working on an extremely large legacy Perl code base and trying to adopt a lot of the best practices suggested by Damian Conway in Perl Best Practices. I know that best practices are always a touchy subject with programmers, but hopefully I can get some good answers on this one without starting a flame war. I also know that this is probably something that a lot of people wouldn't argue over due to it being a minor issue, but I'm trying to get a solid list of guidelines to follow as I work my way through this code base.
In the Perl Best Practices book by Damian Conway, there is this example which shows how alignment helps legibility of a section of code, but it doesn't mention (anywhere in the book that I can find) anything about quoting the hash keys.
$ident{ name } = standardize_name($name);
$ident{ age } = time - $birth_date;
$ident{ status } = 'active';
Wouldn't this be better written with quotes to emphasize that you are not using bare words?
$ident{ 'name' } = standardize_name($name);
$ident{ 'age' } = time - $birth_date;
$ident{ 'status' } = 'active';
Without quotes is better. It's in {} so it's obvious that you are not using barewords, plus it is both easier to read and type (two less symbols). But all of this depends on the programmer, of course.
When specifying constant string hash keys, you should always use (single) quotes. E.g., $hash{'key'} This is the best choice because it obviates the need to think about this issue and results in consistent formatting. If you leave off the quotes sometimes, you have to remember to add them when your key contains internal hypens, spaces, or other special characters. You must use quotes in those cases, leading to inconsistent formatting (sometimes unquoted, sometimes quoted). Quoted keys are also more likely to be syntax-highlighted by your editor.
Here's an example where using the "quoted sometimes, not quoted other times" convention can get you into trouble:
$settings{unlink-devices} = 1; # I saved two characters!
That'll compile just fine under use strict, but won't quite do what you expect at runtime. Hash keys are strings. Strings should be quoted as appropriate for their content: single quotes for literal strings, double quotes to allow variable interpolation. Quote your hash keys. It's the safest convention and the simplest to understand and follow.
I never single-quote hash keys. I know that {} basically works like quotes do, except in special cases (a +, and double-quotes). My editor knows this too, and gives me some color-based cues to make sure that I did what I intended.
Using single-quotes everywhere seems to me like a "defensive" practice perpetrated by people that don't know Perl. Save some keyboard wear and learn Perl :)
With the rant out of the way, the real reason I am posting this comment...the other comments seem to have missed the fact that + will "unquote" a bareword. That means you can write:
sub foo {
$hash{+shift} = 42;
}
or:
use constant foo => 'OH HAI';
$hash{+foo} = 'I AM A LOLCAT';
So it's pretty clear that +shift means "call the shift function" and shift means "the string 'shift'".
I will also point out that cperl-mode highlights all of the various cases correctly. If it doesn't, ping me on IRC and I will fix it :)
(Oh, and one more thing. I do quote attribute names in Moose, as in has 'foo' => .... This is a habit I picked up from working with stevan, and although I think it looks nice... it is a bit inconsistent with the rest of my code. Maybe I will stop doing it soon.)
Quoteless hash keys received syntax-level attention from Larry Wall to make sure that there would be no reason for them to be other than best practice. Don't sweat the quotes.
(Incidentally, quotes on array keys are best practice in PHP, and there can be serious consequences to failing to use them, not to mention tons of E_WARNINGs. Okay in Perl != okay in PHP.)
I don't think there's a best practice on this one. Personally I use them in hash keys like so:
$ident{'name'} = standardize_name($name);
but don't use them to the left of the arrow operator:
$ident = {name => standardize_name($name)};
Don't ask me why, it's just the way I do it :)
I think the most important thing you can do is to always, always, always:
use strict;
use warnings;
That way the compiler will catch any semantic errors for you, leaving you less likely to mistype something, whichever way you decide to go.
And the second most important thing is to be consistent.
I go without quotes, just because it's less to type and read and worry about. The times when I have a key which won't be auto-quoted are few and far between so as not to be worth all the extra work and clutter. Perhaps my choice of hash keys have changed to fit my style, which is just as well. Avoid the edge cases entirely.
It is sort of the same reason I use " by default. It's more common for me to plop a variable in the middle of a string than to use a character that I don't want interpolated. Which is to say, I've more often written 'Hello, my name is $name' than "You owe me $1000".
At least, quoting prevent syntax highlighting reserved words in not-so-perfect editors. Check out:
$i{keys} = $a;
$i{values} = [1,2];
...
I prefer to go without quotes, unless I want some string interpolation. And then I use double quotes. I liken it to literal numbers. Perl would really allow you to do the following:
$achoo['1'] = 'kleenex';
$achoo['14'] = 'hankies';
But nobody does that. And it doesn't help with clarity, simply because we add two more characters to type. Just like sometimes we specifically want slot #3 in an array, sometimes we want the PATH entry out of %ENV. Single-quoting it add no clarity as far as I'm concerned.
The way Perl parses code makes it impossible to use other types of "bare words" in a hash index.
Try
$myhash{shift}
and you're only going to get the item stored in the hash under the 'shift' key, you have to do this
$myhash{shift()}
in order to specify that you want the first argument to index your hash.
In addition, I use jEdit, the ONLY visual editor (that I've seen--besides emacs) that allows you total control over highlighting. So it's doubly clear to me. Anything looking like the former gets KEYWORD3 ($myhash) + SYMBOL ({) + LITERAL2 (shift) + SYMBOL (}) if there is a paranthesis before the closing curly it gets KEYWORD3 + SYMBOL + KEYWORD1 + SYMBOL (()}). Plus I'll likely format it like this as well:
$myhash{ shift() }
Go with the quotes! They visually break up the syntax and more editors will support them in the syntax highlighting (hey, even Stack Overflow is highlighting the quote version). I'd also argue that you'd notice typos quicker with editors checking that you ended your quote.
It is better with quotes because it allows you to use special characters not permitted in barewords. By using quotes I can use the special characters of my mother tongue in hash keys.
I've wondered about this myself, especially when I found I've made some lapses:
use constant CONSTANT => 'something';
...
my %hash = ()
$hash{CONSTANT} = 'whoops!'; # Not what I intended
$hash{word-with-hyphens} = 'whoops!'; # wrong again
What I tend to do now is to apply quotes universally on a per-hash basis if at least one of the literal keys needs them; and use parentheses with constants:
$hash{CONSTANT()} = 'ugly, but what can you do?';
You can precede the key with a "-" (minus character) too, but be aware that this appends the "-" to the beginning of your key. From some of my code:
$args{-title} ||= "Intrig";
I use the single quote, double quote, and quoteless way too. All in the same program :-)
I've always used them without quotes but I would echo the use of strict and warnings as they pick out most of the common mistakes.