On Monday, November 13, 2017 at 11:40:10 AM UTC-6, Stephen Feyrer wrote: > > Updating subject to make it make more sense, hopefully. > > On 13 November 2017 at 14:15, Alex Miller <a...@puredanger.com> wrote: > >> Regarding the title, this is incorrect. Map keys are not functions; >> keywords are functions that take an associative data structure and will >> look themselves up in it. So, the premise here is not even correct to start. >> >> Usually we prefer to work by starting from a problem and consider >> alternatives, but as you state below, you don't have a problem in mind. >> >> > Normally, I don't offer possible solutions when I enquiring about a > problem. Maybe with forethought context and or constraints... > > This is more of a solution (based on a lack of understanding) without a > problem. If you like the problem I'm hoping to address is to reduce my > lack of understanding. > > > >> >> On Monday, November 13, 2017 at 3:49:41 AM UTC-6, Stephen Feyrer wrote: >>> >>> Hi there, >>> >>> This is possibly a silly question (and may have been asked before but I >>> couldn't find earlier examples) so here it goes. >>> >>> >> >>> Get the nth element of the vector >>> >>> user=> (3 [1 "is" the :same]) >>> :same >>> >>> >>> >> Note that you can do something similar now with: >> >> ([1 "is" the :same] 3) >> > > This works for me :) >
The important thing here is that thing being invoked is the vector (which is a custom Clojure type that implements the IFn invocation interface). Putting arbitrary types in the operator position of a call is where the issues lie. > > >> >> Whereas in the situation with maps, keywords (a specific common key type) >> are functions, here you are implying that anything could implicitly be >> invokable as a lookup function on an associative data structure. This >> doesn't make a lot of sense to me and would undoubtedly have performance >> effects. Maybe there is some case like `(map 1 [[:a 0] [:b 1] [:c 2]])` >> where this would make sense. But this doesn't make sense for all indexed >> data structures, just those indexed by longs. Layering invocability on >> longs would require special handling in the compiler (Keywords are a type >> that embeds this by implementing IFn naturally, so it's not a special case). >> >>> >>> Get the nthiness of an element in the vector >>> >>> user=> (::same [1 "is" the :same]) >>> 3 >>> >>> >> This is something completely different - a linear search for a match. >> Clojure has considered and rejected making linear searching easier multiple >> times. It's almost always a sign that you are using the wrong data >> structure in the first place and should be using a hashed data structure >> instead. There is no chance we would do something like this. >> > > Perhaps, I'm not understanding vectors properly. A vector is a set of > ordered elements, I think that is right. > More importantly, vectors are indexed (you can look up an element by index) and this property is extended to make vectors associative where you associate a key (the index) with the value (the element at the index). This operation is fast (what we call "effectively constant" time as it's O(log32(n)) which is a function that grows very slowly compared to O(n)). > Then at some point you might want to get one of those elements picking it > out by its index. Equally, this is probably where I've lost the plot you > might want to know where in a vector your element is residing. > These two sentences are talking about two different kinds of operations, but I think you believe they are the same kind of operation. The first sentence is a fast (effectively constant time) lookup by key (the index). The second sentence is a slow (linear time) search through the vector. Generally, if your program is doing a lot of the latter, you should change it so it does more of the former. :) > > Get the nthiness of an element in the vector >>> >>> user=> (:1 [1 "is" the :same]) >>> (0 2) >>> >>> >> I don't even understand what is intended here. >> >> > You've already covered this above but I'll explain what I meant (just to > be clear). > > user=> (nth [1 "is" the :same] 2) > 1 > > And > > user=> ([1 "is" the :same] 0) > 1 > > Therefore, a lookup of value '1' would return the indices for both > occurrences in a list. > Both cases here are the fast lookup operation - both of these can go pluck out the i-th element without examining any other elements, just like you were instead doing: (nth {0 1, 1 "is", 2 the, 3 :same} 0) or ({0 1, 1 "is", 2 the, 3 :same} 0) > > > >> Taking things further into the realms of really you should have stopped >>> there! >>> >>> Get the these element of the vector >>> >>> user=> ((1 3) [1 "is" the :same]) >>> ("is" :same) >>> >>> >>> Just for fun I tried: >>> >>> user=> ((:this :the) {:this "is" :the "same"}) >>> >>> >>> >>> >>> NullPointerException user/eval786 (NO_SOURCE_FILE:1) >>> >>> >>> > The thought here was the same as the above only with a list of invocations > to return a list of values. > > > >> >>> I may be barking up the wrong tree or possibly just barking... I hope >>> what I'm asking makes some sort of sense. >>> >> >> Not particularly. >> >> >>> By way of apology to the reader, when I began writing this question it >>> was ill thought out and seemed a lot simpler. As a disclaimer, I can't >>> think of direct examples how this would improve readability or such or even >>> necessarily be useful. >>> >> >> Seems like that should have been a sign. :) >> > > That was one yes, the other was the suggestion that this might be a silly > question. In hindsight, I think the question I'm looking at now maybe > quite different to the one I thought I had when I started. > > At this point I think I would ask, how do you find the indices of elements > within a vector for a certain value? > In general, this requires examining each element till you find them (a linear-time search). > Or perhaps, should you be needing to obtain the positional component of a > value, what would be the correct data structure to use? > This is a better question. :) I'd recommending using a data structure that allows you to do a constant time lookup, and avoid linear searches if possible. That is usually a hashed data structure like a map or set (or occasionally a vector if the values happen to be index-like). > For example, you're given a list (in an unspecified form) of horses from a > race in their finishing order. > > Carrot > Colonel Mustard > Sugar > > Binky > > Mr. Ned > Go Faster Stripes > Stick > Scary Monster Not Technically A Horse > > Binky > > > Then (using Clojure) you're asked to get the positional value of 'Go > Faster Stripes' or 'Binky'? > If you don't have control over the input, then you will need to walk in a linear search, either leveraging the natural indexes (probably with an explicit loop/recur), or using your own as you go (using something like keep-indexed). Or if checking for any match at all, something like (some #{"Go Faster Stripes" "Binky"} finishes). But really, I'd endeavor to instead take as input a map like this: {"Carrot" 1, "Colonel Mustard" 2, ...} and then just look up the answer without needing to examine every horse. Without more context on use, it's hard to suggest precise replacements. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.