Introduction to MWB Minor Mode

2014年9月03日 00:11

Introduction to MWB Minor Mode

Table of Contents

继续阅读

假设有一个容器中存放着 int ,Container<int> c, 现在想从其中删除数值 1963,可以有如下方法:

1: c.erase(remove(c.begin(), c.end(), 1963), c.end()); // c is continguous memory container
2: c.remove(1963); // c is list
3: c.erase(1963)   // c is standard associative container

对于 continguous memory container 来说, std::remove() 可以保证返回的 iterator 之前的内存中不包含被删除的值,配合 erase 来用,形成所谓的 erase-remove idiom 。而对于 List 来说,应该调用 list 本身的 remove() 方法。对于 map,set 等等,则必须使用 erase() 方法,而不能使用 remove() ,对 associative container 使用 remove() 可能会覆盖容器存储的内容,甚至破坏容器。

假设我们现在想给定一个条件( bool badValue(int x) )并用这个条件来判断有哪些 Entry 需要删除,对 vector、string、deque、list 可以用下列方法:

1: c.erase(remove_if(c.begin(), c.end(), badValue), c.end()); // for vector, string, deque ...
2: c.remove_if(badValue); // for list.

associative container 没有类似的方法,但可以自行遍历删除:

AssocContainer<int> c;
for (AssocContainer<int>::iterator i=c.begin(); i != c.end(); ++i)
{
    if (badValue(*i))
    {
        c.erase(i); //XXX: This is wrong: when this get executed, iterator will become
                    //XXX: invalid, and ++i will lead to undefined behaviour.
    }
}


for (AssocContainer<int>::iterator i=c.begin(); i != c.end(); /*Nothing*/)
{
    if (badValue(*i))
    {
        c.erase(i++); //XXX: This works, because we are passing unincreased value to erase,
                      //XXX: but we get it increased before it was passed to erase().
    }
    else
    {
        i++;
    }
}
 

(使用许可:署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议 。)

 

 

假设有个文件里面记录的一系列的 int 值,现在我们想把这些数值存到一个 List 里面,结合 Item 5, 我们可能会写出下面的代码:

ifstream dataFile("ints.data");
list<int> data(istream_iterator<int>(dataFile), // Start of iterator
               istream_iterator());             // End of iterator

这段代码可以编译,但运行时并不工作,它不会去调用 list 的构造函数,从而不会生成我们想要的这个 List。

问题,出在 C++ 对代码的解析上。

假设我们需要声明一个函数,该函数接受 double 类型参数并返回 int 类型,C++ 里面,下面三种方法是等效的:

1: int f(double d);  // Old C style.
2: int f(double(d)); // Function style casts.
3: int f(double);    // Same as first but skip parameter.

如果我们要声明另外一个函数,该函数同样返回 int,但接受的参数是一个无参数但返回 double 的函数的指针,则下面的声明是等效的:

4: int g(double (*pf)()); // g takes a pinter to a function as paramter.
5: int g(double pf());    // same as above
6: int g(double ());      // same as above, but parameter (function name) skipped.

观察 1 ~ 6 我们可以看到“ 括号”在不同位置时候的不同作用:

  • 参数 周围的括号可以被忽略
  • 单独 的括号实际上意味着这是一个函数指针的参数列表!

了解了这个区别之后再返回来看最开始的那个声明:

list<int> data(istream_iterator<int>(dataFile), istream_iterator<int>());

这个声明定义了一个返回 list<int> 的函数,该函数接受两个参数:

  • 第一个参数名为 dataFile,类型为 istream_iterator<int>,dataFile 两遍的括号可以忽略。
  • 第二个参数是一个函数指针,该函数不接受参数但返回一个 istream_iterator<int>。

这个和我们最开始想象的完全不一样,而产生分歧的原因就在于 C++ 对代码的解析上:

    只要表达式可以被解析成 函数 ,那么该表达式 就会被编译器解析成函数

想象一下下面这段代码,相信很多人都写出来过,但是它能编译么?

 7: class Widget
 8: {
 9: public:
10:     Widget(){}
11:     virtual ~Widget(){}
12:     void Show(){}
13: };
14: 
15: Widget w();
16: w.Show();

上面片段的第 8 行实际上不是声明了一个 Widget 对象,而是声明了一个用来返回 Widget 对象的函数,第 9 行自然也就出错了。

理解了上面的内容,也就可以想想怎么解决开始时提出的问题了:给形参声明加上括号不合法,但给函数调用的实参加括号是合法的,通过适当的添加括号,问题得以解决:

1: list<int> data((istream_iterator<int>(dataFile)),
2:                istream_iterator<int>());

这里第一个参数周围添加了多余的括号,假设编译器仍然认为 data() 是一个函数声明,则第一个形参周围就被添加了括号,这是一个非法的行为,所以编译器会丢掉这种可能,转而匹配下一种可能得匹配,认为该表达式声明了一个 list<data> 的变量,并调用适当的区间函数(Item 5)来进行初始化。

但并非所有的编译器都支持这种匿名对象,如果编译器不支持,我们需要下面的这种显示的写法:

1: ifstream dataFile("ints.dat");
2: istream_iterator<int> dataBegin(dataFile);
3: istream_iterator<int> dataEnd;
4: list<int> data(dataBegin, dataEnd);

这种写法应该通用。

gentoo emerge unable to sync

2014年9月03日 00:10

 

 

gentoo emerge unable to sync

Author: Tubo

After setting SYNC to customized URL:

SYNC="rsync://mirrors.stuhome.net/gentoo"

emerge –sync always reports error:

rsync: change_dir "/metadata" (in gentoo) failed: No such file or directory

After google, it turns out that the url which was coppied from http://www.gentoo.org/main/en/mirrors-rsync.xml was wrong, as golagoda said at: http://forums.gentoo.org/viewtopic-t-902498-start-0.html: "On most portage mirrors it's gentoo-portage not gentoo, so you might want to try that."

And updating SYNC to

SYNC="rsync://mirrors.stuhome.net/gentoo-portage"

fixed this issue.

 

1 Item 4: Call empty instead of checking size() against zero

简而言之,用 container.size() 来检查 container 是否为空,而不要用 /container.size() == 0/。

原因: empty is a constant-time operation for all standard containers, but for some list implementations, size takes linear time.

2 Item 5: Prefer range member functions to their single-element counterparts

如果 Container 提供了区间成员函数 (Range member functions),尽量用它来替代自己写的循环和 algrithm 中的 copy 。

A range member function is a member function that, like STL algorithms, uses two iterator parameters to specify a range of elements over which something should be done.

Range member function 的好处在于:

  • 代码量更少,更清晰、直观。
  • 有可能会减少申请内存的次数, 减少数据的移动次数。

Range member function 适用的几种情况:

  1. 容器的构造: 所有标准容器都提供该方法:
    container::container(InputIterator begin, // Beginning of range
                         InputIterator end);  // End of range
    
  2. 区间插入: 所有标准容器都提供该方法:
    void container::insert(iterator      position, // where to insert the range
                           InputIterator begin,    // start of range to insert
                           InputIterator end);     // end of range to insert
    

    由于关联容器 (Associative Containers) 有自己的方法来计算插入的位置,insert 方法的第一个 参数经常可以省略:

    void container::insert(lnputIterator begin, InputIterator end);
    
  3. 区间删除 (Range Eraure):

    所有标准容器都提供了区间删除方法,但返回值有所不同:

    • Sequence Container:
      iterator container::erase(iterator begin, iterator end);
      
    • Associative Container:
      void container::erase(iterator begin, iterator end);
      
  4. 区间赋值 (Range Assignment): 所有 Container 均提供:
    void container::assign(lnputIterator begin, InputIterator end);
    

 

容器 (Containers) 用来存储对象 (Objects), 但是被存储的对象却并非原原本本是你给他的那一个, 而是你指定对象的一个拷贝。而后续对该容器内存储对象的操作,大多也是基于拷贝的。 拷贝操作通过类的成员函数 copy constructor 或者 copy assignment constructor 来完成( 如果用户 没有自己声明这两个函数,编译器会自动生成他们):

class Widget {
public:
    Widget(const Widget&); // copy constructor
    Widget& operator=(const Widget&); // copy assignment operator
    // Other functions.
};

如果拷贝构造函数以及拷贝赋值函数的调用开销过于昂贵,将其置于容器中,不断的拷贝有可能会成为程 序的瓶颈。

此外,考虑到类的继承,尝试将子类的对象push 到父类的 Container 中,会引起 “切片 ”问题:

vector<Widget> vw;
class SpecialWidget:    public Widget {...}; // SpecialWidget inherits from // Widget above
SpecialWidget sw;
vw.push_back(sw); // sw is copied as a base class object into vw. Its specialness  is lost
                  // during the copying

上面的例子中,将 sw push_back 到 vw 中时,被调用的 Copy Constructer 是父类 Widget 的,而非 SpecialWidget 的,这样最后存在 vw 中的对象已经不包含任何的 sw 信息,任何尝试调用 vw 特有的方 法都将失效。。。

对此的一个简单 fix 是:别在 Container 中保存对象,转而保存对象的指针,尤其是 shared pointer。

理解 STL 的 Copy。

(使用许可:署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议 。)

Adding Completion to (interactive)

2014年9月03日 00:10

 

 

Adding Completion to (interactive)

Author: Tubo

Question:

Is there any way to add my own completion to an (interactive) elisp function? Ideally, I'd
like to pass it a list of strings that it would tab-complete from. I know that using (interactive "D"), (interactive "F") or (interactive "b") give you completion for directories, files and buffer-names respectively, but what about more general inputs?

Answer:

The argument to interactive need not be a string; if it isn't, it's evaluated to get the list of arguments to pass to the function. Therefore, you can do something like this:
(defun insert-foo-bar-or-baz (arg)
  (interactive
   (list
    (completing-read "Choose one: " '("foo" "bar" "baz"))))
  (insert arg))

 

I have a problem connecting HTC Wildfire A3333 in debugging mode with my Fedora Linux 17. Adb says:

./adb devices
                            List of devices attached 
                            ????????????    no permissions
                            

my udev rules (first rule for Samsung which works just fine and second for HTC which is not):

SUBSYSTEM==”usb”,SYSFS{idVendor}==”04e8″,SYMLINK+=”android_adb”,MODE=”0666″,GROUP="plugdev" 
                            SUBSYSTEM==”usb”,SYSFS{idVendor}==”0bb4″,SYMLINK+=”android_adb”,MODE=”0666″,GROUP="plugdev"
                            

For Samsung devices everything's okay:

 ./adb devices
                            List of devices attached 
                            00198a9422618e  device
                            

I have been trying all of the answers given in a simmilar thread wthout any luck: Using HTC wildfire for android development

 

ANSWER:

I just had this problem myself under Debian Wheezy. I restarted the adb daemon with sudo:

1. sudo ./adb kill-server
                            2. sudo ./adb start-server
                            3. sudo ./adb devices
                            

Everything is working :)

 

重构一种对软件进行修改的行为,但它并不改变软件的功能特征,而是通过让软件程序更清晰,更简洁和更条理来改进软件的质量。代码重构之于软件,相当于结构修改之于散文。每次人们对如何对代码进行重构的讨论就像是讨论如果对一篇文学作品进行修订一样无休无止。所有人都知道应该根据项目的自身情况来对代码进行重构,而重构是无止境的。莫扎特从来不不对他的作品进行修订,特罗洛普对自己作品修订的恰到好处,大多数作家认为他们俩这样做都是合适的,但他们的合适对于你我来说未必是合适的。

最常见的基本重构方法可以归纳为两个方向。通过归纳方法将一个长的过程分解为小的可以重用的组件,和通过内联(inline)方法来消除那些不够份量的小方法。我们可以提炼方法来让大量的子类共享相同的功能特征,我们可以下放方法来让只有用到这些功能的子类才知道它们的存在。重构就是爬山,通过一步一步的小的提高来逐渐的改进整体的质量,但在重构时,我们如何知道哪种方法是上山的正确道路?

关于代码地形学的这个问题公认的方法有两种。去除有异味的代码重构成模式。如果能做到这样,当然是很好的。就像是纠正作文里的一个语法错误或不恰当的比喻。如果我们可以找到这些四处隐藏的有异味的代码,将它们重写成整洁的,条理的,结构化的形式,何乐而不为。但这些都是特殊情况。如果没有明显的模式来重构,或没有很直接的方法来去除代码异味,那该怎么办呢?

这才是我们如今编程艺术的中心问题,而很少人讨论这些。通常我们讨论这些问题时都是罗列出更多更长的有异味的代码模式的清单,但这并不是解决问题的方法。代码异味应该是我们公认的不好的东西,而不是那些置之不理也无妨的事情。我们经常会说到老板不给我们重构的机会,甚至代码有明显的异味,老板们认为这是浪费时间。并不是每个人都有懂软件的老板。我很吃惊为什么只有很少的讨论谈到点子上。。也许我这篇文章才说到问题关键处。

我的观点,当重构没有现成的明显的方向时,我们可以遵循下面的原则:

  1. 当属性、方法或类存在任何的需要复用的意向时,归纳提炼它们。
  2. 不要低估小方法对代码整洁的作用。使用小方法能让你节省很多笔墨。
  3. 能让代码长度变短的提炼都应该去提炼,包括注释。
  4. 用switch()代替多形——即使这样做会使代码变长。
  5. 用封装控制可见度。
  6. 消除依赖。
  7. 简化构造方法——即使这样做会使代码变复杂。
  8. 封装或避免条件表达式。使用guard语句,避免使用else语句。
  9. 使用常量代替魔幻数字。
  10. 不确定时,偏向使用组合而不是继承。
  11. 不确定时,将计算操作移入到这些数据的所有者对象里,或将数据移动到执行计算操作的对象里(也就是迪米特法则(Law of Demeter))。
  12. 使用小对象,松耦合,避免大对象,高聚合。
  13. 不确定时,偏向使用递归而不是循环。
  14. 使用代理对象,模拟对象和辅助对象来隔离网络,数据库,文件和用户接口。
  15. 不确定时,尽量在model里添加代码,必要时才往controler添加代码。view里添加的都应该是便捷功能和简写方法,但不要局限于此。
  16. 偏向使用apply, each, mapcar,而不是loop.
  17. 尽量使用新技术。
[英文原文:Hill Climbing (Wonkish) ]

Refactoring is a process of editing software that doesn’t change what the software does, but instead improves it by making it more clear, more concise, or more direct. Refactoring is to code what structural editing is to prose. The debate about the utility of refactoring is just a rehash of the perpetual debate about revision. Everyone agrees that you ought to revise and that you never can revise enough. There are people like Mozart and Trollope who never revise and who do just fine, but most writers agree that’s fine for them and not a great idea for you and me.

Most of the classic refactorings run in two directions. We can Extract Method to break a long procedure into small and reusable components, and we can Inline Method to get rid of a small method that’s not pulling its weight. We can Pull Up Method to let a bunch of subclasses share common behavior, or we can Push Down Method so only the subclass that uses this behavior needs to know about it. Refactoring then becomes a matter of hill climbing, gradually improving the entire work by making a series of minor changes that facilitate larger and larger changes. When refactoring, how do we know which way is up?

Two broad approaches to the topography of code have been proposed. We move away from code smells, and we refactor toward patterns. These make sense, as far as they go. We should repair blunders in code just as we’d fix grammatical accidents or mixed metaphors, and if we see an opportunity to take some scattered code and rewrite it in a clean, ordered, and structured manner, that’s always a good idea. But these are exceptional cases. How do we refactor when there’s no grand pattern at hand and where we don’t see a straightforward way to expunging a code smell?

This is a central question of the craft of software today, and it’s seldom discussed. We talk around the question by contriving ever longer lists of code smells, but that’s not really a solution: code smells should be things we agree are usually or always bad, not things that might often be perfectly fine. We talk around the question by assuming that management won’t let us refactor even the obvious cases and so worrying about subtle situations is a waste. But not everyone has a pointy-haired boss. I’m surprised there’s so little literature on this question. I think at this point I’ve covered the books, but perhaps I’ve missed great stuff in the journal literature. Email me.

My two cents holds that, when the direction of refactoring is not immediately clear, we drive the ponies in the following directions:

  1. Extract fields, methods, and classes when there is any prospect of eventual reuse by additional methods.
  2. Do not underestimate the impact of tiny methods on cleaning up your code. Invoking small methods let you omit needless words.
  3. Extract whenever extracting reduces the length of code — including comments (not counting doc comments required by coding standards, which don’t count).
  4. Prefer polymorphism to switch(), even if the code is longer.
  5. Prefer encapsulation to visibility.
  6. Break dependencies.
  7. Simplify constructors, even if it complicates the code.
  8. Encapsulate or avoid conditional expressions. Prefer guard expressions and avoid else clauses. The gate is straight down.
  9. Prefer a dedicated type to a primitive, even if the code is longer; it’s better to pass Money than an integer even if you know the integer is money.
  10. When in doubt, prefer composition to inheritance .
  11. When in doubt, move computation to the object that owns the data or move the data to the object that does the computation (aka Law of Demeter).
  12. Prefer small objects, loosely coupled, to large objects and to tight coupling.
  13. When in doubt, prefer recursion to loops.
  14. Isolate the network, the database, files, and the user interface with facades, fakes, and humble objects.
  15. When in doubt, add code to the model if you can, to the controller if you must. Regard any work in the view as a convenience function or syntactic sugar, but don’t let that stop you.
  16. Prefer blocks (apply, each, mapcar) to loops.
  17. Prefer new technology.

Porting of cURL to Android OS using NDK

 

继续阅读