2017-01-03 4 views
0

私はインデックス値にしたいがIntを含むtupleを使用して関数から返されるとDouble.機能はDoubleを返す正常に動作しますが、私はtupleを読んだとき、私はこのエラーを取得:.flatMapを使ったSwift関数は `Double`を返すが、` tuple 'は返さないのはなぜですか?

'flatMap' produces '[SegmentOfResult.Iterator.Element]', not the expected contextual result type '(pitchClass: Int, frequency: Double)'

なぜ.flatMap私は困惑していますDoubleを返しますが、tuple.This linkflatMap(_:)arraysには意味がありますが、この問題を解消するtuplesとの接続が見つかりません。

これを解決する最良の方法は何ですか?

としては

tuningを要求

明確化画分と小数

// test pitches: rational fractions and decimal numbers 
    let tuning = ["1/1", "200.0", "5/4", "500.0", "600.0", "700.0", "1000.0", "2/1"] 

scaleFrequenciesと文字列配列は、両方の数値タイプを処理し、ダブル(すなわちfrequency)を返す関数です。

コードの初期化が含まれています。

import UIKit 

class Tuner { 

     var tuning     = [String]() 
     let tonic: Double   = 261.626 // frequency of middle C 
     var index     = -1 
     let centsPerOctave: Double = 1200.0 // mandated by Scala tuning file format 
     let formalOctave: Double = 2.0  // Double for stretched-octave tunings 

init(tuning: [String]) { 
     self.tuning     = tuning 

     var notes: (pitchClass: Int, frequency: Double) 
     notes = tuning.flatMap(scaleFrequencies) 

    // print(frequency) 

    } 



func pitchClass(pitchClass: Int, _ frequency: Double) -> Int { 
    return pitchClass 
    } 

func frequency(pitchClass: Int, _ frequency: Double) -> Double { 
    return frequency 
    } 



func scaleFrequencies(s: String?) -> (Int, Double) { 

    index     += 1 
    var frequency: Double = 0.0   
    frequency    = processNumerics(numericString: numericString) 

    return (index, frequency) 
} 
+4

'tuning'は何ですか? 'scaleFrequencies'とは何ですか? 'tuning.flatMap(scaleFrequencies)'が 'notes'に代入できるタプルを生成するのはなぜでしょうか? – jtbandes

+0

'scaleFrequencies(tuning)'のように関数に 'tuning'を渡すことを意味しましたか? – jtbandes

+0

'tuning'の各要素は' scaleFrequencies'に順に渡されます。そこから 'processNumerics'に渡され、オプションがアンラップされます(ガードとnilの融合、すなわち強制アンラッピングなし)。戻り値 – Greg

答えて

0

機能は、現在Doubleを返す正常に動作し、すでに私は必要な変数を与える、すなわちfrequency.それを変更しない方がよいです。機能を追加するための新しいクラスを作成します(つまり、周波数をMIDIキーボードのキーにマッピングします)。 あなたのご意見をいただきありがとうございます。

EDIT

問題空間を広げずにこの問題を解決する方が賢明でした。関数に引数を返す必要があるかどうかを疑問視し、代わりに使用可能な引数のみを使用して関数内部からデータをどのように表示するかを尋ねたところで、私の解決策を見つけました。溶液をaccepted answer to another postによって識別される関連する問題に対処し、他のいくつかの記事に推奨されるように実行時エラーを起こすことなく、任意の値をアンラップ(hereherehere。)

値は任意チェーンを使用してアンラップされると強制的なアンラッピングの代わりにnil coalescing。 these rulesに従って有効な数字は周波数に変換され、MIDIキーボードにマッピングされます。無効なチューニング値と、‘x’these rulesで指定されている)でマークされた音符列は、0.0 Hzの周波数を生成します。

解決策は、他の関数が呼び出されるときに返される頻度と比較される関数によって読み取られるオプションのスケール値を比較しやすくします。

Octave map 

    0 Optional("x") 
    0 : 0.0 
    1 Optional("35/32") 
    1 : 286.1534375 
    2 Optional("x") 
    2 : 0.0 
    3 Optional("x") 
    3 : 0.0 
    4 Optional("5/4") 
    4 : 327.0325 
    5 Optional("21/16") 
    5 : 343.384125 
    6 Optional("x") 
    6 : 0.0 
    7 Optional("3/2") 
    7 : 392.439 
    8 Optional("x") 
    8 : 0.0 
    9 Optional("x") 
    9 : 0.0 
    10 Optional("7/4") 
    10 : 457.8455 
    11 Optional("15/8") 
    11 : 490.54875 

それはまた再調整MIDIマップを作成する方法を示していますので、音楽アプリケーションの

MIDI map 

    Octave 0 
    0 0 0.0 
    1 1 8.942294921875 
    2 2 0.0 
    3 3 0.0 
    4 4 10.219765625 
    5 5 10.73075390625 
    6 6 0.0 
    7 7 12.26371875 
    8 8 0.0 
    9 9 0.0 
    10 10 14.307671875 
    11 11 15.3296484375 

    Octave 1 
    12 0 0.0 
    13 1 17.88458984375 
    14 2 0.0 
    15 3 0.0 
    16 4 20.43953125 
    17 5 21.4615078125 
    18 6 0.0 
    19 7 24.5274375 
    20 8 0.0 
    21 9 0.0 
    22 10 28.61534375 
    23 11 30.659296875 

    Octave 2 
    24 0 0.0 
    25 1 35.7691796875 
    26 2 0.0 

    etc 

    Octave 9 
    108 0 0.0 
    109 1 4578.455 
    110 2 0.0 
    111 3 0.0 
    112 4 5232.52 
    113 5 5494.146 
    114 6 0.0 
    115 7 6279.024 
    116 8 0.0 
    117 9 0.0 
    118 10 7325.528 
    119 11 7848.78 

    Octave 10 
    120 0 0.0 
    121 1 9156.91 
    122 2 0.0 
    123 3 0.0 
    124 4 10465.04 
    125 5 10988.292 
    126 6 0.0 

開発者はこれが役立つことがあり、他のオクターブで読み取り周波数で役立ちます。このソリューションを使用すると、標準の音楽キーボードの範囲外にある音階の音符のチューニングを指定する分数と小数からなる数値文字列をアンラップすることができます。その意味はthis siteを訪れる人には失われません。ここで

コード

Tuner.swiftある

import UIKit 

class Tuner   { 

    var tuning      = [String]() // .scl 
    var pitchClassFrequency   = Double()  // .scl 
    let centsPerOctave: Double  = 1200.0  // .scl mandated by Scala tuning file format 

    let formalOctave: Double  = 2.0   // .kbm/.scl Double for stretched-octave tunings 
    var octaveMap     = [Double]() // .kbm/.scl 
    var midiMap      = [Double]() // .kbm 

    let sizeOfMap     = 12   // .kbm 
    let firstMIDIKey    = 0    // .kbm 
    let lastMIDIKey     = 127   // .kbm 

    let referenceMIDIKey   = 60   // .kbm 
    let referenceFrequency: Double = 261.626  // .kbm frequency of middle C 

    var indexMIDIKeys    = Int() 
    var indexOctaveKeys    = Int() 
    var currentKeyOctave   = Int() 
    var index: Int     = 0 


init(tuning: [String]) { 
    self.tuning     = tuning 

// SCL file format - create frequency map of notes for one octave 
    print("Octave map") 
    print("") 
    let _       = tuning.flatMap(scaleToFrequencies) 

// KBM file format - create frequency map of MIDI keys 0-127 
    print("") 
    print("MIDI map") 
    let _       = createMIDIMap() 

    } 


func createMIDIMap()           { 

    indexOctaveKeys    = firstMIDIKey // set indexOctaveKeys to pitchClass 0 
    currentKeyOctave   = firstMIDIKey // set currentOctave to octave 0 

    for indexMIDIKeys in firstMIDIKey...lastMIDIKey { 
     let indexOctaveKeys  =  indexMIDIKeys % sizeOfMap 

     currentKeyOctave  = Int((indexMIDIKeys)/sizeOfMap) 
     let frequency   = octaveMap[indexOctaveKeys] * 2**Double(currentKeyOctave) 

     //  midiMap[i]    = octaveMap[indexMIDIKeys] * 2**Double(currentKeyOctave) 
     if indexOctaveKeys == 0 { 
      print("") 
      print("Octave \(currentKeyOctave)") 
     } 
     print(indexMIDIKeys, indexOctaveKeys, frequency) 
     } 
    } 


func scaleToFrequencies(s: String?)        { 

    var frequency: Double  = 0.0 

    // first process non-numerics. 
    let numericString   = zapAllButNumbersSlashDotAndX(s: s) 

    print(index, numericString as Any)  // eavesdrop on String? 

    // then process numerics. 
    frequency     = (processNumericsAndMap(numericString: numericString))/Double(2)**Double(referenceMIDIKey/sizeOfMap) 
    octaveMap.append(frequency) 
    print(index,":",frequency * 2**Double(referenceMIDIKey/sizeOfMap)) 
    index += 1 
    } 


func processNumericsAndMap(numericString: String?) -> Double { 
    guard let slashToken = ((numericString?.contains("/")) ?? nil), 
     let dotToken  = ((numericString?.contains(".")) ?? nil), 
     let xToken   = ((numericString?.contains("x")) ?? nil), 
     slashToken   == false, 
     dotToken   == true, 
     xToken    == false 
     else { 
      guard let dotToken = ((numericString?.contains(".")) ?? nil), 
       let xToken  = ((numericString?.contains("x")) ?? nil), 
       dotToken  == false, 
       xToken   == false 
       else { 
        guard let xToken = ((numericString?.contains("x")) ?? nil), 
         xToken   == false 
         else { 
          // then it must be mapping. 
          let frequency = 0.0 
          //      print("[x] \(frequency) Hz") 
          return frequency 
        } 
        // then process integer. 
        let frequency = processInteger(s: numericString) 
        return frequency 
      } 
      // then process fractional. 
      let frequency   = processFractional(s: numericString) 
      return frequency 
     } 
    // process decimal. 
    let frequency     = processDecimal(s: numericString) 
    return frequency 
    } 


func processFractional(s: String?) -> Double     { 
    let parts = s?.components(separatedBy: "/") 
    guard parts?.count  == 2, 
     let numerator  = Double((parts?[0])?.digits ?? "failNumerator"), 
     let dividend  = Double((parts?[1])?.digits ?? "failDenominator"), 
     dividend   != 0 
     else { 
      let frequency = 0.0 
      print("invalid ratio: frequency now being set to \(frequency) Hz") 
      return frequency 
     } 
    let frequency   = referenceFrequency * (numerator/dividend) 
    return frequency 
    } 


func processDecimal(s: String?) -> Double      { 

    let parts = s?.components(separatedBy: ".") 
    guard parts?.count  == 2, 
     let intervalValue = Double(s ?? "failInterval"), 
     let _    = Double((parts?[0])?.digits ?? "failDecimal") 
     else { 
      let frequency = 0.0 
      print("invalid cents value: frequency now being forced to \(frequency) Hz ") 
      return frequency 
     } 
    let power    = intervalValue/centsPerOctave      // value with explicit remainder 
    let frequency   = referenceFrequency * (formalOctave**power) 
    return frequency 
    } 


func processInteger(s: String?) -> Double      { 
    let frequency   = 0.0 
    print("not cents, not ratio : frequency now being set to \(frequency) Hz ") 
    return frequency 
    } 


func zapAllButNumbersSlashDotAndX(s: String?) -> String?  { 

    var mixedString = s 
    if mixedString != nil { 
     mixedString = mixedString! 
     } 
     guard var _ = mixedString?.contains("/"), 
     var _ = mixedString?.contains(".") 
     else { 
      let numberToken = mixedString 
      return numberToken 
      } 
      guard let xToken = mixedString?.contains("x"), 
       xToken == false 
       else { 
        let xToken = "x" 
        return xToken 
     } 
    let notNumberCharacters = NSCharacterSet.decimalDigits.inverted 
    let numericString = s?.trimmingCharacters(in: notNumberCharacters) ?? "orElse" 
    return numericString.stringByRemovingWhitespaces 
    } 

} 


extension String { 
var stringByRemovingWhitespaces: String { 
    return components(separatedBy: .whitespaces).joined(separator: "") 
    } 
} 


extension String { 

var digits: String { 
    return components(separatedBy: CharacterSet.decimalDigits.inverted).joined() 
    } 
} 


precedencegroup Exponentiative { 

    associativity: left 
    higherThan: MultiplicationPrecedence 

} 


infix operator ** : Exponentiative 


func ** (num: Double, power: Double) -> Double      { 
return pow(num, power) 
} 


func pitchClass(pitchClass: Int, _ frequency: Double) -> Int  { 
    return pitchClass 
} 


func frequency(pitchClass: Int, _ frequency: Double) -> Double  { 
    return frequency 
} 

ViewController.swift

import UIKit 

class ViewController: UIViewController { 

// Hexany: 6-note scale of Erv Wilson 

     let tuning = ["x", "35/32", "x", "x", "5/4", "21/16", "x", "3/2", "x", "x", "7/4", "15/8"] 


// Diatonic scale: rational fractions 
//  let tuning = [ "1/1", "9/8", "5/4", "4/3", "3/2", "27/16", "15/8", "2/1"] 

// Mohajira: rational fractions 
// let tuning = [ "21/20", "9/8", "6/5", "49/40", "4/3", "7/5", "3/2", "8/5", "49/30", "9/5", "11/6", "2/1"] 

// Diatonic scale: 12-tET 
// let tuning = [ "0.0", "200.0", "400.0", "500", "700.0", "900.0", "1100.0", "1200.0"] 


override func viewDidLoad() { 
    super.viewDidLoad() 

    _ = Tuner(tuning: tuning) 


    } 
} 
+0

元の答えはおそらく不完全だったため投票されました。うまくいけば私の編集はこれに対処します。 – Greg

関連する問題