首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

在宏展开时eval的奇怪行为

在宏展开时,eval的奇怪行为指的是在宏展开过程中使用eval函数的结果与预期不符的现象。eval函数是一种用于执行字符串形式的代码的函数,它接受一个字符串作为参数,将字符串解析为可执行的代码,并返回执行的结果。

在宏展开过程中,如果使用eval函数来执行某个宏参数或宏定义中的代码,可能会出现一些奇怪的行为。这是因为宏展开和eval函数的执行时机不同,导致eval函数执行的代码与宏展开后的代码不一致。

具体来说,eval函数在宏展开时的奇怪行为包括以下几点:

  1. 参数扩展:当将宏参数作为eval函数的参数进行执行时,宏参数的扩展可能会与预期不符。由于宏参数的扩展是在宏展开之前进行的,而eval函数是在宏展开之后才执行的,所以eval函数执行的代码中可能无法获取到正确的宏参数值。
  2. 宏展开顺序:在宏展开过程中,宏定义和宏调用的展开顺序可能会影响eval函数的执行结果。如果宏定义中包含了需要在宏展开之后才能确定的内容,而eval函数又依赖于这些内容进行执行,就会导致eval函数执行的结果与预期不符。
  3. 宏定义内部的eval:在宏定义中使用eval函数执行一些代码时,也可能出现奇怪的行为。由于宏定义是在宏展开之前就进行处理的,而eval函数是在宏展开之后才执行的,所以eval函数执行的代码中可能无法获取到宏定义内部的局部变量或宏参数。

针对这种奇怪行为,可以考虑使用其他方式来替代eval函数,例如使用宏展开时的字符串拼接、条件编译等技术来实现相同的功能。另外,对于涉及到复杂的代码执行需求,也可以考虑使用宏展开之外的运行时机制,例如函数调用等方式来实现。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Julia体验 语言特性 元编程,

这门语言因为受众不仅仅是程序员有很多让人迷惑设计,但是奇怪是它语法等表象设计虽然暗示这不是专门为程序员准备,内在却提供了大量非程序员不可用高级特性,库。...()h函数传入Expr类型参数求值: julia> eval(ast) 3 julia> eval(multiStmt) 21 这就给了我们一种使用代码操纵代码方式: julia> add = Expr...(:call,:-,:a,:b) :(a - b) julia> a = 1 1 julia> b= 2 2 julia> eval(add) -1 Julia由macro ... end...类似C/C++概念,Julia也是实施替换操作 所以上述println(@hello "Andrew")会被替换为println("hello, my name is Andrew"),可以使用...@macroexpand获得展开结果 julia> @macroexpand println(@hello "Andrew") :(println("hello,my name is Andrew"

92320

TiKV 源码解析(五)fail-rs 介绍

这是因为我们第一次打印完后才指定了这个 fail point 行为是 panic,因此第一次 fail point 不做任何事情之后正常输出,而第二次执行到 fail point 就会根据配置行为...当程序执行到某个 fail point ,获取并执行该全局 map 中所保存相应行为。 全局 map 其具体定义 FailPointRegistry。...,感兴趣同学可以去看看代码,太过细节在此不展开了;actions_str 保存着描述行为字符串,用于输出;而 actions 就是保存着 failpoint 行为,包括概率、次数、以及具体行为。...而代码到执行到 fail point 时候到底发生了什么呢,我们可以展开 fail_point! 定义看一下: macro_rules!...而 eval 就是从全局 map 中获取相应行为 p.eval(name) 中执行相应动作,比如输出、等待亦或者 panic。

80001
  • 【独家】Rust 1.70.0:详解新版本亮点与变化

    操作数需要按照严格顺序进行排序,这在某些情况下可能会导致使用上不便。版本中,这个规则被放宽,提高了 asm! 灵活性和易用性。 允许展开 format_args 调用使用捕获。... Rust 1.70.0 更新中,允许展开 format_args 调用使用捕获。这个更新主要是关于 Rust 系统。 Rust 中,(macro)是一种在编译进行代码扩展方式。..."允许展开 format_args 调用使用捕获" 这个更新含义是,当 format_args 在其体中使用变量,这些变量现在可以是外部作用域中变量,这就是所谓 "捕获"。...但是,这个 PR 已经被合并,所以这个改变已经 Rust 1.70.0 中生效。 const eval 中提前检测到了无法实例化类型。...这是一个破坏性改变,因为一些 const eval 期间未定义行为(UB)现在被检测到,而不是被默默地忽略。

    63230

    Clojure 运行原理之编译器剖析

    本文为第一篇,涉及到主要内容有:编译器工作流程、Lisp 机制。.../use使用 eval,当调用clojure.core/eval使用 这三个入口函数都会依次调用 macroexpand、analyze 方法,生成Expr对象,compile 函数还会额外调用...,form参数即是展开各种数据结构(String/ISeq/IPersistentList 等),返回值类型为Expr,可以猜测出,Expr子类是程序主体,遵循模块化编程风格,每个子类都知道如何对其自身求值...eval 每个 Expr 子类都有 eval 方法相应实现。下面的代码片段为 LispExpr.eval 实现,其余子类实现也类似,这里不在赘述。...,还有一点就是揭开了真实面貌,之前一直认为是个很神奇东西,其实它只不过是编译时运行函数而已,输入与输出内容既是构成程序数据结构,同时也是程序内在 AST。

    99930

    SAS-Macro 中那些语句(四)

    当然是不是的,变量计算是有俩个关键词%eval(只能进行整数运算),%sysevalf(可进行整数运算与小数运算).... data _null_; call symput('mvar1','...*&mvar2.); %eval进行运算变量有小数点是会有Error...那么来看看日志。 ? %sysfunc 前几天小编推送了一大堆SAS里面的基础函数,那么那些函数是否可以用呢?...*单个解析:用变量日志打印出 12*/ %put NOTE:&I&M; %put NOTE:%superq(I)%superq(M); /*双重解析:用变量日志打印出 你好*/ %put NOTE...%superq() 解析括号内作为一个整体变量, 这个关键词可以起到解析变量作用,当然此处还没有完全体现出%superqSAS中真正应用.... data _null_; call...据说%superq作用在执行期,SAS程序执行是先编译执行...猜完了,来看看日志... ? 奇怪奇怪

    4.1K22

    深入浅出 Babel 下篇:既生 Plugin 何生 Macros

    解释器或编译器遇到时会自动进行这一模式转换,这个转换过程被称为“展开(Macro Expansion)”。对于编译语言,展开在编译发生,进行展开工具常被称为展开器。...(X) : (Y)) 如果我们程序使用了这个,就会在编译阶段被展开,例如: MIN(a + b, c + d) 会被展开为: ((a + b) < (c + d) ?...,这里有一个Javascript实现 注意:一般在编译阶段被展开, 下面代码只是为了协作你理解上述Lisp代码 function nonsense(name) { let rtn eval...除了数据结构设计,现代编程语言机制还包含以下特性: 1️⃣ 卫生(Hygiene) 卫生指的是内生成变量不会污染外部作用域,也就是说,展开,Sweet.js 会避免内定义变量和外部冲突...So,上面的代码还不够健壮,我们再优化一下,求值失败给用户更好提示: defaultImport.forEach(referencePath => { if (referencePath.parentPath.type

    1.5K31

    (译) Understanding Elixir Macros, Part 6 - In-place Code Generation

    展开顺序 正如你所预料那般, 模块级代码(不是任何函数一部分代码)扩展阶段被执行. 有些令人意外是, 这将发生在所有(除了 def)展开之后....因为这段代码将在所有展开后运行. 例如, 请记住, 即使我们是从一个推导式中调用, 它也只会被调用一次. 但是, 生成代码将在推导式中运行 — 对每个元素运行一次....考虑下上面的 head 形状, 这是我们展开后最终会出现情况: # 调用者上下文 for {state, {action, next_state}} <- fsm do   # 这里是我们生成函数代码...试着确保你不是盲目地做 escapes(和/或 unquote: true), 而不理解这是你真正想要. 毕竟, 这不是默认行为是有原因....一定要记住 — 展开阶段, 相当于 AST 片段普通组合. 如果你理解调用者上下文和输入, 那么直接执行转换或在必要通过延迟执行转换并不算难. 本系列绝不可能涵盖方方面面和所有的细节.

    17840

    nodejs创建线程问题

    我们回头看一下返回非0,c++处理。我们对c++层CHECK_EQ(uv_thread_create_ex(…), 0)进行展开。...,因为他执行完我们处理函数后,会把处理函数注册为系统默认,然后再次发送SIGABRT信号,而默认行为就是终止进程。...总结:nodejs创建过多线程可能会导致进程终止。而我们无法阻止这个行为。...所以nodejs里使用多线程时候,我们需要注意就是不要开启过多线程,而在创建线程时候,我们也不需要关注是否成功,因为只要进程不挂掉,那就是成功。...对于业务错误我们可以注册error事件处理,new Worker时候,我们可以加try catch。可以捕获一下参数错误情况。

    97320

    【Rust日报】2023-11-29 Rust unsafe 代码中调试UB

    Rust unsafe 代码中调试UB 这篇文章讲述了 Rust 中调试UB代码遇到问题。...避免未定义行为方法: 可能探讨了编写不安全代码需要注意事项和最佳实践,以避免可能导致未定义行为问题。...ReadMore:https://hyphenos.io/blog/2023/debugging-ub-unsafe-rust-code/ 调查疯狂编译时间 作者提到了一些涉及编译器优化、展开、代码生成和编译时间案例和实践经验...编译器优化和技巧: 提到了一些编译器优化和技巧,例如减少不必要代码依赖、使用 #[cfg] 属性进行条件编译、减少展开等,以缩短编译时间。...展开影响: 讨论了展开在 Rust 中重要性以及展开可能导致编译时间增加。还可能提到了一些减少展开影响方法。

    12110

    C++:04---内联函数

    1.概念: 内联类似于定义,当程序执行到内联函数,相当于复制了一份函数代码。...”,C++中基本是被废了,书《高质量程序设计指南——C++/C语言》中这样解释到: ?...编译器调用点内联展开函数代码,必须能够找到 inline 函数定义才能将调用函数替换为函数代码,而对于头文件中仅有函数声明是不够。...但相比于放在源文件中,放在头文件中既能够确保调用函数是定义是相同,又能够保证调用点能够找到函数定义从而完成内联(替换)。 但是你会很奇怪,重复定义那么多次,不会产生链接错误?...(递归调用堆栈展开并不像循环那么简单, 比如递归层数在编译可能是未知, 大多数编译器都不支持内联递归函数).

    1.3K40

    听GPT 讲Rust源代码--compiler(48)

    当代码中使用到这些内建,编译器会在编译期间将它们展开为对应代码。这种在编译期间进行展开方式可以在编译进行语法检查,并且减少了运行时开销。...Rust中,是一种元编程工具,可以在编译生成代码,因此其语法形式可能相对复杂。 该文件实现了log_syntax!,它是一个帮助开发人员调试和理解展开过程辅助工具。...,会在指定位置记录展开详细信息,包括名称、参数、语法结构等等。...每个展开函数都是一个闭包,接受输入TokenStream并返回展开TokenStream。 在编译器启动,会调用env.rs中定义函数来初始化内置环境结构。...这个过程会注册每个内置名称和对应展开函数。然后,当编译器遇到使用内置代码,会在内置环境结构中查找对应展开函数,然后调用这个函数来执行展开操作。

    10510

    由phithon一个题目谈可变参数函数

    可变参数 可变参数函数是指参数个数可变函数,函数声明和定义时候并没有明确指出函数需要参数个数,具体有多少个参数,是调用时候确定....自己动手写可变参数函数 c语言中要实现一个可变参函数,需要用到一下 void va_start( va_list arg_ptr, prev_param ); type va_arg( va_list...arg_ptr, type ); void va_end( va_list arg_ptr ); 这些定义stdarg.h头文件中,所以写可变参数函数时候需要包含此头文件. gcc编译器使用内置间接实现变参...php5.6引入了一个新特性,PHP中可以使用 func(...arr)这样方式,将arr数组展开成多个参数,传入func函数。...$_GET); $_GET变量 被展开为两个参数 [‘test’,’phpinfo();’]和assert,传入usort函数.usort函数第二个参数是回调函数assert,执行了第一个参数中phpinfo

    1.2K10

    静态作用域和动态作用域

    其原因是采用静态作用域规则时候,对于函数定义者来说,他可以通过阅读自己代码很容易地知道他所使用到变量当前绑定具体实体是什么,而在使用采用动态作用域语言,则需要考虑这个函数被调用时候该变量所对应具体实体...,这事实上是一种破坏封装行为。...表达式定义捕获外部环境,我们在这个环境中求 closure body 值,当然,参数绑定形成作用域要被放在 capture 环境开头。...当我们在当前作用域中找不到一个名字,我们会先查找函数被调用空间。 C++ 中模拟动态作用域 上一节讲的是解释器中实现两种作用域方式,那如果我们就是想在现有的语言里模拟这个特性呢?...其实说 C++ 完全是静态作用域语言是不完全正确,C++ 系统由于是直接展开,所以它是根据展开位置来判定其值到底是多少,所以本身是类似于动态作用域,例如: #define ADD_N(x) (

    2.1K10

    iOS中预编译指令初步探究

    类似这样#define X A是比较简单,在编译编译器会在语义分析认定是后,将X替换为A,这个过程称为展开。...函数顾名思义,就是行为类似函数,可以接受参数。具体来说,定义时候,如果我们名字后面跟上一对括号的话,这个就变成了函数。...终于弄明白了这个奇怪do while之后,我们终于可以继续深入到这个里面了。...__FILE__返回当前文件绝对路径,__LINE__返回展开文件中行数,__func__是改所在scope函数名称。...而实际上日常中很多我们常用并没有那么多奇怪问题,很多时候我们按照想法去实现,再稍微注意一下上述介绍可能存在共通问题,一个高质量就可以诞生。

    2.3K80

    javascript 中 delete

    MDC文章 可能是最全面的资源,但遗憾是错过了一些有趣细节; 奇怪是,这些被遗忘事情之一正是Firebug复杂行为原因.而 MSDN参考手册 几乎是无用. 1....嗯,正如我之前所说,Eval代码变成变量声明时有一个特殊行为.Eval代码内声明变量实际上是没有 DontDelete 标志: [javascript] view plaincopy eval...Eval代码中声明变量和函数创建 properties 没有DontDelete标志. 新指定properties 创建标志位是 empty (所以没有DontDelete标志)....MDC文章 可能是最全面的资源,但遗憾是错过了一些有趣细节; 奇怪是,这些被遗忘事情之一正是Firebug复杂行为原因.而 MSDN参考手册 几乎是无用. 1....嗯,正如我之前所说,Eval代码变成变量声明时有一个特殊行为.Eval代码内声明变量实际上是没有 DontDelete 标志: [javascript] view plaincopy eval

    3K80

    听GPT 讲Rust源代码--compiler(47)

    用户可以该文件中重写全局错误处理器以自定义内存分配失败行为。...用户可以通过修改该文件或使用自定义函数来自定义内存分配失败行为。...结构体和枚举定义文件中不同位置,具体作用可以根据名称及注释进行推断。总体上,这些结构体和枚举定义了展开过程中需要一些操作和数据结构,以便于派生特定trait进行相应处理和解析。...Rust中,panic用于程序遇到不可恢复错误时终止程序执行。 随着Rust语言发展和不同版本之间更改,panic每个版本中行为可能会有所不同。...通过定义和函数来统一处理这些差异,确保不同版本Rust中,panic行为都保持一致。

    10410

    精致全景图 | 系统调用是如何实现

    将该展开后,我们可以得到如下函数定义: 由上可见,SYSCALL_DEFINE3展开后为三个函数,其中只有__x64_sys_write是外部可访问,其它两个都有被static修饰,不能被外部访问...这就奇怪了,那各系统调用函数到底是在哪里注册呢?...那也就是说,regs参数字段里,是带着各系统调用函数所需参数,SYSCALL_DEFINE等展开出来一系列函数,会从这些字段中提取出真正参数,然后对其进行类型转换,最后这些参数被传入到最终系统调用函数中...对于上面的write系统调用展开那些函数,__x64_sys_write会先从regs中提取出di, si, dx字段作为真正参数,然后__se_sys_write会将这些参数转成正确类型,最后...调用do_syscall_64方法之前,对rdi和rsi赋值,是为了遵守c calling convention,因为该calling convention中约定,调用c方法,第一个参数要放到rdi

    1.1K30

    听GPT 讲Rust源代码--compiler(37)

    它负责将宏规则中语法树转换为相应代码,并执行相应展开操作。 NoopTracker:这个struct是一个空跟踪器,它在展开不会产生任何输出。...这些trait作用如下: Tracker:这个trait表示展开跟踪器。它定义了一些展开可能调用方法,用于跟踪展开过程。...Rust中,展开是一种通过定义生成代码方式。展开过程中,需要进行一些语义上检查,以确保生成代码是合法。 详细介绍: BinderInfo: 该结构体存储了展开过程中绑定信息。...等结构体用于表示信息和处理展开过程,而AstFragment、AstFragmentKind、SupportsMacroExpansion、InvocationKind和AddSemicolon等枚举类型用于描述展开结果和行为...除此之外,还有一些enum作用如下: ConsumeClosingDelim: 这个enum用于表示解析器解析过程中遇到右侧闭合分隔符行为

    12410
    领券