搜索
查看: 17315|回复: 133

灵活的可变参数

    [复制链接]

75

主题

880

帖子

5101

积分

六级会员

The only one

Rank: 9Rank: 9Rank: 9

积分
5101
发表于 2012-10-30 15:45:56 | 显示全部楼层 |阅读模式
本帖最后由 look 于 2012-10-30 15:54 编辑

一,先看下帮助文档中可变参数的讲解


1、在形参列表尾部定义可变参数在定数定义的形参列表尾部,可以用三个连续的圆点表示可变参数(不定参数)。
可变参数必须是最后一个参数,如下:

io.open()

func = function( a,b, ... ){ //使用三个连续的圆点表示任意个数、任意类型的参数
    var arg = { ... }
    io.print( #arg +
"个参数", arg[1],arg[2] )
}

func(1,2,99,888,777);


2、在实参列表尾部使用可变参数
在实参列表尾部可以使用可变参数

io.open()

str ="abcd"

//在实参尾部可以使用不定参数
io.print( "string.unpack有多个返回值",string.unpack(str) );

//可变参数不放在最后面就只能取第一个值
io.print( string.unpack(str) ,"string.unpack的第一个返回值");



二,实际应用中,如何在中间或者前面使用可变参数(实参)
        大家看到我上面的标题,是不是感觉和帮助文档有些冲突?
答案是否定的,答案在aardio中自带的范例和标准库源码中.
1,中间实参可变的范例--->模拟自动化-->鼠标按键--->超级热键演示    部分代码如下;
hotkey.reg(
    "CTRL","K",
   
function(hwnd,...){
        ..winex.say(
"你按了CTRL+K!")
    }
)

hotkey.reg(
   
"CTRL","K","K",
   
function(hwnd,...){
        ..winex.say(
"你按了CTRL+K,K!")
    }
)

看到了吗? 注意看hotkey.reg()最后一个参数是个固定参数,而前面参数是不固定的,
如果你不看源码,会不会认为hotkey.reg()函数定义如下:

hotkey.reg=function(...,func){
   
//....代码略
}

你可以很奇怪这样是不是和帮助文档中所讲有冲突?下面看看源码中是怎么实现的
    reg = function(...){
        
var tab = {...};
        
if(#tab<2)
            
error("至少要指定一个热键、一个触发函数",2)
            
        
var func = tab[#tab];//这里把可变实参中的最后一个参数取出作为回调函数
        var t = type(func)
        
if( ( t != type.function) && ( t != type.string ) ){
            
error("最后一个参数必须是函数对象或字符串",2)
        }
        
        
var root = {}
        
var node = this.actions
        
var vk ;
        
//以下代码处理除最后一个参数
        for(i=1;#tab-2;1){
            vk =   ..key.getCode(tab[ i ] ) ;
            
if(!vk)
               
error("指定了错误的按键,位置:"+i,2)
            
if( ! node[ vk ] ){
                node[ vk ] = {};
            }   
            node = node[ vk ]  
        }
         
        vk = tab[#tab-1];
        vk = (vk !=
'\0' )? ( ..key.getCode(vk) ): 0
        
        
if( type(func) == type.string ){
            func =
loadcode(func) : func;
        }
        
if(!node[ vk ])
            node[ vk ] = {};
            
        node[ vk ].event = func;
    }

大家看了上面的代码有些晕,下面来个简单的,和上面功能差不多的;
import console;

最后一个固定=
function(...){
   
var tab = {...};
   
var func=tab[#tab]
    table.pop(tab);
    func(table.unpack(tab))
}

//调用试试
最后一个固定(
    123,
   
"呵呵",
    {1;2;5},
   
function(...){
        console.log(...)
    }   
)

//再试试
最后一个固定(
    123,
   
"呵呵",
    {1;2;5},
   
"第四个参数",
   
"第五个参数",
   
function(...){
        console.log(...)
    }   
)



2,中间实参固定,两边可变的范例--->多线程--->线程命令订阅模式,代码如下:

//线程命令订阅模式
import win.ui;
/*DSG{{*/
var winform = ..win.form( bottom=399;parent=...;text="aardio Form";right=599 )
winform.add(
edit={ bottom=273;right=521;left=66;multiline=1;top=52;z=1;edge=1;cls=
"edit" }
)
/*}}*/

import thread.command;
var 订阅者 = thread.command();
订阅者.自定义线程命令 =
function(...){
    winform.edit.appendText(
'\n',...) //将参数追加输出到文本框
}
订阅者.自定义线程命令2 =
function(...){
    winform.edit.appendText(
'\n',...) //将参数追加输出到文本框
}  

//创建线程
thread.create(
   
function(hwnd){
   
        
import thread.command
        
        
//如果不指定窗口,所有订阅了此命令的窗口相应函数都会被调用
        thread.command.post("自定义线程命令","线程调用",",线程调用参数2",'\r\n') //这里自定义线程命令是第一个参数
        
        
//也可以显式指定窗口,仅触发指定窗口的命令
       thread.command.post(hwnd,"自定义线程命令2","线程调用",'\r\n')//这里自定义线程命令是第二个参数
        
    },订阅者._form.hwnd
)

winform.show()

win.loopMessage();

看到了吗? 注意看thread.command.post()中间有个固定参数自定义线程命令,而前面参数是不固定的,后面的也是不固定的
如果你不看源码,会不会认为thread.command.post()函数定义如下:

thread.command.post=function(...,cmd,...){
   
//.....代码略
}

你可以很奇怪这样是不是和帮助文档中所讲有冲突?下面看看源码中是怎么实现的
    var sendCmd = function( sendApi,hwnd,method,... ){  
        
var t = type(hwnd);
        
if( t == "string" ){//判断第二参数的类型做相应处理,第二个参数只有两种类型要么是线程命令要么是句柄
            var realName = hwnd;
            
var sendTable = {realName;method;...};//看看这里sendTable第一个键
            var subscribe = commandTable.getByNamespace("subscribe['"+realName+"']");
            
            
for(hwnd in subscribe){
               
var id = commandTable.push(sendTable);
                sendApi(hwnd,0x4CC
/*_WM_THREAD_COMMAND*/,id,0)
            }
        }
        
elseif(t == "number" ){
           
var sendTable = {method;...}; //看看这里sendTable第一个键,你可以比较一下和上面if中的处理
            var id = commandTable.push( sendTable );
            
return sendApi( hwnd,0x4CC/*_WM_THREAD_COMMAND*/,id,0);
        };
    }
   
    post =
function( ... ){
        sendCmd(::PostMessage,... );
    }
有兴趣的朋友可以试着自己实现一个和上面功能一样的简单例子,欢迎回帖!




评分

参与人数 2银币 +60 收起 理由
dem + 10 赞一个!
双书幻 + 50

查看全部评分

小时候,幸福是一件东西,拥有就是幸福; 长大了,幸福是一个目标,达到就是幸福; 成熟后,发现幸福原来是一种心态,领悟就是幸福.
回复

使用道具 举报

48

主题

613

帖子

3427

积分

五级会员

Rank: 8Rank: 8

积分
3427
发表于 2012-10-30 18:03:58 | 显示全部楼层

这帖得回

这帖得回
回复

使用道具 举报

9

主题

209

帖子

1326

积分

四级会员

Rank: 6Rank: 6

积分
1326
发表于 2012-10-30 19:44:49 | 显示全部楼层

一起学习,

一起学习,
回复

使用道具 举报

92

主题

1503

帖子

8141

积分

荣誉会员

Rank: 8Rank: 8

积分
8141
发表于 2012-10-30 20:27:51 | 显示全部楼层

基础知识,重温学习,谢谢look版主指导~

基础知识,重温学习,谢谢look版主指导~
回复

使用道具 举报

0

主题

44

帖子

373

积分

二级会员

Rank: 3Rank: 3

积分
373
发表于 2012-10-31 14:04:40 | 显示全部楼层

学习帖要试试

学习帖要试试
回复

使用道具 举报

0

主题

13

帖子

1867

积分

四级会员

Rank: 6Rank: 6

积分
1867
发表于 2012-10-31 20:28:15 | 显示全部楼层

谢谢分享了啊

谢谢分享了啊
回复

使用道具 举报

0

主题

76

帖子

480

积分

二级会员

Rank: 3Rank: 3

积分
480
发表于 2012-10-31 21:06:20 | 显示全部楼层

...

...
回复

使用道具 举报

13

主题

122

帖子

697

积分

三级会员

Rank: 4

积分
697
发表于 2012-11-1 12:43:48 | 显示全部楼层

哦,可变参数放在前面好像是有冲突,看看先

哦,可变参数放在前面好像是有冲突,看看先
有很多时候,这语言都是相通的。特别是肢体语言。
回复

使用道具 举报

8

主题

98

帖子

716

积分

三级会员

Rank: 4

积分
716
发表于 2012-11-1 15:16:39 | 显示全部楼层

不错,看看隐藏的是什么

不错,看看隐藏的是什么
回复

使用道具 举报

12

主题

182

帖子

1087

积分

四级会员

Rank: 6Rank: 6

积分
1087
QQ
发表于 2012-11-1 19:42:15 | 显示全部楼层

回复了再看,谢谢版主分享

回复了再看,谢谢版主分享
再烦也别忘微笑,再急也要注意语调!
即使是不成熟的尝试,也胜于胎死腹中的策略。
回复

使用道具 举报

4

主题

27

帖子

723

积分

三级会员

Rank: 4

积分
723
发表于 2012-11-3 10:50:31 | 显示全部楼层

刚学函数 正好学习下参数!一直不太明白!感谢楼主!

刚学函数 正好学习下参数!一直不太明白!感谢楼主!
回复

使用道具 举报

5

主题

15

帖子

127

积分

一级会员

Rank: 2

积分
127
发表于 2012-11-3 19:53:46 | 显示全部楼层

有創意的語言 學習中

有創意的語言
學習中
回复

使用道具 举报

12

主题

541

帖子

3177

积分

五级会员

子非魚、安知魚之樂

Rank: 8Rank: 8

积分
3177
发表于 2012-11-3 19:59:23 | 显示全部楼层

{:victory:}

回复

使用道具 举报

40

主题

151

帖子

970

积分

三级会员

Rank: 4

积分
970
发表于 2012-11-3 20:39:18 | 显示全部楼层

看看是什么

看看是什么
回复

使用道具 举报

1

主题

2

帖子

22

积分

新手入门

Rank: 1

积分
22
发表于 2012-11-4 08:06:28 | 显示全部楼层

感谢分享,认真学习。

感谢分享,认真学习。
回复

使用道具 举报

6

主题

141

帖子

1135

积分

四级会员

Rank: 6Rank: 6

积分
1135
发表于 2012-11-4 14:38:46 | 显示全部楼层

回复看看

回复看看
回复

使用道具 举报

0

主题

6

帖子

92

积分

一级会员

Rank: 2

积分
92
发表于 2012-11-5 22:23:34 | 显示全部楼层

看看,学习一下!

看看,学习一下!
回复

使用道具 举报

4

主题

14

帖子

97

积分

一级会员

Rank: 2

积分
97
发表于 2012-11-7 17:50:42 | 显示全部楼层

谢谢分享~!~~~

谢谢分享~!~~~
回复

使用道具 举报

8

主题

26

帖子

285

积分

二级会员

Rank: 3Rank: 3

积分
285
QQ
发表于 2012-11-8 17:15:25 | 显示全部楼层

学习了,谢谢

学习了,谢谢
回复

使用道具 举报

手机版|未经许可严禁引用或转载本站文章|站长邮箱|aardio.com|aardio官方社区 ( 皖ICP备09012014号 )

GMT+8, 2017-9-22 07:08 , Processed in 0.171875 second(s), 28 queries , Wincache On.

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表