Judging by the downvotes I seem to have set off the Elixir fanboys. You can't define additional string interpolation syntax with Rust, but you can define custom functions to convert from a string to any given type with the Into trait. You can also use arbitrary delimiters with the raw string syntax.
As another comment pointed out, Scala lets you define the equivalent of custom sigils. Elixir brings good, bad, new, and old things to the table but custom sigils are not particularly new or unusual.
The article mentions being inspired by Rust syntax, save for 'skipping the ugly “r”', but neglects to mention that the leading r exists so that it's possible to have raw strings that have zero hashes at either end. IOW, in Rust, a string that allows escape sequences looks like "foo", and a string that doesn't allow escape sequences looks like r"foo". And note that Rust didn't invent this syntax, but rather took it from Python--though the addition of optional hashes around the string delimiters allows this single syntax to raw-encode not just backslashes, but also double-quotes (which Python has a separate, triply-quoted string syntax for (and which Swift appears to have used to denote multiline strings (which is just the default behavior of all string literals in Rust))).
> This system was inspired by the Rust programming language. Rust stacks one or more pounds at each end of a string (and prefixes the letter “r”) to create what it calls “raw strings”, that is strings without further escape sequence interpretation. You cannot incorporate interpolation or coded tabs, new lines, or returns.
“one or more” should be “zero or more”, and the bit about the “r” prefix shouldn’t be parenthesised, as it’s actually the part that makes it a raw string. Also its mention of interpolation is poor: Rust doesn’t have interpolation on plain string literals, but things like the format!() macro perform what is more or less interpolation on their first argument (which must be a string literal), and raw strings work just fine there.
The only thing I want from Swift 5 is easier string handling. I just want an easy and concise way to do things like split a filename into parts, extract regex matches, etc. At the moment it's faster to write string handling code in Objective C...
This is not something strings should do; you should be using URL instead. Foundation realized this long ago and has started deprecating string-based path APIs because treating a path as a string exposes fundamental misconceptions very quickly.
> extract regex matches
This is something that is being worked on/discussed, but has not been “solved” yet.
I didn't mean that String should have a "pathExtension" property like NSString. I just want operations like "insert a number before the last period" to be easier to do.
Also, there are a lot more things that are a pain with String. I mean, just the fact that I can't pass a Substring to a function that expects a String boggles my mind.
Yes, like I said, you should be using URL for this, which will make it possible to extract the filename without the extension, modify it, and get the path string from that (which is semantically what I believe you are trying to do). Not only does this create self-documenting code, it also makes it harder to fall into a the many “gotchas” that handling paths entails.
Yes, I know that, but I was just using filename manipulation as an example, because it was the first thing that came to my mind. I now see it was a bad example, since URL has a couple of APIs for file name handling.
Anyway, these types of operations come up all the time when working with strings, and these operations are really really incovenient in Swift.
> Anyway, these types of operations come up all the time when working with strings, and these operations are really really incovenient in Swift.
Again, what are these operations? I think most of the issues people have with String is due to hard to discover APIs rather than design issues with String.
Text parsing is something that comes up often (for me). For example parsing CSV files, or parsing tab separated data from the clipboard, or parsing various types of config files.
Swift has sweet solutions for a few special cases (eg. parse file names, parse dates, parse JSON), but parsing generic text is not something that Swift is good at.
NSString has a rich set of APIs for those tasks (NSScanner, NSRegularExpression, and all the rangeOfString... methods). Swift has pretty much nothing. (There is firstIndex(of:), but as far as I can see there is no way to find the next index, which makes it pretty much useless for most parsing tasks)
Maybe the problem is that I'm just not familiar enough with Swifts String, but until now every time I've had to work with Strings I became very frustrated.
Why would URL be needed to handle file system only paths? They’re different and OS Specific. Rusts Path vs String vs third-party URL strikes the right balance IMO. It’s a third thing.
Sorta, it's the right choice on iOS and macOS but conceptually filesystem paths are different than URIs even though the same information can be encoded into both. It's weird to have URIs pointing at google (technically valid by means of being the same type) being passed to file-management APIs - only to have them unsurprisingly fail. It subverts the type system by allowing invalid blobs to avoid being caught by the type system. Paths as URIs in contexts where only FS paths are valid is akin to any other stringly-typed API. A third type is more logical: URL, String and FsPath.
I’m not sure about the specifics with swift, but I thinking he’s referring to a type, URL. Ruby has a URI module that you would use to work with uri strings, and I think that’s exactly what he is taking about.
I was playing along with Advent of Code and decided to do some of the puzzles, mainly ones where having a graphical view of what's going on would be really nice, in Swift. For reference, the other ones were done in D.
My input parsing code was inevitably a mess of stuff like:
let parts = l.components(separatedBy: ",")
let first = parts[0].components(separatedBy: "=")
let second = parts[1].trimmingCharacters(in: .whitespaces).components(separatedBy: "=")
When I did puzzles in D my input parsing was just creating a regex, matching on it, and pulling out the results.
I started to look at how to do regex in Swift and it seemed easier (!) to just use .components(separatedBy:) as required. Google came up with a number of people who have created libraries/extensions that make this easier, but Swift really needs some better regex handling built in.
I really wish Swift closures were more uniform. I remember Alan Kay (or maybe Dan Ingalls) was famed for saying “its ok to cheat, as long as you don’t get caught” (re. Language implementation).
I really like swift, but there are times when I feel I need a magic decoder to figure out which edge cases apply. My biggest frustration is that something like this
for view in self.subviews { view in
...
return something
}
Is very different from the naively similiar
self.subviews.forEach { view in
...
return something
}
I just wish closures were a more first class part of the language like they were in Smalltalk. If language written in 1980 could use closures/lambdas all the way down even for things like if/else, and keep the deception pretty complete, I don’t understand why swift can’t do similiar.
The trailing closure syntax [1] seems to be a point of pride with Swift. However, I feel that it’s grown to be a painful aspect of the language. Another example is when a function takes two closure arguments, e.g.:
> I just wish closures were a more first class part of the language like they were in Smalltalk.
Functions are first class types and values in Swift. Both named functions and anonymous functions can be used as values and can capture values from outer scopes. What’s not first class?
> If language written in 1980 could use closures/lambdas all the way down even for things like if/else, and keep the deception pretty complete, I don’t understand why swift can’t do similiar.
Smalltalk’s approach of using higher order functions for all control structures is more uniform in some ways but is not inherently superior. Swift has statements that perform non-local control transfer (break, continue, return) and designing those to work with closures (presumably only non-escaping closures) would be tricky. Also Swift ‘if’ and ‘switch’ statements can perform pattern matching and bind variables in various complex ways, so again it’s not clear if completely unifying all this with anonymous closure syntax would produce something that is simpler overall than just special casing conditionals and loops in the statement syntax.
I don't understand your syntax on the for-in. Is there some magic on an array that takes a closure and is nonobvious? Or is there a syntactic issue with the code in your comment?
tho I'm not familiar with swift: my guess here is that the first (for ... in) shares a closure / var, so stuff like this classic JS mistake can happen:
for i=0;i<10;i++ { setTimeout(() => console.log(i), 100); }
and you get 10 calls logging "9". (most languages I've touched do this, JS just makes it worse since `var x` in the loop will not fix it)
The second won't do that, since the "view" var isn't "mutated" between calls.
2) GGP is returning in a void block so both sets of code will fail
3) there is really no difference except iteration vs function calls as far as I can tell, you can iterate arrays and use higher order functions built into arrays... which seems normal
4) you can only access the index in (1) by calling .enumerated() I suppose.
I think the difference OP is pointing out is that the return behaves differently. In the forEach, the return exits the closure, but in for-in, it returns from the enclosing function.
First, to make arguments that rely on syntax, one must use correct syntax. If OP’s syntax were valid, that return in the for-in would indeed exit the closure.
To address this argument: the fact that a ‘return’ within a loop exits the enclosing function and a return from within a closure exits the closure is not a Swift problem.
I am not familiar with the Swift world - a quick look at the site says "Objective-C not present on Linux" .. I assume that means the GUI parts also ?
I am not sure how this plays out, if you think.. Apple gets the GUI builder only on Apple products, but "community" builds the plumbing, while small groups at Apple or elsewhere, are paid to make sure plumbing + GUI is advancing .. ? If this is roughly true, what benefit does the non-Apple world get here?
The benefit is that Swift is a fantastic language that people want to use outside of macOS and iOS development. Remember that languages and frameworks aren’t the same thing.
You can still use Swift to plug into other GUI frameworks and libraries to make apps on other platforms, and there are a few Swift frameworks for writing web applications such as Vapor and IBM Kitura.
Swift on Linux lacks the Objective-C runtime and therefore the Objective-C-based Foundation and Cocoa frameworks. In their place, the Swift project has been creating a pure Swift replacement.
Linux is also an easy target for cross-platform development in Swift, given that it’s a POSIX OS and a first—class host for LLVM. It’s a great testbed for the pure Swift and cross-platform developmen and tooling before it eventually moves to Windows as a first-class Swift platform.
> Swift on Linux lacks the Objective-C runtime and therefore the Objective-C-based Foundation and Cocoa frameworks. In their place, the Swift project has been creating a pure Swift replacement.
Clarification: Foundation is being reimplemented in Swift. Cocoa will continue to be written in Objective-C and be macOS-only.
I found your comment to be flippant and condescending in way that doesn’t drive this conversation forward, especially since you don’t back up your argument. Perhaps you could fix these?
I’m sure it’s just anti-Apple trolling and flame bait. Possibly also fueled by HN being fascinated with JavaScript and Rust right now such that nothing else is worthy of praise.
At any rate, it’s easier to be bitter about nothing than constructive about something.
Ruby string interpolation (might be the exact same as Perl): %[string] or %^string^ or %(string), etc. Basically % followed by any pair of the same character around a string works.
This kind of feels like, "so we put a huge ice cube in the ocean and finally solved global warming."
Isn't it just yet another syntax for strings with another set of rules? What happens when my string includes """# ? Why not just make """ behave this new way and have one less type of string literal?
Why can't the solution be, "put the ASCII in a file to be read in." ?
Changing the behavior of """ would cause compatability issues, especially considering it's not unreasonable to want a multiline string that employs escape codes. There are plenty of cases where you want a large string literal embedded in the binary as opposed to reading a file at runtime (hard-coded OpenGL shaders are one case I can think of).
Perl 6 (Raku) takes it a little further with what's known as the Q lang[1].
In their most literal form possible, strings are created by using a Q followed
by any pair delimiting surrounding the text.
Q[This is a literal string.] #=> This is a literal string.
Q!The most literal-est of all.! #=> The most literal-est of all.
Q<So I say 'Hello'> #=> So I say 'Hello'
From there, adverbs are used to sort of expand a literal string's behavior.
For example, `Q:q` (or its more verbose form, `Q:single`) means the string can
interpolate \\, \qq[...] and escaping the delimiter with \.
Q:q[A simple string] #=> A simple string
Q:q{Backslash: \} #=> Backslash: \
Q:q!Backslash: \\! #=> Backslash: \
Q:q{This is a \} so not too early.} #=> This is a } so not too early.
In the other hand, `Q:qq` (or `Q:double`) means the string can
interpolate scalars (`$`), arrays (`@`), hashes (`%`), function calls (`&`),
closure (`{...}`) and backslashes.
In order to prevent unwanted interpolation such as in "username@email.xyz" or
"https://es.wikipedia.org/wiki/%C3%87", only scalar variables are interpolated
normally. As demonstrated, the array constructor `[]` is used to interpolate
a whole array , the hash constructor `{}` for a hash, etc.
Since both `Q:q` and `Q:qq` are so common in the language, they have more
usual and succinct forms: single quotes (`''`) for `Q:q` and double quotes(`""`)
for `Q:qq`. Furthermore the Q can be dropped so `q` or `qq` (followed by
a delimiter) can be used as well.
From here onwards, a small number of adverbs can be used on the quoting
constructs `q` or `qq` to further restrict/expand a string's behavior.
For example, for a string that only interpolates scalar ($) and closure ({...})
variables, the adverbs `:s` (or `:scalar`) and `:c` (or `:closure`) can be used.
This results in `qq:s:c` (or `qq:sc`, `qq:scalar:closure`). For example:
I see comments like this a lot about Perl and PHP as if they are trying to justify why they shouldn't have fallen out of favor. Both languages had plenty of good things, but rehashing them in this way doesn't do anything because the good things are not the reason they fell out of favor.
I flagged your comment, not only because it is utterly irrelevant (which would just earn you a downvote), but because it is a lame attempt to start yet another language war. Please try to post better in the future, thanks.
You really deserve a "fuck off you judgemental wanker".
Bring on the down votes.
Not all of us think that HN etiquette (and lack of sense of humour) is perfect, I come here for interest in the subjects covered, not for the snottiness of the attitudes of other users.
Ok, but if you want to comment here, you need the discipline to refrain from outright personal attack even when another comment was unfairly provocative.
https://elixir-lang.org/getting-started/sigils.html