Skip to content

Instantly share code, notes, and snippets.

@dexterous
Last active January 6, 2016 21:30
Show Gist options
  • Save dexterous/1327614 to your computer and use it in GitHub Desktop.
Save dexterous/1327614 to your computer and use it in GitHub Desktop.
The truth about dynlangs
#!/usr/bin/env lein-exec
(println (group-by (fn [e] (if e true false)) [true, false, -1, 0, 1, 2, nil, (new Object), [], #{}, '(), [(new Object)], {}, {:foo, (new Object)}]))
;;{true [true -1 0 1 2 #<Object java.lang.Object@4d8ce14a> [] #{} () [#<Object java.lang.Object@48ff4cf>] {} {:foo #<Object java.lang.Object@7114460>}], false [false nil]}
#!/usr/bin/env groovy
@groovy.transform.ToString
class CustomTruth {
def value
def asBoolean() { value }
}
println([true, false, -1, 0, 1, 2, null, new Object(), [], [new Object()], [:], [foo: new Object()], new CustomTruth(value: true), new CustomTruth(value: false)].groupBy { it ? true : false })
//[true:[true, -1, 1, 2, java.lang.Object@2e716cb7, [java.lang.Object@18987a33], [foo:java.lang.Object@427eb6e2], CustomTruth(true)], false:[false, 0, null, [], [:], CustomTruth(false)]]
#!/usr/bin/env python
from collections import defaultdict
from operator import truth
def returning(a, do):
do(a)
return a
def group_by(key, iterable):
return dict(reduce(lambda a, e: returning(a, lambda x: x[key(e)].append(e)), iterable, defaultdict(list)))
class MethodStub:
def __init__(self, val): self.val = val
def __repr__(self): return '%s(%s)' % (self.__class__.__name__, self.val)
class LenTruth(MethodStub):
def __len__(self): return self.val
class NonZeroTruth(MethodStub):
def __nonzero__(self): return self.val
def integers_upto(n):
while n > 0:
yield n
n = n - 1
print group_by(truth, [True, False, -1, 0, 1, 2, None, object(), '', (), [], (i for i in range(0)), integers_upto(0), 'a string', (object()), [object()], (i for i in range(2)), integers_upto(2), {}, {'foo': object()}, LenTruth(0), NonZeroTruth(False), LenTruth(1), NonZeroTruth(True)])
#{False: [False, 0, None, '', (), [], {}, LenTruth(0), NonZeroTruth(False)], True: [True, -1, 1, 2, <object object at 0x7fc96b9f4090>, <generator object <genexpr> at 0x7fc96ba13780>, <generator object integers_upto at 0x7fc96ba135f0>, 'a string', <object object at 0x7fc96b9f40a0>, [<object object at 0x7fc96b9f40b0>], <generator object <genexpr> at 0x7fc96ba134b0>, <generator object integers_upto at 0x7fc96ba135a0>, {'foo': <object object at 0x7fc96b9f40c0>}, LenTruth(1), NonZeroTruth(True)]}
#!/usr/bin/env ruby
p [true, false, -1, 0, 1, 2, nil, Object.new, [], [Object.new], {}, {:foo=> Object.new}].group_by { |e| e ? true : false }
#{true=>[true, -1, 0, 1, 2, #<Object:0x9931579>, [], [#<Object:0x5abd09e8>], {}, {:foo=>#<Object:0x1414627a>}], false=>[false, nil]}
@dexterous
Copy link
Author

An alternative implementation of truth.py (fundamentally just the group_by implementation) can be found at https://gist.github.com/1327932 courtesy of @dnene

@dexterous
Copy link
Author

Personally I was kind'a disappointed at Groovy's truth coersion being so lenient. I really liked Ruby and Clojure's strict rule of false and nil being the only falsy values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment