Обобщение над изменчивостью указателя [duplicate]

URLEncoder должен быть способом. Вам нужно только иметь в виду только кодировать только имя и / или значение имени строки запроса, а не весь URL-адрес, а не символ разделителя параметров строки запроса & или имя параметра- символ разделителя значений =.

String q = "random word £500 bank $";
String url = "http://example.com/query?q=" + URLEncoder.encode(q, "UTF-8");

Обратите внимание, что пробелы в параметрах запроса представлены +, а не %20, что является законно действительным. %20 обычно используется для представления пробелов в самом URI (часть перед символом разделителя строки URI-запроса ?), а не в строке запроса (часть после ?).

Также обратите внимание, что существует два метода encode(). Один без аргумента набора символов и другой. Тот, у кого аргумент без аргумента, устарел. Никогда не используйте его и всегда указывайте аргумент charset. javadoc даже явно рекомендует использовать кодировку UTF-8, как это предусмотрено RFC3986 и W3C .

Все остальные символы небезопасны и сначала преобразуются в один или несколько байтов, используя некоторую схему кодирования. Затем каждый байт представлен 3-символьной строкой «% xy», где xy - двухзначное шестнадцатеричное представление байта. Рекомендуемой схемой кодирования для использования является UTF-8. Однако, по соображениям совместимости, если кодировка не указана, используется кодировка по умолчанию платформы.

blockquote>

См. Также:

18
задан ideasman42 9 January 2017 в 05:27
поделиться

3 ответа

На самом деле вы этого не делаете. Напомним, что T, &T и &mut T все разные типы . В этом контексте ваш вопрос совпадает с вопросом: «Как избежать написания дублирующих функций доступа для String и HashMap».

Matthieu M имел правильные термины «абстрактные по поводу изменчивости»:

TL; DR - то, что Rust, вероятно, необходимо будет улучшить с помощью новых функций для поддержки этого. Поскольку никто не преуспел, никто не на 100% уверен, какие функции должны быть. В настоящее время лучше всего предположить более высокие типы типов (HKT).

10
ответ дан Shepmaster 17 August 2018 в 15:28
поделиться

(ссылки на игровые площадки к решениям с использованием параметров типа и связанных типов )

В этом случае &T и &mut T являются двумя разными типы. Код, который является общим для разных типов (как во время компиляции, так и во время выполнения), идиоматически написан в Rust, используя черты. Например, учитывая:

struct Foo { value: i32 }
struct Bar { foo: Foo }

, предположим, что мы хотим предоставить Bar общий аксессор для своего члена данных Foo. Аксессор должен работать как с &Bar, так и с &mut Bar, соответствующим образом возвращающим &Foo или &mut Foo. Таким образом, мы пишем черту FooGetter

trait FooGetter {
    type Output;
    fn get(self) -> Self::Output;
}

, задача которой должна быть общей для конкретного типа Bar. Его тип Output будет зависеть от Bar, так как мы хотим get иногда возвращать &Foo, а иногда &mut Foo. Обратите также внимание на то, что он потребляет self типа Self. Поскольку мы хотим, чтобы get был общим для &Bar и &mut Bar, нам нужно реализовать FooGetter для обоих, так что Self имеет соответствующие типы:

// FooGetter::Self == &Bar
impl<'a> FooGetter for &'a Bar {
    type Output = &'a Foo;
    fn get(self) -> Self::Output { & self.foo }
}

// FooGetter::Self == &mut Bar
impl<'a> FooGetter for &'a mut Bar {
    type Output = &'a mut Foo;
    fn get(mut self) -> Self::Output { &mut self.foo }
}

Теперь мы можем легко используйте .get() в общем коде, чтобы получить & или &mut ссылки на Foo из &Bar или &mut Bar (просто требуя T: FooGetter). Например:

// exemplary generic function:
fn foo<T: FooGetter>(t: T) -> <T as FooGetter>::Output {
    t.get() 
}

fn main() {
    let x = Bar { foo: Foo {value: 2} };
    let mut y = Bar { foo: Foo {value: 2} };

    foo(&mut y).value = 3;
    println!("{} {}\n", foo(&x).value, foo(&mut y).value);
}

Обратите внимание, что вы также можете реализовать FooGetter для Bar, так что get является общим для &T, &mut T и T (по перемещая его). Это на самом деле способ, которым метод .iter() реализован в стандартной библиотеке и почему он всегда делает «правильную вещь» независимо от ссылочного аргумента, на который он ссылается.

7
ответ дан gnzlbg 17 August 2018 в 15:28
поделиться
  • 1
    Кажется, что это работает только для методов? (которые берут себя), хотя я полагаю, что функции могут быть обернуты и вызвать методы. – ideasman42 28 February 2017 в 18:54
  • 2
    @ ideasman42 Да, см. функцию foo в последнем фрагменте кода выше для того, как вы можете обернуть вызов метода в свободной функции. Вы можете применить любой метод метода / метода объекта в свободной функции. Обратите внимание, что мы должны использовать методы, потому что то, что вы хотите, требует "перегрузки функций" (как в разных функциях .get вызывается в зависимости от типов аргументов), которые недоступны для свободных функций. В частности, это не ограничивается типом первого аргумента, поскольку вы можете использовать связанные типы для перегрузки типов других аргументов, а также в ночной специализации. – gnzlbg 28 February 2017 в 19:02

В настоящее время Rust не поддерживает абстрагирование над изменчивостью.

Есть некоторые способы, которыми это может быть достигнуто, хотя они не идеальны:

  • Используйте макрос для развернуть дублирующий код, объявить макрос и поделиться между обеими функциями - нужно сконструировать, чтобы он работал для изменяемого и неизменяемого, конечно.
  • Напишите неизменяемую версию функции (чтобы гарантировать, что ничего не изменилось) затем напишите функцию-обертку для изменяемой версии, которая выполняет unsafe приведение результата, чтобы сделать его изменчивым.

Ни один из них не очень привлекателен (макрос слишком многословный и немного менее читаемый, добавляет некоторый код-раздувание), unsafe более читабельна, но было бы неплохо избежать, поскольку отличать от неизменяемого до изменяемого не так приятно иметь через базу кода.

На данный момент лучший вариант, насколько я могу видеть (где код для копирования не подходит), заключается в том, чтобы написать неизменяемую версию функции, а затем обернуть ее с помощью mut версии функции, где бот h входы и выходы изменяемы.

Для этого требуется выход unsafe на выходе функции, поэтому он не идеален.


Примечание: важно иметь неизменяемая функция содержит тело кода, так как обратное позволит случайным образом изменить то, что может быть неизменным.

-5
ответ дан ideasman42 17 August 2018 в 15:28
поделиться
  • 1
    -1, потому что создание поддельной ссылки &mut - IN; программе становится трудно рассуждать, и вы рискуете потерять основное преимущество Rust: ваша программа безопасна для памяти, если она компилируется – bluss 9 January 2017 в 03:49
  • 2
    Исключение критических инвариантов при использовании блоков unsafe отсутствует. Помните, что небезопасный код не для того, чтобы нарушать инварианты Руста, он предназначен для поддержания их вручную ". – bluss 9 January 2017 в 03:55
  • 3
    @ Ответ Shepmaster утверждает, что это не поддерживается, это нормально, но есть способы сделать это, как включено в этот ответ. Таким образом, даже если его downvoted как плохой выбор - его стоит отметить, что это можно сделать, и может быть лучше, чем копировать вставки больших блоков кода. – ideasman42 9 January 2017 в 05:27
  • 4
    @bluss const -> mut выполняется только по аргументу return, а не по телу функции. Пока входы изменяемы, а тело-оболочка - всего несколько строк, я думаю, что это вполне безопасно. Считайте, что код для копирования в скопировании может иметь значительные недостатки. AFAICS - это вопрос выбора меньшего из двух зол: S – ideasman42 9 January 2017 в 05:37
Другие вопросы по тегам:

Похожие вопросы: