I'm new to coffee script, and there is likely more things wrong with this definition than this problem itself.
Given
class window.SlideManager
constructor: (#$contentDiv, #analyticsCanvas) ->
#iterator = Iterator(#slides)
#slides = #$contentDiv.data('slides')
nextSlide: ->
try {
url = #iterator.next()
} catch {
#iterator = Iterator(#slides)
url = #iterator.next()
}
this.renderSlide(url)
renderSlide: (slide) ->
$.get(slide, {nolayout: 'true'}, (data) ->
#$contentDiv.contents().replaceWith(data)
window.setupCanvas($(#analyticsCanvas), window.createChartData(window.getVisitCounts($(#analyticsCanvas))))
)
I get a unexpected = syntax error on line 8 (url = #iterator.next())
Does anyone know what I might be missing?
You shouldn't be using braces:
nextSlide: ->
try
url = #iterator.next()
catch
#iterator = Iterator(#slides)
url = #iterator.next()
First, the basics: CoffeeScript uses significant whitespace to delimit blocks of code. You don't need to use semicolons ; to terminate expressions, ending the line will do just as well (although semicolons can still be used to fit multiple expressions onto a single line). Instead of using curly braces { } to surround blocks of code in functions, if-statements, switch, and try/catch, use indentation.
See: http://coffeescript.org/
You may try to use this without brackets{}:
nextSlide: ->
try
url = #iterator.next()
catch
#iterator = Iterator(#slides)
url = #iterator.next()
instead of this:
nextSlide: ->
try {
url = #iterator.next()
} catch {
#iterator = Iterator(#slides)
url = #iterator.next()
Related
I got this error in Swift
"The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions"
Here is the code that is throwing the error.
let obj = self.AddressList[indexPath.row] as! Address
// let a:String! = obj.street+" ,"+obj.city+" "+obj.country
// let b:String! = obj.country
StaticData.singleton.cardAddress = obj.street+" ,"+obj.city+" "+obj.country
StaticData.singleton.AddressID = obj.id
StaticData.singleton.cart_addresstotal = obj.total_amount
StaticData.singleton.cart_addressFee = obj.delivery_fee
DispatchQueue.main.async {
self.dismiss(animated:true, completion:nil)
}
in particular it is this portion of the code in which the error is pointing towards:
StaticData.singleton.cardAddress = obj.street+" ,"+obj.city+" "+obj.country
Just replace the + operator with String concatenation. In general, using String concatenation is the preferred approach over using the + operator.
StaticData.singleton.cardAddress = "\(obj.street) ,\(obj.city) \(obj.country)"
For some reason when I input a string with double spaces such as " ", the function does not remove them from the string, nor does it remove them when they are generated by two WUB's in a row
For example:
songDecoder("WUBCATWUBWUBBALLWUB") outputs "CAT_ _BALL" (underscores represent spaces)
I could fix this by other means, but since I have no idea why my current code isn't working I figured I should ask to patch my understanding.
def songDecoder(song:String):String = {
val l = song.indexOf("WUB")
if (song.contains(" ")) {
val e = song.indexOf(" ")
songDecoder(song.patch(e,Nil,1))
}
if (l==0) {
val c = song.patch(l,Nil,3)
songDecoder(c)
}
if (l== -1)
song.trim
else {
val c = song.patch(l,Nil,2)
val b = c.patch(l," ",1)
songDecoder(b)
}
}
The reason it doesn't work is because when you call a recursive method it eventually returns with its result. The code that clears out the double-whitespace doesn't save that result.
if (song.contains(" ")) {
val e = song.indexOf(" ")
songDecoder(song.patch(e,Nil,1)) //send patched song to decoder
} //don't save returned string
//continue with unpatched song
The 2nd if block also recurses without saving the result.
if (l==0) {
val c = song.patch(l,Nil,3)
songDecoder(c) //send patched song to decoder
} //don't save returned string
//continue with unpatched song
You can remove both of those if blocks and you'll get the same results from your method. The only code that effects the output is the final if/else and that's because it is at the end of the method's code block. So whatever the if/else produces that's what the method returns.
if (l== -1)
song.trim //return the final result string
else {
val c = song.patch(l,Nil,2) //remove one WUB
val b = c.patch(l," ",1) //replace with space
songDecoder(b) //return whatever the next recursion returns
}
Just as an FYI, here's a different approach.
def songDecoder(song:String):String =
"(WUB)+".r.replaceAllIn(song, " ").trim
How about something like:
song.split(“(WUB)+”).mkString(“ “).trim
For context: I'm trying to use the very handy LibXL. I've used it with success in Obj-C and C++ but am now trying to port over to Swift. In order to better support Unicode, I need to sent all strings to the LibXL api as wchar_t*.
So, for this purpose I've cobbled together this code:
extension String {
///Function to convert a String into a wchar_t buffer.
///Don't forget to free the buffer!
var wideChar: UnsafeMutablePointer<wchar_t>? {
get {
guard let _cString = self.cString(using: .utf16) else {
return nil
}
let buffer = UnsafeMutablePointer<wchar_t>.allocate(capacity: _cString.count)
memcpy(buffer, _cString, _cString.count)
return buffer
}
}
The calls to LibXL appear to be working (getting a print of the error messages returns 'Ok'). Except when I try to actually write to a cell in a test spreadsheet. I get can't write row 0 in trial version:
if let name = "John Doe".wideChar, let passKey = "mac-f.....lots of characters...3".wideChar {
xlBookSetKeyW(book, name, passKey)
print(">: " + String.init(cString: xlBookErrorMessageW(book)))
}
if let sheetName = "Output".wideChar, let path = savePath.wideChar, let test = "Hello".wideChar {
let sheet: SheetHandle = xlBookAddSheetW(book, sheetName, nil)
xlSheetWriteStrW(sheet, 0, 0, test, sectionTitleFormat)
print(">: " + String.init(cString: xlBookErrorMessageW(book)))
let success = xlBookSaveW(book, path)
dump(success)
print(">: " + String.init(cString: xlBookErrorMessageW(book)))
}
I'm presuming that my code for converting to wchar_t* is incorrect. Can someone point me in the right direction for that..?
ADDENDUM: Thanks to #MartinR for the answer. It appears that the block 'consumes' any pointers that are used in it. So, for example, when writing a string using
("Hello".withWideChars({ wCharacters in
xlSheetWriteStrW(newSheet, destRow, destColumn, wCharacters, aFormatHandle)
})
The aFormatHandle will become invalid after the writeStr line executes and isn't re-useable. It's necessary to create a new FormatHandle for each write command.
There are different problems here. First, String.cString(using:) does
not work well with multi-byte encodings:
print("ABC".cString(using: .utf16)!)
// [65, 0] ???
Second, wchar_t contains UTF-32 code points, not UTF-16.
Finally, in
let buffer = UnsafeMutablePointer<wchar_t>.allocate(capacity: _cString.count)
memcpy(buffer, _cString, _cString.count)
the allocation size does not include the trailing null character,
and the copy copies _cString.count bytes, not characters.
All that can be fixed, but I would suggest a different API
(similar to the String.withCString(_:) method):
extension String {
/// Calls the given closure with a pointer to the contents of the string,
/// represented as a null-terminated wchar_t array.
func withWideChars<Result>(_ body: (UnsafePointer<wchar_t>) -> Result) -> Result {
let u32 = self.unicodeScalars.map { wchar_t(bitPattern: $0.value) } + [0]
return u32.withUnsafeBufferPointer { body($0.baseAddress!) }
}
}
which can then be used like
let name = "John Doe"
let passKey = "secret"
name.withWideChars { wname in
passKey.withWideChars { wpass in
xlBookSetKeyW(book, wname, wpass)
}
}
and the clean-up is automatic.
I'm having a problem with understand how I can work with substrings in Swift. Basically, I'm getting a JSON value that has a string with the following format:
Something
I'm trying to get rid of the HTML anchor tag with Swift so I'm left with Something. My thought was to find the index of every < and > in the string so then I could just do a substringWithRange and advance up to the right index.
My problem is that I can't figure out how to find the index. I've read that Swift doesn't support the index (unless you extend it.)
I don't want to add CPU cycles unnecessarily. So my question is, how do I find the indexes in a way that is not inefficient? Or, is there a better way of filtering out the tags?
Edit: Converted Andrew's first code sample to a function:
func formatTwitterSource(rawStr: String) -> String {
let unParsedString = rawStr
var midParseString = ""
var parsedString = ""
if let firstEndIndex = find(unParsedString, ">") {
midParseString = unParsedString[Range<String.Index>(start: firstEndIndex.successor(), end: unParsedString.endIndex)]
if let secondStartIndex = find(midParseString, "<") {
parsedString = midParseString[Range<String.Index>(start: midParseString.startIndex, end: secondStartIndex)]
}
}
return parsedString
}
Nothing too complicated. It takes in a String that has the tags in it. Then it uses Andrew's magic to parse everything out. I renamed the variables and made them clearer so you can see which variable does what in the process. Then in the end, it returns the parsed string.
You could do something like this, but it isn't pretty really. Obviously you would want to factor this into a function and possibly allow for various start/end tokens.
let testText = "Something"
if let firstEndIndex = find(testText, ">") {
let testText2 = testText[Range<String.Index>(start: firstEndIndex.successor(), end: testText.endIndex)]
if let secondStartIndex = find(testText2, "<") {
let testText3 = testText2[Range<String.Index>(start: testText2.startIndex, end: secondStartIndex)]
}
}
Edit
Working on this a little further and came up with something a little more idiomatic?
let startSplits = split(testText, { $0 == "<" })
let strippedValues = map(startSplits) { (s) -> String? in
if let endIndex = find(s, ">") {
return s[Range<String.Index>(start: endIndex.successor(), end: s.endIndex)]
}
return nil
}
let strings = map(filter(strippedValues, { $0 != "" })) { $0! }
It uses a little more functional style there at the end. Not sure I much enjoy the Swift style of map/filter compared to Haskell. But anyhow, the one potentially dangerous part is that forced unwrapping in the final map. If you can live with a result of [String?] then it isn't necessary.
Even though this question has been already answered, I am adding solution based on regex.
let pattern = "<.*>(.*)<.*>"
let src = "Something"
var error: NSError? = nil
var regex = NSRegularExpression(pattern: pattern, options: .DotMatchesLineSeparators, error: &error)
if let regex = regex {
var result = regex.stringByReplacingMatchesInString(src, options: nil, range: NSRange(location:0,
length:countElements(src)), withTemplate: "$1")
println(result)
}
Normally in Javascript I can do something like this:
var step;
determineStep();
function determineStep() {
step = 'A';
asyncCallbackA(function(result)) {
if (result.testForB) performB();
});
}
function performB() {
step = 'B';
asyncCallbackB(function(result)) {
if (result.testForC) performC();
});
}
function performC() {
step = 'C';
...
}
However Coffeescript does not allow named functions that get hoisted so I would have to define a function before calling it. This would result in them being out of order (very confusing). And if any of them have circular dependencies then it is not possible at all.
In Coffeescript I am forced to do:
step = null
determineStep =
step = 'A'
asyncCallbackA (result) ->
if result.testForB
step = 'B'
asyncCallbackB (result) ->
if result.testForC
step = 'C'
asyncCallbackC (result) ->
...
determineStep()
If you have multiple steps this can quickly get out of hand.
Is it possible to implement the Javascript pattern in Cofffeescript? If not, what is the best way to handle this scenario?
I think you're a little confused. When you say:
f = -> ...
the var f is (of course) hoisted to the top of the scope but the f = function() { ... } definition is left where it is. This means that the only order that matters is that you need to define all your functions before you determineStep().
For example, this works just fine:
f = -> g()
g = -> h()
h = -> console.log('h')
f()
In your case:
step = null
determineStep = ->
step = 'A'
asyncCallbackA (result) -> performB() if(result.testForB)
performB = ->
step = 'B'
asyncCallbackB (result) -> performC() if(result.testForC)
performC = ->
step = 'C'
...
determineStep()
should be fine. determineStep can call performB before performB is defined (in source order) because:
The var performB is hoisted.
By the time determineStep executes, the performB = function() { ... } will have been done.
Similarly for the other functions so you don't have to worry about interdependencies amongst your functions.