Julia: Renomear `shift!` E `unshift!`?

Criado em 27 set. 2017  ·  59Comentários  ·  Fonte: JuliaLang/julia

Conforme mencionado no slack há alguns dias, unshift! pode ser herdado, mas é um nome razoavelmente pobre IMHO. Como pré-1.0 é a hora de consertar essas coisas, que tal?

Já que prepend foi retirado, que tal unshift! -> pushfront! e shift! -> popfront! ?

Comentários muito úteis

Outra ideia: push/pop!(first, x, ...) e push/pop!(last, x, ...) .

Teoricamente, essa sintaxe generaliza bem para coisas como pop!(min, x) .

Todos 59 comentários

Poderíamos fazer uma renomeação total dessas funções:

| velho | novo |
| ----- | ----- |
| push! | rpush! |
| pop! | rpop! |
| unshift! | lpush! |
| shift! | lpop! |

Ou uma palavra-chave esquerda / direita (início / fim? Primeiro / último?) Se os problemas de desempenho puderem ser resolvidos

Esquerda e direita parecem um pouco ambíguos; talvez a frente / verso de @c42f ou algo semelhante ficasse mais claro?

Não tenho certeza se a frente e o verso são mais claros do que a esquerda e a direita. Claro, para a terminologia esquerda / direita é um pouco lamentável imprimirmos vetores verticalmente, mas frente / verso não são melhores nesse aspecto.

Ah, e já usamos l e r para esquerda e direita nas reduções, então há precedentes - a menos que queiramos alterá-los também.

Não tenho certeza se a frente e o verso são mais claros do que a esquerda e a direita.

Eu também não tenho certeza. front associa-se a índices mais baixos (como Base.front ) e back com índices mais altos em minha mente, mas tenho certeza de que esse tipo de associação varia.

Talvez ideias melhores: head - tail e first - last parecem distintamente menos ambíguas, dados seus significados preexistentes?

Os nomes hpush! , hpop! , tpush! e tpop! não são ruins. No entanto, já associamos esquerda e direita com a ordem de matrizes em foldl e foldr , etc. Na verdade, uma vez que esses têm l e r no final, os nomes análogos são pushl! , popl! , pushr! e popr! que eu meio que gosto :)

Das opções até agora para renomear todas as quatro funções, as versões com sufixo pushl! , popl! , pushr! e popr! parecem melhores para mim.

No entanto, tenho algumas reservas sobre renomear push! e pop! . Por exemplo, considere enviar e enviar para uma fila prioritária. Neste caso não há "direita" e "esquerda", há apenas uma ordem natural e uma estrutura de dados que retorna o menor / maior elemento. Há também a versão de pop! que pega uma chave para ser usada com um dicionário como estruturas de dados, e popr! também não faria muito sentido como verbo nesse caso.

Acho que push! e pop! podem ficar e ser usados ​​por PriorityQueues. Eles também podem apenas apelidar de pushr! e popr! para Arrays.

Eu amo shift! & unshift! , é o mesmo com javascript. por favor reserve isto!

Até agora, eu gosto mais da sugestão do primeiro post.

Acho bom usar os nomes push*! e pop*! para enfatizar a semelhança entre as variantes e para que as variantes possam ser encontradas facilmente completando a tabulação. (Eu gosto da sugestão de sufixo r e l .)

-2 a r e l terminologia. Os nomes são um pouco feios e existem 4 deles. Eu preferiria apenas renomear shift e unshift como o OP sugere. Mas também sinto que shift e unshift são usados ​​amplamente o suficiente para que possamos simplesmente mantê-los. Seria lamentável introduzir termos que ninguém mais usa para operações tão comuns.

O vetor push_front , portanto, há algum precedente para isso.

Presumo que os nomes existentes podem ser rastreados até shift embutido em sh , e presumivelmente perl pegou isso e inventou unshift (http://www.perlmonks.org /? node_id = 613144) Outras linguagens (php, javascript, ...?) seguiram, então há muitos precedentes.

Eu prefiro palavras em inglês adequadas ... :) ( unshift está no OED que data de 1972.)

ou pelo menos mencione shift! & unshift! no documento de pop! & push! :

help?> pop!
search: pop! popdisplay apropos deepcopy precompile __precompile__ peakflops promote_type
also see: `shift!` `unshift!` `push!`

  pop!(collection, key[, default])

  Delete and return the mapping for key if it exists in collection, otherwise return default, or
  throw an error if default is not specified. 

Outra ideia: push/pop!(first, x, ...) e push/pop!(last, x, ...) .

Teoricamente, essa sintaxe generaliza bem para coisas como pop!(min, x) .

ou pelo menos mencione shift! & unshift! no documento de pop! & push! :

Relacionado a # 23789

Ideia legal, @TotalVerb!

Ou mesclar com splice! / insert! , com first e last como pseudo-índices?

Outra ideia: push / pop! (Primeiro, x, ...)

Ah o quê? Ok, esta é uma ideia realmente criativa :-)

Parece muito estranho usar as funções first e last puramente como sintaxe, ao invés de ter algo a ver com o código real dentro delas. É ótimo, mas não tenho certeza se esse tipo de coisa deve ser incentivado no ecossistema, pois pode levar a complicações estranhas. Por exemplo, se você sempre quis renomear funções que estavam sendo usadas como sintaxe, o que fazer? Admitidamente nada provável para first e last , mas ainda assim.

Eu tenho que dizer, por mais legal que eu ache essa ideia - ela me lembra a ideia de @mbauman de usar funções de redução na indexação, como em X[mean, :, sum] - eu acho que é muito sofisticada para uma operação tão fundamental. Acho que as opções que sou a favor neste momento são:

  1. Deixe as coisas como estão - duvidosas como são "mudar" e "não mudar", elas são bastante padronizadas.
  2. Renomeie shift! e unshift! para popl! e pushl! .
  3. Além de 2, renomeie pop! e push! para popr! e pushr! .
  4. Além de 3, faça pop! e push! aliases para popr! e pushr! .

Estou basicamente entre 1 e 2, mas há algum apelo para 3 e 4 também.

Acho que 1) faz muito sentido que a aplicação da mesma operação (push ou popping) ao início e ao final de um array tenha pelo menos nomes relacionados; push! e shift! são um par não intuitivo; 2) a palavra shift! pode ser confundida com deslocamento de bits >> , como pode ser facilmente visto pesquisando nos documentos por "shift"; 3) muitos usuários do Julia não terão um fundo perl / javascript de qualquer maneira.
Portanto, sou a favor da opção 2 no post acima.
Mas, se os renomearmos, o que fazer com circshift! ?

A opção 2 ou 4 de Stefan parece boa para mim. Não acho que circshift! precise mudar, porque não é uma operação do tipo pop

Proposta:

| velho | novo | apelidos |
| ----: | ----: | ----: |
| push! | pushr! | push! |
| pop! | popr! | pop! |
| unshift! | pushl! | |
| shift! | popl! | |

Devo dizer que é tentador, especialmente se mantivermos push! e pop! como apelidos para os casos em que você está usando apenas uma estrutura como uma pilha e não se importa se é a esquerda ou direito, você está empurrando e saindo.

Imo usando front e back são (significativamente) mais claros do que abreviar left e right .

Especialmente porque nossos vetores são verticais (por isso deve ser superior / inferior) 🙂. Outras opções podem ser início / fim ou primeiro / último.

esquerda / direita parece bom para mim; é consistente com nossa terminologia de redução ( foldl e foldr ), e como os vetores são normalmente inseridos em [a,b,c,…] e gerados por print .

A outra coisa boa sobre esquerda / direita é que ela tem uma abreviação de um caractere bem estabelecida.

Sério, não sei qual extremidade de um vetor é a frente ou o verso. O índice da frente é 1 ou atrás? Sim, às vezes imprimimos nossos vetores verticalmente, mas também os imprimimos da esquerda para a direita em outros casos. Já estamos usando consistentemente a nomenclatura esquerda / direita herdada para muitas outras funções.

Que tal ter novos métodos para anexar! e prefixar! onde o segundo argumento é um escalar?

Esta conversa voltou para https://github.com/JuliaLang/julia/issues/23902#issuecomment-332615200, que, por sua vez, mostra https://github.com/JuliaLang/julia/issues/23902#issuecomment-332668546 , ou seja, head / tail ou first / last terminologia? :)

Ops, desculpe por prolongar a discussão. Meu ponto é que, em vez de inventar novas palavras, devemos reutilizar as existentes.

Ops, desculpe por prolongar a discussão. Meu ponto é que, em vez de inventar novas palavras, devemos reutilizar as existentes.

Desculpe @phaverty! Simulamos. Minha resposta deveria seguir @StefanKarpinski , ao invés de comentar seu comentário :). Melhor!

Eu gosto mais de popfirst! , pushfirst! , poplast! , pushlast! com pop! e push! como apelidos para os dois último.

onde o segundo argumento é um escalar?

Não é possível definir escalar genericamente.

"Não é possível definir escalar genericamente."

Ah, entendo. Você pode especificar, digamos,

anexar! (x :: Vector {T}, y :: T)

, mas você realmente deseja que y seja "algo que pode ser convertido em T". Mas, o sistema de tipos (ainda?) Não sabe que conjunto de tipos pode ser convertido. Desapontamento.

Vamos dar um voto (não obrigatório, informativo):

  • 👍 para pushr! , popr! , pushl! e popl! com push! e pop! como apelidos para os dois primeiros
  • 👎 para manter as coisas como estão
  • 😕 para alguma outra opção

Essa escolha de emoji é um tanto tendenciosa;).

E: +1: na sugestão de OPs, se preferir;)

Tenho algumas ideias sobre como renomear essas funções, então vou pedir desculpas antecipadamente por possivelmente adicionar algum ruído a esta conversa. Até agora, os nomes de Julia das funções push! , pop! , shift! e unshift! funções de Julia são iguais às funções Perl, Ruby e JavaScript (https: // en .wikipedia.org / wiki / Double-ended_queue # Operations). Pessoalmente, não me importo com esses nomes, pois os aprendi originalmente em Perl, mas admito plenamente que shift / unshift não são memoráveis. Também parece haver um acampamento que pensa que push / pop é um mau par complementar .

Outra ideia: push/pop!(first, x, ...) e push/pop!(last, x, ...) .

Se fôssemos ir nessa direção, eu sugeriria que usássemos enqueue! e dequeue! como os nomes dessas funções.

O que eu gosto nos nomes originais é que eles usam apenas uma palavra. Tentando manter uma palavra, mas fazer alguns pares mais agradáveis, eu descobri push! e pull! para FIFO e push! e pop! para FILO. Isso faria com que o push / pop funcionasse no início de uma fila em vez de no final:

Old | Novo
------- | -----
Empurre! | por!
pop! | puxar!
mudança! | Empurre!
não mude! | pop!

Poderíamos deixar push / pop no final e mover put / pull para o início para ter menos quebra, mas acho que isso deixaria as coisas um tanto confusas.

Outra alternativa é usar append! e prepend! para se referir respectivamente a push! e shift! . Não tenho nenhuma palavra razoável para retirar da fila, no entanto, e behead e curtail foram os melhores que consegui encontrar ...

@phaverty Contanto que seja possível ter um Vector{Any} , isso será ambíguo.

Vou postar novamente: https://github.com/JuliaLang/julia/issues/23902#issuecomment -332919287

@omus Renomear shift! para push! parece gratuitamente confuso.

append! opera em duas coleções, enquanto push! et. al. opera em um elemento, então IMO esse nome simplesmente não pode ser usado aqui.

Finalmente, podemos sempre abraçar o Unicode e ir com algo como:

ASCII | Unicode | Nome Unicode | Pseudônimo
--- | --- | --- | ---
Empurre! | ⇤ | seta para a esquerda para barra |
pop! | ↦ | seta para a direita da barra | mapsto
mudança! | ⇥ | seta para a direita para barra |
não mude! | ↤ | seta para a direita da barra | mapas de

Pense na barra no Unicode como a fila. ~ Infelizmente, esses caracteres Unicode não têm apelidos legais no REPL, pelo que posso dizer ~.

Renomear shift! para push! parece gratuitamente confuso.

Honestamente, eu ficaria infeliz se realmente adotássemos essa abordagem. Essa abordagem definitivamente tenta ser legal com os recém-chegados e realmente significa para os usuários existentes de Julia.

@omus , por exemplo, ↦ é \mapsto .

Ok, eu menti: tenho mais uma coisa a dizer. Como uma sugestão mais séria, poderíamos seguir essa abordagem. Ele perde o bom push / pop, mas é muito mais claro quanto à operação em andamento:

Old | Novo
- | -
Empurre! | lastin!
pop! | Último a sair!
mudança! | primeiro em!
não mude! | primeiro a sair!

Sinta-se à vontade para votar contra a maioria dessas sugestões. Depois de fazer algumas pesquisas neste tópico, a única conclusão verdadeira a que cheguei é que os cientistas da computação adotaram a terminologia push / pop e não tinham ideia do que denominar shift / unshift.

Agora que temos dobramento constante, os argumentos de palavra-chave para isso devem ser rápidos, correto? Não entendo por que teríamos 4 funções para isso em vez de 2, especialmente porque funções com várias palavras são especificamente desencorajadas para promover a refatoração.

Por mais divertido que seja, parece que não podemos fazer melhor do que o status quo aqui.

Por mais divertido que seja, parece que não podemos fazer melhor do que o status quo aqui.

O montante do apoio ao OP parece substancial? Talvez encerrar este problema seja um pouco prematuro? :)

Sim, a sugestão do OP tem 11 para cima e 0 para baixo ...

Eu interpretei isso como suporte para a noção geral de renomeação, não para aquela sugestão específica.

É claro para mim que, depois de toda essa discussão, não encontramos uma alternativa realmente convincente.

FWIW pushfront! ainda é meu favorito e vale a pena renomear na minha opinião, mas isso pode ser apenas meu viés C ++.

Gosto de pushfront! e popfront! .

Bem, eu fiz um PR em # 25100 para usar pushfront! / popfront! pois acho que é o mínimo que podemos fazer para renomear unshift! . Na verdade, a única coisa que unshift! tem a seu favor é (a) é o status quo e (b) tem precedente em perl / javascript / php / outras linguagens que herdam escolhas duvidosas de perl

Sinta-se à vontade para derrubá-lo ;-)

Semelhante ao que @ Sacha0 mencionou em # 25100. Acho que se realmente quisermos fazer uma renomeação, sugiro ir com:

enqueue!(::typeof(first), a, item) = unshift!(a, item)
enqueue!(::typeof(last), a, item) = push!(a, item)
dequeue!(::typeof(first), a) = shift!(a)
dequeue!(::typeof(last), a) = pop!(a)
julia> enqueue!(::typeof(first), a, item) = unshift!(a, item);

julia> enqueue!(::typeof(last), a, item) = push!(a, item);

julia> dequeue!(::typeof(first), a) = shift!(a);

julia> dequeue!(::typeof(last), a) = pop!(a);

julia> foo = [1, 2, 3]
3-element Array{Int64,1}:
 1
 2
 3

julia> enqueue!(first, foo, 0)
4-element Array{Int64,1}:
 0
 1
 2
 3

julia> dequeue!(first, foo)
0

julia> enqueue!(last, foo, 5)
4-element Array{Int64,1}:
 1
 2
 3
 5

julia> dequeue!(last, foo)
5

Alternativamente:

push!(::typeof(first), a, item) = unshift!(a, item)
push!(::typeof(last), a, item) = push!(a, item)
pop!(::typeof(first), a) = shift!(a)
pop!(::typeof(last), a) = pop!(a)

Também poderíamos manter push! e pop! sem passar first ou last que seria push!(last, ...) e pop!(last, ...) padrão

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

StefanKarpinski picture StefanKarpinski  ·  3Comentários

tkoolen picture tkoolen  ·  3Comentários

arshpreetsingh picture arshpreetsingh  ·  3Comentários

StefanKarpinski picture StefanKarpinski  ·  3Comentários

helgee picture helgee  ·  3Comentários