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 <[email protected]> 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/d/optout.