Поддерживать API и использовать идиомы в порту

12

Я работаю над портом от Python до Rust и наткнулся на некоторый код, который не может быть выражен так же естественно в Rust, как в Python.

Одним из случаев этого является использование параметров по умолчанию:

class Foo:
  def __init__(self, a="Hello"):
    self._a = a

В Rust вы можете реализовать это с помощью компоновщика:

struct FooBuilder {
  a: &'static str,
}

struct Foo {
  _a: &'static str
}

impl FooBuilder {
  fn new() -> FooBuilder {
    FooBuilder {
      a: "Hello",
    }
  }

  fn change_a(self, new_a: &'static str) -> FooBuilder {
    FooBuilder {
      a: new_a,
      ..self
    }
  }

  fn build(self) -> Foo {
    Foo {
      _a: self.a,
    }
  }
}

Чтобы использовать класс в Python, это просто:

foo = Foo("Hello, World!")

Однако в Rust вам нужно написать что-то вроде:

let foo = FooBuilder::new().change_a("Hello, World!").build();

Это приводит к вопросу: лучше ли поддерживать API для порта или лучше использовать идиомы языка переноса? Зависит ли это от того, насколько хорошо API известен с самого начала?

erip
источник
2
API класса - это то, как вы его используете, а не то, как это выражается в коде. Таким образом, этот перевод имеет совершенно другой и просто неприемлемо громоздкий ABI.
Дедупликатор
Где сказано, что это идиоматический Rust?
Надир Сампаоли
Извините, я, должно быть, неправильно понял. Вы опубликовали некоторый код на Rust вместе с дилеммой: будете ли вы поддерживать API для порта или будете использовать идиомы языка переноса . Этот код не похож ни на один из этих случаев. Если это правильная интерпретация, какова цель этого примера кода? Что это описывает и как это связано с актуальным вопросом?
Надир Сампаоли

Ответы:

18

Вы хотите, чтобы ваши идеи были четко выражены на языке, который их принимает. Это означает использование языка идиом.

Возьмите популярную библиотеку Underscore: js и lua . Порт lua функционально эквивалентен по большей части . Но когда это уместно, реализации немного отличаются. Например:

_.toArray()

становится

_.to_array()

Это изменение делает имя функции более понятным для программистов Lua.

Аналогично, для _.each () требуется объект, массив или что-то похожее на массив в JavaScript, но _.each () в Lua также может использовать итератор - механизм, который не был доступен в JavaScript, когда исходная библиотека Underscore был создан.

Автор Lua разумно перевел то, что предполагал первоначальный автор , если бы написал это на Lua. Это ключ. Спросите себя об исходном намерении, а затем реализуйте это намерение на своем языке по своему выбору - идиомы и все такое. В зависимости от исходного и целевого языка это может означать добавление, редактирование или удаление функций.

Помните, что кросс-языковые пользователи будут редки. Большинство пользователей будут использовать один язык или другой. Для них различия не имеют значения. Если кто-то использует оба, они, вероятно, достаточно опытны, чтобы оценить ваш перевод. Это ничем не отличается от перевода разговорных языков. Некоторые идеи не могут быть переведены напрямую. Лучшие переводчики придерживаются замысла оригинала, а не обреченного дословного буквального перевода.

Скудный Роджер
источник