2016-05-31 14 views
1

Ich konnte die Absicht von einige nicht verstehen? Funktion in Clojure.Warum einige? gibt true zurück, wenn es false als Parameter in Clojure annimmt?

Ich brauche eine Funktion (eingebaut), die false zurückgibt, wenn es dauert (Null oder falsch). Hier

ist das Beispiel:

(some? "1") 
=> true 

(some? nil) 
=> false 

(some? false) ;;Which is odd!! 
=> true 
+0

Das Interessante daran ist, dass 'Null' tut genau das gleiche wie 'einige?'. – S4M

+1

@ S4M Nein, tut es nicht. '(nil? nil)' gibt 'true' zurück, während' (einige? nil) ''false' zurückgibt. –

+0

@PiotrekBzdyl Sie haben recht, es ist '(nicht (nil? False))', die 'true' und' (not (nil? Nil)) zurückgibt, die 'false' zurückgibt. – S4M

Antwort

5

Überprüfen Sie die Dokumentation von some?:

(some? x) 

Returns true if x is not nil, false otherwise. 

false ist definitiv nicht nil so (some? false) kehrt true.

Es ist eine Ergänzung von nil?

(= (some? x) (not (nil? x)) 

Als @delta vorgeschlagen, Sie boolean verwenden können, um zu überprüfen, ob etwas nicht nil oder false ist.

+5

Ich würde hinzufügen, dass semantisch 'einige?' Völlig seinem Titel entspricht, was bedeutet, dass es überprüft, dass der Wert * etwas * ist, während nur 'Null' als * nichts * in clojure betrachtet wird. Offensichtlich ist 'falsch 'etwas. Es gibt also nichts Seltsames an diesem Verhalten. – leetwinski

+0

@leetwinski Einverstanden, jedoch sind Leute oft verwirrt, weil in 'einigen' logischen wahren Werten (d. H. Nicht falsch), die durch das Prädikat zurückgegeben werden, als eine Übereinstimmung behandelt werden. Auch hier ist die Benennung konsistent und sagt: "Gib mir ein Element, das zum Prädikat passt". Auch die Benennung von 'some->' ist konsistent, was wiederum false als 'some?' Behandelt. –

+1

In der Tat .. Ich würde es lieber 'etwas nennen?' Wirklich .. aber gut .. Rich weiß besser) – leetwinski

0

Die effektive source for some? ist

(defn some? [x] (not (nil? x))) 

Es wäre besser not-nil? genannt werden, die Tupelo Angebote als Alias.

Wie andere gesagt haben, ist die Funktion, die Sie suchen, boolean.

1

Noch einfacher, verwenden IF:

user=> (if "1" true false) 
true 
user=> (if nil true false) 
false 
user=> (if false true false) 
false 
1

Zwar gibt es mehr als einen Weg, um zu tun, was Sie fragen, ich denke, die einfachste die truthy? & falsey? Funktionen zu verwenden ist from the Tupelo library:

Die Wahrheit ist nicht mehrdeutig

Clojure heiratet die Welten von Java und Lisp. Leider haben diese zwei Welten unterschiedliche Vorstellungen von Wahrheit, so akzeptiert Clojure sowohl falsche und null als falsch. Manchmal jedoch wollen Sie logische Werte in wörtlichen wahr oder falsch Werte zwingen, so bieten wir eine einfache Art und Weise , das zu tun:

(truthy? arg) 
    Returns true if arg is logical true (neither nil nor false); 
    otherwise returns false. 

(falsey? arg) 
    Returns true if arg is logical false (either nil or false); 
    otherwise returns false. Equivalent to (not (truthy? arg)). 

Seit truthy? und falsch?sind Funktionen (anstelle von Sonderformen oder Makros), können wir sie als Argument verwenden können an jedem anderen Ort zu filtern oder dass eine höhere Ordnung Funktion erforderlich ist:

(def data [true :a 'my-symbol 1 "hello" \x false nil]) 

(filter truthy? data) 
;=> [true :a my-symbol 1 "hello" \x] 
(filter falsey? data) 
;=> [false nil] 

(is (every? truthy? [true :a 'my-symbol 1 "hello" \x])) 
(is (every? falsey? [false nil])) 

(let [count-if (comp count keep-if) ] 
    (let [num-true (count-if truthy? data) ; <= better than (count-if boolean data) 
     num-false (count-if falsey? data) ] ; <= better than (count-if not  data) 
    (is (and (= 6 num-true) 
       (= 2 num-false)))))) 
+0

Ich denke, die erforderliche Funktion ist "truthy?", Nicht "falsch?". – Thumbnail

+0

Wenn man bedenkt, dass die logische Wahrheit in allen konditionalen Formen von der Sprache selbst respektiert wird, würde ich diese Prädikate als die beste Lesbarkeit im besten 99.99% der Zeit betrachten. "falsch?" ist genau "nicht". IDK das Impl von keep-if, aber bedenke idiomatisch '(filter identity data)', '(filter not data)' - Ich werde dies nicht ablehnen, da dies ein gutes Beispiel für das Hinzufügen von Lesbarkeit durch kontextuelle Neudefinition im SICP-Stil ist besser, wenn Sie hier die Ein-Zeilen-Implementierung zur Verfügung stellen, anstatt sie zu Lernzwecken zu verknüpfen. –

+0

Sie haben Recht, dass der Hauptzweck Lesbarkeit ist, so dass der Text des Codes wörtlicher sagt, was er zu tun beabsichtigt. Dies ist besonders hilfreich für Leute, die Clojure lernen. Die Verwendung von 'not' ist nicht zu schwer zu lesen, aber es gibt keine umgekehrte Analogie zu' truthy? '. Natürlich kann man 'if' nicht verwenden, da es sich um eine spezielle Form handelt. Daher ist der dünne Wrapper "truthy" und "false", um zu "true"/"false" zu zwingen. Während 'boolean' funktioniert, benutzte ich Clojure für 2 Jahre, bevor ich es jemals bemerkte! Selbst dann erscheint es in den Dokumenten als "Cast", bis Sie das gesamte Verhalten getestet und überprüft haben. –