2013-08-14 4 views

ответ

2

Здесь я написал REMOVE-LAST функцию,

remove-last: func [ 
    "Removes value(s) from tail of a series." 
    series [series! port! bitset! none!] 
    /part range [number!] "Removes to a given length." 
] [ 
    either part [ 
     clear skip tail series negate range 
    ] [ 
     remove back tail series 
    ] 
] 

Пример использования:

b: [a b c d e f g] 
remove-last b ;== [], 'g removed, tail of the series return. 
head remove-last/part b 2 ;== [a b c d], 'e and 'f removed 

возвращает хвост серии, чтобы иметь возможность использовать в следующей ситуации;

b: [a b c d e f g] 
head insert remove-last b 'x ;== [a b c d e f x] 
3

Определить "лучше". Высокая производительность? Самая ясность? Что вы хотите, чтобы выражение вернулось в конце, или вам все равно? Эти два вы обеспечиваете возврат разных результатов ... один из них после удаления, а другой элемент удален.

Если вы хотите, чтобы глава серии после удаления, вам нужно take/last s, а затем s, чтобы получить это выражение. Сравнение:

>> delta-time [ 
    loop 10000 [ 
     s: copy "abc" 
     take/last s 
     s 
    ] 
] 
== 0:00:00.012412 

>> delta-time [ 
    loop 10000 [ 
     s: copy "abc" 
     head remove back tail s 
    ] 
] 
== 0:00:00.019222 

Если вы хотите, чтобы выражение оценки к пункту удален, вы должны были бы сравнить take/last s против чего-то свернутого как also (last s) (remove back tail s) ... потому что также будут работать первое выражение, а затем второй ... возвращая результат из первого:

>> delta-time [ 
    loop 10000 [ 
     s: copy "abc" 
     take/last s 
    ] 
] 
== 0:00:00.010838 

>> delta-time [ 
    loop 10000 [ 
     s: copy "abc" 
     also last s remove back tail s 
    ] 
] 
== 0:00:00.024859 

т.д.

Если вы не заботитесь о результате, я иду с take/last. Если вы заботитесь о результатах и ​​хотите стать главой сериала, я собираюсь с take/last s, а затем s. Для меня это лучше, чем head remove back tail s, хотя это эстетический выбор. Это еще быстрее, по крайней мере, на моем нетбуке.

Если вам нужен хвост серии в конце выражения, то remove back tail s на удивление аналогичен по производительности take/last s, а затем tail s. Я бы сказал, что последнее является более явным и, вероятно, предпочтительным, если читатель забудет соглашение о возврате REMOVE.

И also last s remove back tail s выглядит ужасно, но является напоминанием о also, что довольно полезно и легко забыть, что оно есть. FWIW, он работает примерно так же, как с использованием промежуточной переменной.

+0

Итак, возможно ** УДАЛИТЬ/ПОСЛЕДНИЙ ** было бы неплохо иметь в Реболе здесь? Это также может позволить (например, «remove/last/part s 2» удалить последние 2 'вещи' из серии. – draegtun

+0

@ draegtun Интересная идея, мы можем [обсудить ее в чате] (http://chat.stackoverflow.com/rooms/291/rebol-and-red). Исторически исходные операции Rebol не являются строго симметричным или ортогональным набором операций. При добавлении элементов есть ** INSERT ** и ** APPEND ** нет ** REMOVE ** родной аналог, который автоматически действует на спине. Девиз * «Вдохновленный теорией, информированный практикой» * подразумевает, что такие вещи, как 'remove/last/part s 2', просто не появлялись, поэтому часто люди живут с' remove/part skip tail s -2 2', если он появляется. Это уродливо, но, возможно, недостаточно распространено, чтобы заботиться? – HostileFork

+0

Я думаю, что ** REMOVE ** можно/можно рассматривать как следствие ** TAKE ** в том, что оба работают над * рядом * и оставляют * index * нетронутыми. Пища для размышлений? – draegtun