Yea I agree with you that multiple dispatch can achieve the same thing and 
much better (such a lovely feature).

But there is a problem - consider:

type Dequeue ... end
type Last end
type First end
getindex(d::Dequeue, ::Last) = last(d)
getindex(d::Dequeue, ::First) = first(d)
pop!(d::Dequeue, ::Last) = pop!(d) # removes and returns last element
pop!(d::Dequeue, ::First) = shift!(d) # removes and returns first element
pop!(d::Dequeue, index::Int) = splice!(d) # removes and returns element at 
index x


   - My types Last / First can clash with types I have defined elsewhere.
   - I want to do [ dequeue[Last] ] instead of [ dequeue[Last() ]

How can I go around these ?

Dne čtvrtek 26. května 2016 21:23:32 UTC+2 Matt Bauman napsal(a):
>
> So, if I understand correctly, the problem you're trying to solve is that 
> A[end] lowers to getindex(A, endof(A)), but you want to know that the index 
> is the last one since you can implement a more efficient algorithm in that 
> case.
>
> Making getindex a macro won't solve this problem, so lets set aside that 
> discussion.  But there may be a solution for you here.  You can try using a 
> special index type that specifically refers to the number of indices from 
> the end.
>
> immutable BackwardsIndex <: Integer
>     i::Int
> end
>
> Now simply add `getindex(::YourType, ::BackwardsIndex)` method that 
> traverses the dequeue backwards.  `x[BackwardsIndex(1)]` then refers to 
> your last element with O(1) complexity. That's pretty verbose, but here's 
> what you can try: make `endof(::YourType) = BackwardsIndex(1)`.  Now 
> `A[end]` is O(1) complexity.  This won't work for AbstractArray subtypes, 
> but I think it should work for other custom indexable types.
>
> You can even add primitive arithmetic to the BackwardsIndex type to 
> support things like `A[end-1]`, but anything more than that becomes 
> complicated fast.  What's `x[end÷2]`?  Or worse: `x[rand(2:end-1)]`?  These 
> are the same challenges that a syntax-level change would rapidly run into.
>
> Matt
>
> On Thursday, May 26, 2016 at 2:45:34 PM UTC-4, Stefan Karpinski wrote:
>>
>> The difference is that a symbol is a value but `end` is not a value. If 
>> you can write 
>>
>> v[:foo]
>>
>>
>> then you should also be able to do this:
>>
>> x = :foo
>> v[x]
>>
>>
>> This precludes doing the lookup at compile time – except as an 
>> optimization. That argument doesn't apply to `end` since the `end` keyword 
>> is purely syntactic – trying to assign `end` to a variable is just a syntax 
>> error:
>>
>> x = end
>>
>> v[x]
>>
>>
>> Lowering things to macro calls is sometimes effective – we do this for 
>> non-standard string literals, for example – but it should be done as 
>> sparingly. In this case, the only thing that you're going to accomplish 
>> with this approach is to make a feature that's thoroughly broken. For 
>> example, by having v[:foo] do one thing while `x = :foo; v[x]` does 
>> something completely different.
>>
>> On Thu, May 26, 2016 at 2:31 PM, Ford Ox <[email protected]> wrote:
>>
>>>
>>>
>>> Dne čtvrtek 26. května 2016 18:03:50 UTC+2 Yichao Yu napsal(a):
>>>>
>>>> > Because it is done at compile time, where you can even decide to call 
>>>> > completely different function. See 
>>>> > dequeue = ..... 
>>>> > dequeue[:first] # is replaced with different function than dequeue[1] 
>>>> > dequeue[:last] # is replaced with different function than 
>>>> dequeue[end] ( 
>>>> > O(1) vs O(n) ) 
>>>>
>>>> I don't see what you mean by compile time. You cannot dispatch on the 
>>>> symbol at compile time. If you use syntax level rewrite, there's no 
>>>> point of using symbol either. 
>>>>
>>>  
>>> What do you mean by syntax level. Why there is no point for using symbol 
>>> if that's the case?
>>>  
>>>
>>>>
>>>> > 
>>>> > Because you can define your own syntax. The :middle was just stupid 
>>>> example 
>>>> > to show you, that you can decide on your own symbol based on 
>>>> collection you 
>>>> > are working with ( say there is collection which when accessing 
>>>> middle has 
>>>> > different complexity than accessing other elements). 
>>>>
>>>> You can easily do this by defining your own token. Misusing the symbol 
>>>> syntax isn't the right way to go. 
>>>>
>>>
>>> Yeah, I also feel that using symbol is not the right approach, but I 
>>> couldn't think about any other simpler way of doing that. 
>>> Can you show me what do you mean by token?
>>>  
>>>
>>>>
>>>> > 
>>>> > Of course you can do arithmetics with this approach. 
>>>>
>>>> No you can't. Not in a way that you can overload it for different types 
>>>> anyway. 
>>>>
>>>> >> Which is what make the way you propose unsatisfying. 
>>>> >> 
>>>> > 
>>>> > Are you talking about [ FIRST = :first ]? 
>>>> > If so, I could argue about this since you can't also do [ LAST = end 
>>>> ] 
>>>> > The only difference is that [ LAST = end ] throws error at compile 
>>>> time. 
>>>>
>>>> The difference is that `end` is a keyword. And symbol literal is not. 
>>>>
>>> Which is intended and its fine.
>>> The problem is that user won't know, what symbols should he use, unless 
>>> he checks the docs, which is not nice. 
>>>
>>
>>

Reply via email to