Yanıtlar:
İmzalar birbirlerinden farklıysa, bir işlevin birden çok imzası olabilir. Varsayılan değerleri sağlamak için bunu kullanabilirsiniz.
(defn string->integer
([s] (string->integer s 10))
([s base] (Integer/parseInt s base)))
Varsayımın falseve nilher ikisinin de değer dışı olarak kabul (if (nil? base) 10 base)edildiğini (if base base 10), kısaltılabileceğini veya daha ileriye götürülebileceğini unutmayın (or base 10).
recursadece aynı arity üzerinde çalışıyor. yukarıda java.lang.IllegalArgumentException: Mismatched argument count to recur, expected: 1 args, got: 2, compiling:
(string->integer s 10)mu (yani )?
restClojure 1.2 [ ref ] sürümünden bu yana argümanları harita olarak da yok edebilirsiniz . Bu, işlev bağımsız değişkenleri için varsayılanları adlandırmanıza ve sağlamanıza olanak tanır:
(defn string->integer [s & {:keys [base] :or {base 10}}]
(Integer/parseInt s base))
Şimdi arayabilirsin
(string->integer "11")
=> 11
veya
(string->integer "11" :base 8)
=> 9
Bunu burada eylem halinde görebilirsiniz: https://github.com/Raynes/clavatar/blob/master/src/clavatar/core.clj (örneğin)
Bu çözüm, orijinal çözümün ruhuna daha yakın , ancak marjinal olarak daha temiz
(defn string->integer [str & [base]]
(Integer/parseInt str (or base 10)))
Bir Benzer bir model kullanışlı kullanımları olabilir orkombinelet
(defn string->integer [str & [base]]
(let [base (or base 10)]
(Integer/parseInt str base)))
Bu durumda daha ayrıntılı olsa da, varsayılanların diğer girdi değerlerine bağlı olmasını istiyorsanız yararlı olabilir . Örneğin, aşağıdaki işlevi düşünün:
(defn exemplar [a & [b c]]
(let [b (or b 5)
c (or c (* 7 b))]
;; or whatever yer actual code might be...
(println a b c)))
(exemplar 3) => 3 5 35
Bu yaklaşım, adlandırılmış argümanlarla (M. Gilliar'ın çözümünde olduğu gibi) çalışacak şekilde kolayca genişletilebilir :
(defn exemplar [a & {:keys [b c]}]
(let [b (or b 5)
c (or c (* 7 b))]
(println a b c)))
Veya daha fazla füzyon kullanarak:
(defn exemplar [a & {:keys [b c] :or {b 5}}]
(let [c (or c (* 7 b))]
(println a b c)))
or
orfarklıdır :orçünkü orfarkını bilmiyor nilve false.
Göz önünde bulundurmak isteyebileceğiniz başka bir yaklaşım daha var: kısmi işlevler. Bunlar, muhtemelen işlevler için varsayılan değerleri belirlemenin daha "işlevsel" ve daha esnek bir yoludur.
Baştaki parametre (ler) olarak varsayılan olarak sağlamak istediğiniz parametre (ler) i içeren bir işlev oluşturarak başlayın (gerekirse):
(defn string->integer [base str]
(Integer/parseInt str base))
Bu, Clojure'un sürümü partial"varsayılan" değerleri yalnızca işlev tanımında göründükleri sırada sağlamanıza izin verdiği için yapılır . Parametreler istendiği gibi sıralandıktan sonra, işlevi kullanarak işlevin "varsayılan" bir sürümünü oluşturabilirsiniz partial:
(partial string->integer 10)
Bu işlevi birden çok kez çağrılabilir hale getirmek için, şunu kullanarak bir var'a koyabilirsiniz def:
(def decimal (partial string->integer 10))
(decimal "10")
;10
Şunları kullanarak da bir "yerel varsayılan" oluşturabilirsiniz let:
(let [hex (partial string->integer 16)]
(* (hex "FF") (hex "AA")))
;43350
Kısmi fonksiyon yaklaşımının diğerlerine göre bir önemli avantajı vardır: fonksiyonun tüketicisi , fonksiyon tanımını değiştirmeye gerek kalmadan fonksiyonun üreticisi yerine varsayılan değerin ne olacağına hala karar verebilir . Bu, varsayılan işlevin istediğim şey olmadığına karar verdiğim örnekte gösterilmiştir .hexdecimal
Bu yaklaşımın bir başka avantajı, varsayılan işleve daha açıklayıcı ve / veya farklı bir kapsam (var, yerel) olabilecek farklı bir ad (ondalık, onaltılık vb.) Atayabilmenizdir. Kısmi işlev, istenirse yukarıdaki bazı yaklaşımlarla da karıştırılabilir:
(defn string->integer
([s] (string->integer s 10))
([base s] (Integer/parseInt s base)))
(def hex (partial string->integer 16))
(Bu yanıtın üst kısmında verilen nedenlerle parametrelerin sırası tersine çevrildiğinden, bunun Brian'ın yanıtından biraz farklı olduğunu unutmayın)
Ayrıca https://clojuredocs.org/clojure.core/fnil adresine de bakabilirsiniz.(fnil)
(recur s 10)kullanmak daha iyi olur . Bu, gelecekte işlevi yeniden adlandırmayı kolaylaştırır. Bu durumlarda kullanmamak için herhangi bir sebep bilen var mı ?recurstring->integerrecur