搜索
aardio官方社区 门户 查看主题

灵活的可变参数

发布者: look | 发布时间: 2012-10-30 15:45| 查看数: 18780| 评论数: 133|帖子模式

本帖最后由 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

查看全部评分

最新评论

jyb21 发表于 2012-10-30 18:03:58

这帖得回

这帖得回
coder 发表于 2012-10-30 19:44:49

一起学习,

一起学习,
qqmmcc 发表于 2012-10-30 20:27:51

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

基础知识,重温学习,谢谢look版主指导~
feng123144 发表于 2012-10-31 14:04:40

学习帖要试试

学习帖要试试
sj123 发表于 2012-10-31 20:28:15

谢谢分享了啊

谢谢分享了啊
ghl1975 发表于 2012-10-31 21:06:20

...

...
vr4u 发表于 2012-11-1 12:43:48

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

哦,可变参数放在前面好像是有冲突,看看先
lyz8 发表于 2012-11-1 15:16:39

不错,看看隐藏的是什么

不错,看看隐藏的是什么
wynn_li 发表于 2012-11-1 19:42:15

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

回复了再看,谢谢版主分享
a左手刀 发表于 2012-11-3 10:50:31

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

刚学函数 正好学习下参数!一直不太明白!感谢楼主!
akqjt 发表于 2012-11-3 19:53:46

有創意的語言 學習中

有創意的語言
學習中
xauto 发表于 2012-11-3 19:59:23

{:victory:}

zyzy135 发表于 2012-11-3 20:39:18

看看是什么

看看是什么
ke717 发表于 2012-11-4 08:06:28

感谢分享,认真学习。

感谢分享,认真学习。
小X 发表于 2012-11-4 14:38:46

回复看看

回复看看
yadinae 发表于 2012-11-5 22:23:34

看看,学习一下!

看看,学习一下!
gadzan 发表于 2012-11-7 17:50:42

谢谢分享~!~~~

谢谢分享~!~~~
wisefox 发表于 2012-11-8 17:15:25

学习了,谢谢

学习了,谢谢

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

GMT+8, 2018-5-28 15:36 , Processed in 0.062500 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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