我在users.rust-lang.org开了一个帖子,询问了相关问题
反对意见居多,但大概是我步子迈太大的缘故
——我的提议允许大家使用x~uniform;
来给x赋一个新的,产生自随机数生成器uniform的随机数值,原理如下
impl CustomAssign<RNG> for i32{
fn custom_assign(&mut self,rhs:&mut RNG){
*self=rhs.sample();
}
}
fn main(){
let uniform=RNG::uniform(0,1);// RNG 是什么我就不写了
let mut x:f64=0;//可变借用x的前提是x已经完成初始化
x~uniform;//其实是x.custom_assign(&mut uniform);
}
我有这个想法,最初的原因只是发现,Rust有各种assign的重载,但不能重载=
,也没有重载assign的任何方法。
我们的确可以重载|= ^= &=
之类的算符来完成自定义assign的功能,但考虑到这几个符号都有自己独特的语义,借助这几个重载符号容易引起歧义
同时,类似a=From::from(b)
或者a=b.into()
的赋值有点过于笨拙
于是我想干脆一步到位,定义两个可以customize的trait,并绑定不同的符号
一个是CustomAssign
,绑定~
,左边是可变借用,右边是T,T可以直接传递所有权,或者借用,或者可变借用。
另一个是CustomInitialize
,绑定:=
,trait只有对右边的借用,签名如下:
trait CustomInitialize<Rhs=Self>{//默认Rhs跟Self相同,但Rhs可以随便改
fn custom_initialize(rhs:Rhs)->Self;//Self会赋值给左边
}
这里“绑定”的意思是
//预先定义
impl CustomInitialize<i32> for i128{
fn custom_initialize(rhs:i32)->Self{rhs as i128}
}
// ...
let x:i128 :=1i32;
//等价于下面的式子
let x:i128 = <i128 as CustomInitialize<i32>>::custom_initialize(1i32);
//写完才发现,我在这里竟要求了一个冒号等价于这么多东西
这两种定义会不会存在什么潜在的问题?
我又应该以什么样的方法把类似feature request提交给rust论坛呢?
(只是担心,在users里面发文章都被喷,发到internal那里……)
1
共 12 条评论, 1 页
评论区
写评论我不想用
这么啰嗦的指令,毕竟
比上面的代码更短且更好敲
讲道理我还是写了两个syntax的
一个是
a~b
,调用a.custom_assign(b)
一个是
a:=b
,调用a=CustomInitialize::custom_initialize(b)
这两个应该算是新语法了
至于“大多数宏都尽量把解析内容尽可能缩小”
我读的是这个,成品是
写成这样已经很不容易了……
(BTW,下一步的计划是上proc_marco,加速编译,已经找到了dalao的栗子,正在仔细研读)
--
👇
苦瓜小仔: 似乎你想把所有 Rust 语法放到一个宏里面,但这根本不必要。宏的主要作用(via Rust By Example):
大多数宏都尽量把解析内容尽可能缩小,从而尽可能不对编译(时间、优化等方面)很大造成影响,而你反其道而行之。
你把 block 的部分纳入进来,既没有减少重复代码(该写的 Rust 语法还是得写),你也没有创造新的语法(该写的语法还是 Rust 语法),更无关变长参数。
我不懂,但我大受震撼:)
似乎你想把所有 Rust 语法放到一个宏里面,但这根本不必要。宏的主要作用(via Rust By Example):
大多数宏都尽量把解析内容尽可能缩小,从而尽可能不对编译(时间、优化等方面)很大造成影响,而你反其道而行之。
你把 block 的部分纳入进来,既没有减少重复代码(该写的 Rust 语法还是得写),你也没有创造新的语法(该写的语法还是 Rust 语法),更无关变长参数。
我不懂,但我大受震撼:)
如果回到大四作死选编译原理的那段时光
我觉得我能拿满分……
最后搞出来的macro整个就是一shift-reduce现场:
现在大概还需要处理一下block的问题
总觉得已经不是什么问题了
大不了if a==b {cai_exec!{}}解决……
正在研读https://danielkeep.github.io/tlborm/book/
之前明明感觉自己挺擅长Rust的
现在发现……我不会的还很多……
--
👇
苦瓜小仔: 其实还可以简化:
其实还可以简化:
好神奇
果然我不适合写marco
这么做应该相当完美了
作死试了试,只有类似下面这样的代码才不能通过编译(必须在里面多写一个
cai_exec!
)相关代码会被我整理之后送进
https://github.com/Neutron3529/obfuscate-integer
和crates.io
协议是
GPL-v3 or later
如果这么搞,我大概可以先自娱自乐一下,等想法成熟之后,再把“重载赋值函数”这个功能当RFC提出来
感谢你的帮助:)
--
👇
苦瓜小仔: 你可以试试这个:
你可以试试这个:
我想做一个可以正常翻译如下程序的marco
目前的成果是,发现了
$t:tt
这个比较好用的匹配工具,但,不知为什么匹配的时候总会出问题比如程序会觉得
let
像一个stmt
,从而报错说某个带:=
赋值的语句有歧义👇
苦瓜小仔: 是的:每条语法规则是你自己定义的,所以要解析语法。但你可以用其他技巧简化,比如 $( ... )? 表示零次或一次。
即使你用(函数式)过程宏,你也得自己解析语法。
你使用
cai_exec
不是解决了~
和:=
的问题吗?我不明白你的第二个问题 —— “一次marco解决所有问题”。是的:每条语法规则是你自己定义的,所以要解析语法。但你可以用其他技巧简化,比如 $( ... )? 表示零次或一次。
即使你用(函数式)过程宏,你也得自己解析语法。
你使用
cai_exec
不是解决了~
和:=
的问题吗?我不明白你的第二个问题 —— “一次marco解决所有问题”。完整marco(可以编译,但只能逐句加marco)的定义在这里
话说,想实现“一次marco解决所有问题”这个目标不会要用到#[proc_marco]吧……
感谢回复
你说的“宏”的确是一个好主意
我总觉得可以直接用宏完成我想做的事情(毕竟我只需要一个语法糖)
目前已经可以用宏把
:=
和~
绑定到对应的trait但这么做稍显繁琐
有没有办法把宏变成这样呢:
--
👇
苦瓜小仔: 我觉得原贴下的评论都在理啊,没有觉得你被“喷”。你只是听到合理的反对的声音而已。
你的在这里的帖子里的问题太多了,而且针对最核心的问题,你的确没有展示出强有力的理由说服别人接受或者使用你所定义的新符号。
正如 @H2CO3 所言:
从我自己的角度看,如果只是为了方便使用,完全可以试试宏,它的功能之一就是提供 DST —— 创造特定领域的语法,比如
r!(x~uniform)
。此外,语法简洁并不是编程核心考量的问题 —— 至少不是 Rust (及其社区)所主要考量的问题。
我觉得原贴下的评论都在理啊,没有觉得你被“喷”。你只是听到合理的反对的声音而已。
你的在这里的帖子里的问题太多了,而且针对最核心的问题,你的确没有展示出强有力的理由说服别人接受或者使用你所定义的新符号。
正如 @H2CO3 所言:
从我自己的角度看,如果只是为了方便使用,完全可以试试宏,它的功能之一就是提供 DST —— 创造特定领域的语法,比如
r!(x~uniform)
。此外,语法简洁并不是编程核心考量的问题 —— 至少不是 Rust (及其社区)所主要考量的问题。