LINUX.ORG.RU

Implicit function arguments в Rust

 


1

9

Привет, ЛОР.

Расскажи мне, как в Rust принято таскать read-only данные типа конфигурации? В идеале я хочу аналог ReaderT из Haskell, т.к. он позволяет легко тестировать код без свистоплясок глобальными переменными и прочих странных вещей. Для Rust я похожего не нашёл.

Неужели нужно городить глобальные переменные либо руками каждой фукнции писать лишний аргумент?

★★★★★

Последнее исправление: hateyoufeel (всего исправлений: 2)

Ответ на: комментарий от Virtuos86

Там свои заморочки есть. Все операции в обёрнутую монаду XXX нужно прокидывать с помощью liftXXX, а если требуется работать с функциями, использующими разные монады — всё ещё веселее.

red75prim ★★★
()
Последнее исправление: red75prim (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Отсутствие implicit arguments — это какой из этих вариантов?

Ну их много где нет, так что «проблема» не специфична для раста.

DarkEld3r ★★★★★
()
Ответ на: комментарий от hateyoufeel

Особенно если какое-то значение понадобится в функции, которая вызывается не напрямую из main, а где-то на втором-третьем уровне

Вообще-то это и есть так называемые побочные эффекты, от которых в Haskell, что ты приводишь в пример, вообще принято избавляться. Передавай параметры явно.

Aswed ★★★★★
()
Ответ на: комментарий от Weres

в Haskell можно замутить и глобальную переменную при желании, только надо не забыть одну прагму обозначить. Создатели Rust, очевидно, многое переняли из Haskell, и даже само название unsafe как-бы намекает

dave ★★★★★
()
Ответ на: комментарий от dave

А я в Java EE могу через DI конфиг пошарить. Делает ли это функцию с ReaderT нечистой? Мне кажется, что нет. Потому что ни к одному, ни к другому он не относится.

Weres ★★★
()
Ответ на: комментарий от dave

Я не хаскеллист, я не знаю что такое unsafePerformIO. Про ReaderT в треде несколько раз подчеркивали, что он предоставляет в функцию константный стейт. Следовательно, он не может быть источником побочных эффектов. В этом был смысл поста, на который вы ответили приведя в пример возможность создания глобальной переменной. Какое отношение имеет глобальная переменная к ReaderT? Или я что-то не так понял?

Weres ★★★
()
Ответ на: комментарий от Aswed

Вообще-то это и есть так называемые побочные эффекты,

Нет.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от korvin_

Не понял вопрос. А как ещё можно обращаться к переменной?

Я криво сформулировал. Что будет, если локально объявить переменную с таким же именем?

hateyoufeel ★★★★★
() автор топика

В расте не изобрели ещё di контейнеры?

nikolnik ★★★
()
Ответ на: комментарий от pftBest

TLS это считай глобальная переменная.

Зависит от того, куда этот TLS сунут. Но вообще ты прав, да.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от Weres

Изначально речь была о чтении конфига. Вот и можно его прочитать, а потом сохранить результат в глобальной переменной, которые в Haskell, оказывается, тоже есть. Только это совершенно неидиоматический подход. Хотя мне кажется, что в некоторых случаях его используют, где вынуждены приспосабливаться к особенностям внешнего окружения, как то, какие-нибудь либы к GUI

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 1)

Вообще так делать неправильно, но я бы колхозил так: Стек с конфигами thread local. Функция получения значений из конфига на вершине стека. Две функции для изменения конфига, одна принимает конфиг, добавляет в стек и возвращает некий объект, который при дропе удалит свой конфиг из стека, вторая - надстройка над первой, принимает конфиг и FnOnce, вызывает первую, вызывает функцию и потом дропает объект.

khrundel ★★★★
()
Ответ на: комментарий от Weres

Потому как результат функции зависит не только от входных значений функции но и еще чего-то там во внешнем мире.

Aswed ★★★★★
()
Ответ на: комментарий от Aswed

Я думал, что тут неизвестно когда начинает читаться файл конфига.

По факту так и есть, и неизвестно, когда закончится чтение.

O02eg ★★★★★
()
Ответ на: комментарий от Aswed

Добро пожаловать в реальный, многопоточный мир.

O02eg ★★★★★
()
Ответ на: комментарий от O02eg

Пример можете привести? Обращу ваше внимание, что мы обсуждаем здесь ReaderT который, насколько я понял его семантику, позволяет задать иммутабельный стейт и неявно передавать его вниз по стеку. Где здесь проблемы с чтением или многопоточностью?

Weres ★★★
()
Ответ на: комментарий от O02eg

Как можно использовать стейт до его инициализации? Можете код показать?

Weres ★★★
()
Ответ на: комментарий от O02eg

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

Чувак, ты хрень написал. Перестань это делать.

hateyoufeel ★★★★★
() автор топика
13 октября 2017 г.

Ммм, я правильно понимаю, что твою хотелку сейчас можно реализовать с помощью ассоциированных констант и (опционально) lazy_static?

struct ReaderT;

impl ReaderT {
    const X: i32 = 1;
    const Y: &'static str = "";
}

fn main() {
    println!("{}, {}", ReaderT::X, ReaderT::Y);
}

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Хотя, с другой стороны, и раньше можно было делать:

mod config {
    pub const PARAM1: i32 = 1;
    pub const PARAM2: &str = "";
}

Virtuos86 ★★★★★
()
Ответ на: комментарий от Virtuos86

Нет, потому что мне не константы нужны. Если бы можно было impl делать локально и он бы передавался вниз по стеку вызовов, тогда да.

hateyoufeel ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.