JavaScript İçinde Currying – JSManifest

JavaScript İçinde Currying – JSManifest

köri işlevlerle çalışırken gelişmiş bir tekniktir ve birden çok programlama dilinde kullanılır.

Alan bir işlevi bozduğunuzda çoklu argümanlar içine yuvalama işlevleri dizisisenin bir köri. Her yuvalama işlevi, işlev için sonraki bağımsız değişkenlere sahip olmayı bekler.

Köri işlevi her zaman bir yeni fonksiyon her çağrı için tüm argümanlar alınana kadar. Bu argümanlar, körlüğün ömrü boyunca yaşayabilir. kapatma ve tümü son işlevi yürütmek için kullanılacaktır.

Çok temel bir örnek şöyle görünebilir:

function combineWords(word) {
  return function(anotherWord) {
    return function(andAnotherWord) {
      return `${word} ${anotherWord} ${andAnotherWord}`
    }
  }
}

Bunu kullanmak için, son işleve ulaşana kadar işlevi birkaç kez çağırabilirsiniz:

const result = combineWords('hello,')('good')('morning')
console.log(result)

Yani ne oluyor combineWords curried bir fonksiyondur (belli ki) ve serideki bir sonraki fonksiyonu çalıştırmadan önce bir kelimenin verilmesini bekler. bağlayabilirsin 'wow!' ile combineWords ile başlayan diğer selamlamaları oluşturmak için yeniden kullanın. 'wow!':

let greet = combineWords('wow!')
greet = greet('nice')

console.log(greet('jacket'))
console.log(greet('shoes'))
console.log(greet('eyes'))
console.log(greet('socks'))
console.log(greet('hat'))
console.log(greet('glasses'))
console.log(greet('finger nails'))
console.log(greet('PS3'))
console.log(greet('pet'))

Kavramı anlamak biraz zorsa, şu şekilde okumayı deneyin:

Anne, pişirmeden önce 4 yumurtanın (tartışmaların) hepsini bekliyor ve 4 çocuğunun her biri birer birer birer tane taşıyacak.

function Egg() {...}


function prepareCooking(cook) {
  return function(egg1) {
    return function(egg2) {
      return function(egg3) {
        return function(egg4) {
          return cook(egg1, egg2, egg3, egg4)
        }
      }
    }
  }
}

const cook = function(...eggs) {
  api.turnOnStove()
  api.putEggsOnTop(...eggs)
  api.pourSalt()
  api.serve()
  console.log('served children')
  return 'served'
}

const start = prepareCooking(cook)

let collect = start(new Egg())
collect = collect(new Egg())
collect = collect(new Egg())
collect = collect(new Egg()) 


için cook çağrılacak geri çağrı, 4 yumurtanın hepsinin birbiri ardına geçirilmesi gerekiyordu, her biri çağrı için bekleyen bir sonraki işlevi önceden dolduruyordu.

Üçüncü yumurtada duracak olursanız:

let collect = start(new Egg())
collect = collect(new Egg())
collect = collect(new Egg())

O zaman son fonksiyon beklediğinden beri egg4 değerine henüz ulaşılamamıştır. collect bu işlev mi:

function prepareCooking(cook) {
  return function(egg1) {
    return function(egg2) {
      return function(egg3) {
        
        return function(egg4) {
          return cook(egg1, egg2, egg3, egg4)
        }
      }
    }
  }
}

Köriyi bitirmek için son yumurtayı toplayın:

let collect = start(new Egg())
collect = collect(new Egg())
collect = collect(new Egg())
collect = collect(new Egg())

Şimdi, her yuvalama işlevinin, köri işlevi içindeki dış kapsama tüm erişime sahip olduğunu bilmek önemlidir. Bunu bilerek, belirli durumlara göre uyarlamak için iç içe geçmiş her işlev arasında özel mantık sağlayabilirsiniz. Ama köriyi köri olarak bırakmak en iyisidir ve başka bir şey değil.

Daha gelişmiş bir köri işlevi aşağıdaki gibi görünebilir: (bir ES5 versiyonun yanı sıra bir ES6 çünkü yeni JavaScript geliştiricileri için okunması biraz zor olabilecek ES5 sözdizimini gösteren çok sayıda eski öğretici var)

ES5

function curry(fn) {
  return function curried() {
    const args = Array.prototype.slice.call(arguments)
    const done = args.length >= fn.length
    if (done) {
      return fn.apply(this, args)
    } else {
      return function() {
        const args2 = Array.prototype.slice.call(arguments)
        return curried.apply(this, args.concat(args2))
      }
    }
  }
}

…aynıdır:

ES6

const curry = (fn) => {
  return function curried(...args) {
    const done = args.length >= fn.length
    if (done) {
      return fn.apply(this, args)
    } else {
      return (...args2) => curried.apply(this, [...args, ...args2])
    }
  }
}

Bu örneği daha ayrıntılı olarak açıklayalım:

Aradığın zaman curry(fn) iç döndürecek curried çağrıldıktan sonra sonraki argümanları bekleyecek işlev. Şimdi bu iç işlevi çağırdığınızda, iki koşulu değerlendirir:

  1. Arayan, tüm argümanları karşılamak için yeterli argümanları iletti mi? fn?
  2. Yoksa hala eksik olan argümanlar var mı? fn ihtiyaçlar?

Eğer 1 numara durum buysa, o zaman ihtiyacımız olan tüm argümanlara sahibiz fn ilan edildi ve köri, çağrının döndürülmesiyle sona erecek. fn ve kendisine alınan tüm argümanları iletmek (temelde fn normalde şimdi)

Ancak, eğer 2 numara durum buysa, o zaman köri devam etmeli ve bir şekilde içimize geri dönmeliyiz. curried argümanlarını karşılayana kadar daha fazla argüman almaya devam edebilmemiz için işlev fn. kod return (...args2) => curried.apply(this, [...args, ...args2]) şimdiye kadar ortaya çıkan tüm argümanları toplar ve bu davada körü körüne devam etmek için bunları kullanır.

Önemli bir kural var:

Tüm argümanların toplanması beklenmeden önce çağrılacak fonksiyonun sabit sayıda argümanı olmalıdır. Bu, işlevin yayılmış parametrelere sahip olamayacağı anlamına gelir (ör: fn(...args))

eski:

const curry = (fn) => {
  return function curried(...args) {
    const done = args.length >= fn.length
    if (done) {
      return fn.apply(this, args)
    } else {
      return (...args2) => curried.apply(this, [...args, ...args2])
    }
  }
}


function func(...args) {
  
}

const currying = curry(func)

Çözüm

Köri yapmanın ilginç bir teknik olduğunu düşünüyorum çünkü köri yapmak diğer ileri tekniklerin oluşturulmasını da içeriyor. İlgili kapanışlar, daha yüksek dereceli işlevler ve özyineleme vardır.

Ve bu, bu yazının sonunu tamamlıyor. Umarım değerli bir şey bulmuşsundur ve gelecekte daha fazlasını arayacaksın!

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.