Частичное применение во время компиляции в Rust?

Сохраненная процедура - лучший способ сделать это. Поскольку решение Мехерзада будет работать только в том случае, если данные будут следовать одному и тому же порядку.

Если у нас есть такая структура таблицы

col1 | col2 | col3
-----+------+------
 3   | k    | 7
 5   | d    | 3
 1   | a    | 5
 6   | o    | 2
 2   | 0    | 8

, она не будет работать. SQL Fiddle Demo

Вот пример кода процедуры для достижения того же.

delimiter //
CREATE PROCEDURE chainReaction 
(
    in inputNo int
) 
BEGIN 
    declare final_id int default NULL;
    SELECT col3 
    INTO final_id 
    FROM table1
    WHERE col1 = inputNo;
    IF( final_id is not null) THEN
        INSERT INTO results(SELECT col1, col2, col3 FROM table1 WHERE col1 = inputNo);
        CALL chainReaction(final_id);   
    end if;
END//
delimiter ;

call chainReaction(1);
SELECT * FROM results;
DROP TABLE if exists results;

-2
задан sdgfsdh 2 March 2019 в 20:07
поделиться

2 ответа

Я смог сделать это ночью, используя функцию const, возвращающую закрытие:

#![feature(const_fn)]

fn foo(x: String, y: String) -> String {
    x + &y
}

const fn foo_applied(x: String) -> impl Fn(String) -> String {
    move |y| foo(x.clone(), y)
}

fn main() {
    let foo_1 = foo_applied("1 ".into());
    println!("{}", foo_1("2".into()));
    let foo_2 = foo_applied("2 ".into());
    println!("{}", foo_2("1".into()));
}

Детская площадка

0
ответ дан Shepmaster 2 March 2019 в 20:07
поделиться

Обратите внимание, что вашей функции foo в настоящее время требуются две строки, выделенные в куче без необходимости. Вот еще одна версия, которая является более универсальной и эффективной (хотя YMMV, как я опишу далее):

fn foo<T>(x: T, y: &str) -> String
where
    T: Into<String>,
{
    x.into() + y
}

assert_eq!(foo("mobile ", "phones"), "mobile phones");

Конкатенация почти всегда будет требовать выделения памяти где-то, но эта может принимать выделенные для кучи строки как а также произвольные кусочки строк. Он также может избежать перераспределения, если емкость x достаточно велика, хотя это не очень вероятно, учитывая, что x получается из строки, известной во время компиляции. String::insert_str позволили бы нам изменить положение параметра типа, но вставка в начале строки имеет стоимость O (n). Знание первого операнда конкатенации строк априори не очень полезно для компилятора с точки зрения того, какие оптимизации он может использовать.


Предположим, что мы все еще хотим выполнить частичную функцию во время компиляции. Похоже, что это еще один случай использования, когда const generics будет блестеть. С помощью этой функции можно действительно мономорфизировать эту функцию через &'static str с чем-то вроде этого еще не реализованного синтаксиса:

fn foo<const X: &'static str>(y: &str) -> String {
    x.to_string() + y
}

Увы, дженерики const в настоящее время находятся в стадии разработки и не совсем готовы к этому еще. Хотя и менее эргономично, мы можем вместо этого повторить эффект создания одной функции для каждого строкового литерала с макросами на основе правил:

macro_rules! define_foo {
    ($fname: ident, $x: literal) => {
        fn $fname (y: &str) -> String {
            $x.to_string() + y
        }
    }
}

Использование:

define_foo!(bar, "Conan ");

assert_eq!(bar("Osíris"), "Conan Osíris");    

См. Также:

0
ответ дан Shepmaster 2 March 2019 в 20:07
поделиться
Другие вопросы по тегам:

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