added threading operator
Just for funzies...
ACK.
Cool man, thanks! I am going to need a bit to dig into this; a bit slammed right now. A few initial thoughts/questions:
- I am assuming this is something akin to Clojure's
->and->>macros? (I believe the equivalent in Haskell being something like composition under point-free syntaxx = f . g). Amirite on this? - A while back I did a thing on coderwall: https://coderwall.com/p/shjfkg. Basically it brings composition to
Proc. In this case you would be able to compose a bunch of lambdas and then just pass off tomap. That would be another way to go about this but suffers on the syntax side.
Again, just want to clarify the purpose here. I like the concept a lot just want to make sure we are adding the right thing in the right place.
Haha - I'm not sure if it's "the right thing in the right place" as much as me just screwing around.
Yeah - just like threading in Clojure - except that each intermediate value is an Option as well, meaning that any method in the threading could potentially return a nil, producing a NoneClass, so that the rest of the operations won't fail.
I've thought about doing something like this before...but maybe make it less haskelly and amenable to enumerables, like:
# anarray could be empty, but if it has at least one element,
# then the block will be called with it
Option(anarray).if_first { |one| ... }
# or, alternately something like
Option(anarray).if_not(:empty?) { |a| ... }
# and then allow for threading per element
Option([" 1 ", " 2 ", " 3 "]).thread(:strip, :to_i, :next)
# => [2,3,4]
# which is way prettier and efficient than
[" 1 ", " 2 ", " 3 "].map(&:strip).map(&:to_i).map(&:next)
# and at least way prettier than
[" 1 ", " 2 ", " 3 "].map { |i| i.strip.to_i.next }
# PLUS if any of the intermediate method calls returns nil, then you still get a result, like
Option([" 1 ", " 2 ", " 3 "]).thread(:strip, :make_a_nil, :to_i, :next)
#=> [<NoneClass instance>, <NoneClass instance> <NoneClass instance>]
Ok, I see where you are going with the Enumerable integration but I don't think that is something I would want to add to Option. I think maybe a companion lib that patches a few methods in to Enumerable might be interesting:
def lift_option
map { |v| Option(v) }
end
or
def first_option
Option(first)
end
def last_option
Option(last)
end
As for the proposed feature itself, I want to add it but first a few questions/requests:
- A complete failure on my part for not mentioning it in the contribution guidelines but could you just add some coverage specs for both Some and None in spec/option_spec.rb? Nothing crazy, I am just looking for the fact that the 2 states of the Option are doing 2 different things.
- The name.
thread(although technically thread is just a nickname for the->macro) is fine in clojure because you you deal with higher-level concurrency abstractions but I fear some ambiguity in the ruby world (asThreadis pretty much it wrt to concurrency). What do you think of either 'weave' or 'sequence'? - Not super important but I would be partial to
Some#threadimplemented as a recursive call to eithermaporflat_mapfollowed by the tail call tothread. Not a biggie. I'll still take it without this.
Anyways, thanks for the work and let me know what you think about item number 2.