-1

I am new to Swift and I am trying to experiment with the language to familiarize myself with all the cool functionality. Currently, I am trying to write a forEach closure to append a different string depending on the value of the element in the forEach. The variable lightStates is a [Bool] list. What I am looking for is for statusStr to be a string of "1"'s and "0"'s depending if the b element in the forEach closure is true or false,

I am getting a "Declared closure result 'String' is incompatible with contextual type 'Void'" error at the String in... line within the closure.

   var statusStr : String = ""
   statusStr.append(lightStates.forEach{ (b:Bool) -> String in return b ? "1":"0"})
   return "Lights: \(statusStr) \n"

Ideally, I would like to know know if what I am doing is even allow/possible. But also I am open to suggestions in how to get the desired functionality (printing a string of "1"'s and "0"'s based on a array of [Bool]s)

DaOhms
  • 11
  • 1

2 Answers2

0

Yes, you are doing wrong first of all. Foreach doesn't return anything and append function require something to add.

You can use map here instead of foreach. something like this

statusStr.append(contentsOf: array.map { $0.description == "true" ? "1" : "2" })

i know this is not the optimised or best solution but i am just trying to clear logic here.

CrackIt
  • 606
  • 1
  • 5
  • 15
0

Option 1 (simplest):

lightStates.map { $0 ? "1" : "0" } .joined()

Option 2 (reusable):

Store the bits in an integer type (UInt fits up to 64), and then turn that into a String.

public extension Sequence {
  /// The first element of the sequence.
  /// - Note: `nil` if the sequence is empty.
  var first: Element? {
    var iterator = makeIterator()
    return iterator.next()
  }

  /// - Returns: `nil` If the sequence has no elements, instead of an "initial result".
  func reduce(
    _ getNextPartialResult: (Element, Element) throws -> Element
  ) rethrows -> Element? {
    guard let first = first
    else { return nil }

    return try dropFirst().reduce(first, getNextPartialResult)
  }

  /// Accumulates transformed elements.
  /// - Returns: `nil`  if the sequence has no elements.
  func reduce<Result>(
    _ transform: (Element) throws -> Result,
    _ getNextPartialResult: (Result, Result) throws -> Result
  ) rethrows -> Result? {
    try lazy.map(transform).reduce(getNextPartialResult)
  }
}
public extension BinaryInteger {
  /// Store a pattern of `1`s and `0`s.
  /// - Parameter bitPattern: `true` becomes `1`; `false` becomes `0`.
  /// - Returns: nil if bitPattern has no elements.
  init?<BitPattern: Sequence>(bitPattern: BitPattern)
  where BitPattern.Element == Bool {
    guard let integer: Self = (
      bitPattern.reduce( { $0 ? 1 : 0 } ) { $0 << 1 | $1 }
    ) else { return nil }

    self = integer
  }
}
if let lightStatesInteger = Int(bitPattern: lightStates) {
  _ = String(lightStatesInteger, radix: 0b10)
}