10
17
2014
7

(lib)Tcl 现代方法:变量

之前有人问到如何从 C 端访问 Tcl 变量,此处做一总结。庶几不失「现代」之名。有关 Tcl_Obj 的维护者资料击此

于是终于回到了主线。《Tcl 现代方法》本来是作为记录 Tcl 现代用法的系列博文,一开始是介绍 C 库的,但是后来 Tcl 脚本的内容反倒更多,结果现在纯粹谈起来 C 库又会导致歧义,因此在标题前加上 lib 标记,以示内容是 C 库而非 Tcl 脚本。

背景

Tcl 自 8.0 起,引入了 Tcl_Obj 系统,该系统在保留 Tcl 「Everything is a String」原则的同时,大大提高了程序效率,可以总结成这样:Tcl 变量存在一个显类型(Tcl 端类型)和隐类型(C 端类型),程序员脑中又有一个实用类型,显类型一定是字符串,但实际上实用类型并不一定是显类型,而使用隐类型的一种或多种,如 for 循环中的计数器 i,实用整数类型,而显类型则是字符串,隐类型应当是 int。

在过去,显类型和隐类型都是字符串,导致计数器 i 每次循环都会走一遍「字符串->整数->字符串」,效率极差。Tcl_Obj 则将字符串表示和隐类型数据一起保存,每当需要字符串时,就直接返回字符串,需要隐类型数据时,就直接返回隐类型数据;如果两者不匹配,则将其中过期了的一种更新。如每次 for 循环中如果有 puts $i,则会每次都更新一次 i 的字符串表示然后打印;如果在 for 循环外执行 puts $i,则只会造成一次字符串表示更新。更新隐类型数据同理。

说来好玩,因为一开始没用 Tcl_Obj,所以 Tcl 有一套相当强大的字符串处理函数,叫做 Tcl_DString(dynamic string),因为不推荐用于变量,而且比较直观,一看就懂,故而此处不做讨论。

另外注意,我提到的隐类型、显类型、实用类型,都是为了讨论方便自己提出的,实际上 Tcl 界乃至编程界并没有这样的说法(或许会有类似的讲法,如果你知道请务必告诉我)。

看上去好像很复杂,其实规则很简单:dual-ported (internal representation and string representation); cache of each other and computed lazily.

不过絮叨一大串,其实本文不介绍 Tcl_Obj 用法,只是个背景而已。

示例代码

A piece of code is worth a thousand words.

#include <tcl.h>

int z = 0;

void ObjRW(Tcl_Interp *interp)
{
    Tcl_Obj *xObj;
    double val;

    /* Read */
    xObj = Tcl_GetVar2Ex(interp, "x", NULL, 0); /* not incr'ing its refcount */
    Tcl_GetDoubleFromObj(interp, xObj, &val); /* not incr'ing its refcount */
    printf("x = %lf\n", val);
    /* Write */
    Tcl_SetDoubleObj(xObj, 6.28);
    xObj = Tcl_SetVar2Ex(interp, "x", NULL, xObj, 0); /* not incr'ing its refcount */
    /* Read (again) */
    Tcl_GetDoubleFromObj(interp, xObj, &val);
    Tcl_DecrRefCount(xObj);
    printf("x = %lf (new)\n", val);
}

/* Inefficient in most cases. Use Tcl_Obj instead. */
void StrRW(Tcl_Interp *interp)
{
    /* the string representation of y will be updated and returned */
    printf("y = %s\n", Tcl_GetVar(interp, "y", 0));
    Tcl_SetVar(interp, "y", "42", 0); /* now the "real" data will be outdated */
    printf("y = %s (new)\n", Tcl_GetVar(interp, "y", 0));
}

void LinkedVar(Tcl_Interp *interp)
{
    Tcl_Obj *zObj;
    int value;

    /* Original value */
    zObj = Tcl_GetVar2Ex(interp, "z", NULL, 0); /* Tcl simply returns our z */
    Tcl_GetIntFromObj(interp, zObj, &value);
    printf("z = %d\n", value);
    Tcl_DecrRefCount(zObj); /* delete the old obj */
    /* C-side */
    z = 10;
    zObj = Tcl_GetVar2Ex(interp, "z", NULL, 0); /* not incr'ing its refcount */
    Tcl_GetIntFromObj(interp, zObj, &value);
    printf("z = %d (C new)\n", value);
    /* Tcl-side */
    Tcl_SetIntObj(zObj, 100);
    Tcl_SetVar2Ex(interp, "z", NULL, zObj, 0); /* update the var */
    Tcl_DecrRefCount(zObj);
    printf("z = %d (Tcl new)\n", z); /* our own z got updated */
}

int main()
{
    Tcl_Interp *interp;
    Tcl_Obj *var1, *var2; /* var1 double, var2 int */

    /* Initialize */
    interp = Tcl_CreateInterp();
    /* Create Tcl_Obj's */
    var1 = Tcl_NewDoubleObj(3.14);
    var2 = Tcl_NewIntObj(99);
    /* Create variables */
    /* Not incrementing the refcount means we transfer the ownership */
    Tcl_SetVar2Ex(interp, "x", NULL, var1, 0); /* NULL means x isn't an array */
    Tcl_SetVar2Ex(interp, "y", NULL, var2, 0);
    Tcl_LinkVar(interp, "z", (void *)&z, TCL_LINK_INT); /* MAGIC! */
    /* Read/write them */
    ObjRW(interp);
    StrRW(interp);
    LinkedVar(interp);
    /* Finalize */
    Tcl_UnsetVar(interp, "x", 0);
    Tcl_UnsetVar(interp, "y", 0);
    Tcl_UnsetVar(interp, "z", 0);
    Tcl_DeleteInterp(interp);
    return 0;
}

参考文献

(写这么一节参考文献,应该能让我的博客看上去更专业吧smiley

  1. Tcl Source Code Wiki
  2. Tcl man pages
  3. 《Tcl/Tk 入门经典》,中文版第二版
Category: 编程 | Tags: tcl tcl 现代方法 | Read Count: 3066
Avatar_small
rca 说:
Oct 23, 2014 08:56:57 AM

这么古老的东西,好玩么

Avatar_small
Mike Manilone 说:
Oct 25, 2014 10:27:05 AM

@rca: 很有意思的,和 Lisp 的可玩性差不多。不过毕竟确实老了些,没有闭包,但是其他东西都很全。

mega888 apk 说:
Aug 30, 2021 12:05:56 AM

I propose merely very good along with reputable data, consequently visualize it:

Satta king 说:
Sep 25, 2021 05:17:55 AM

Profit primarily prime quality items -- you can understand them all within:

J&K 11th Model Paper 说:
Aug 16, 2022 10:33:29 PM

This JKBOSE Class Xllth Exams were administered by the Jammu and Kashmir State Board of School Education. upon the satisfactory completion of the exam. The Jammu and Kashmir 11th Question Paper 2023 for the JKBOSE Class 11th Exam will be released soon by the JK Board. All students who choose to pursue further education should take this test seriously since, upon completing it, J&K 11th Model Paper 2023 they will be able to pursue a variety of professional paths as well as enrol in undergraduate, diploma, and ITI programmes. JK Board will release the JKBOSE Class 11th test Question Paper 2023 in the month of May on the same official web portal site, according to the official announcement.

AP 10th Physics Ques 说:
Sep 17, 2022 10:06:40 PM

Physical Science is the part of Science known as Physics (PS), every student in class 10th grade studying at Government & Private Schools of the state board can download the AP SSC PS Model Paper 2023 with answers for all topics of the course designed by the board experts based on the new revised syllabus and curriculum of the BSEAP. Either Telugu medium, English medium and Urdu medium students of class 10th can download the AP SSC Physics model papers 2023 to practice with regular revisions and mock tests. AP 10th Physics Question Paper Class teachers and leading institutional experts are prepared those AP 10th Class PS Model Paper 2023 Pdf with answers that support all exam formats of the board such as Summative Assessments (SA-1 & SA-2) and Formative assessments (FA-1, FA-2, FA-3, FA-4) along with Assignments.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Powered by Chito | Hosted at is-Programmer | Theme: Aeros 2.0 by TheBuckmaker.com