Zachowaj API zamiast używania idiomów w porcie

12

Pracuję na porcie od Pythona do Rusta i natrafiłem na kod, który nie może być wyrażony w Rust tak naturalnie, jak w Pythonie.

Jednym z takich przypadków jest użycie parametrów domyślnych:

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

W Rust możesz to zaimplementować za pomocą konstruktora:

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,
    }
  }
}

Aby użyć klasy w Pythonie, wystarczy:

foo = Foo("Hello, World!")

Jednak w Rust musisz napisać coś takiego:

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

Prowadzi to do pytania: czy lepiej jest utrzymywać API dla portu, czy lepiej jest używać idiomów języka portowania? Czy to zależy od tego, jak dobrze interfejs API ma zacząć?

erip
źródło
2
API klasy polega na tym, jak z niej korzystasz, a nie na tym, jak jest wyrażona w kodzie. Tak więc tłumaczenie to ma zupełnie inny i po prostu niedopuszczalnie kłopotliwy ABI.
Deduplicator,
Gdzie jest powiedziane, że to idiomatyczna rdza?
Nadir Sampaoli,
Przepraszam, musiałem źle zrozumieć. Umieściłeś trochę kodu Rust wraz z dylematem: jeśli utrzymasz API dla portu lub użyjesz idiomów języka portowania . Ten kod nie wygląda jak żaden z tych przypadków. Jeśli jest to poprawna interpretacja, jaki jest cel tej próbki kodu? Co to opisuje i jak ma się do faktycznego pytania?
Nadir Sampaoli,

Odpowiedzi:

18

Chcesz, aby Twoje pomysły były jasno wyrażone w języku, w którym je hostujesz. Oznacza to używanie idiomów języka hosta.

Weź popularną bibliotekę Underscore: js i lua . Port lua jest w większości funkcjonalnie równoważny . Ale kiedy jest to właściwe, implementacje są nieco inne. Na przykład:

_.toArray()

staje się

_.to_array()

Ta zmiana sprawia, że ​​nazwa funkcji wydaje się bardziej natywna dla programistów Lua.

Podobnie, _.each () wymaga obiektu, tablicy lub czegoś podobnego do tablicy w JavaScript, ale _.each () w Lua może również przyjmować iterator - mechanizm, który nie był dostępny w JavaScript, gdy oryginalna biblioteka Underscore został stworzony.

Autor Lua rozsądnie przetłumaczył, co zamierzałby oryginalny autor , gdyby napisał to w Lua. To jest klucz. Zapytaj siebie o pierwotną intencję, a następnie zastosuj ją w wybranym języku - idiomy i wszystko inne. W zależności od języka źródłowego i docelowego może to oznaczać dodawanie, edytowanie lub usuwanie funkcji.

Pamiętaj, że użytkownicy w różnych językach będą rzadcy. Większość użytkowników będzie używać jednego lub drugiego języka. Dla nich różnice nie mają znaczenia. Jeśli ktoś korzysta z obu tych metod, prawdopodobnie jest wystarczająco zaawansowany, aby docenić twoje tłumaczenie. Nie różni się niczym od tłumaczenia języków mówionych. Niektórych pomysłów nie można bezpośrednio przetłumaczyć. Najlepsi tłumacze trzymają się oryginału, a nie przeklętego dosłownego tłumaczenia dosłownego.

Scant Roger
źródło