论坛首页 Java企业应用论坛

ajoo的jaskell和jparsec

浏览 14927 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-02-04  
ajoo 写道
好。我的facts是个immutable的tuple。它至少支持一个set成员。


不错,但是我们还有一个跟踪调试的问题,因为有些处理流程可能会很复杂,所以我们应该提供流程跟踪和类似设置断点的能力,我们不要求做到策略库内部函数实现过程的跟踪,但是至少要能够得到每一行语句执行前和执行后的数据,以判定所写的策略语句是否复合预期的要求。

比如说要跟踪“折扣2”执行前后的数据变化,OO架构可以轻易完成的工作,高阶函数要怎么玩呢?

Facts facts = new Facts; 
facts.New("价格", "100");; 
facts.New("数量", "2");; 
facts.New("货物名称", "猪");; 

Actions acs = new Actions; 
acs.New("折扣1 = 5%", "数量 > 100 or 货物名称='猪' ");; 

acs.New("折扣2 = 3%", "数量 > 10 and 数量 < 100");; 
// register event
acs.current_ac.before += new Action.OnBefore(ac_trace_action);;
acs.current_ac.after += new Action.OnAfter(ac_trace_action);;

acs.New("折扣3 = 0%", "数量 <= 10");; 
acs.New("折扣 = Max(折扣1, 折扣2, 折扣3);");; 
acs.New("总额 = 价格 * 数量 * (100% - 折扣);");; 

acs.OnAction(facts);; 

string total = facts.Get("总额");; 
stirng discount = facts.Get("折扣");;

// handle event
private void ac_trace_action(bool is_before, string expression,  string error, Facts facts);
{
	string discount = facts.Get("折扣2");;
	string count = facts.Get("数量");;
}
0 请登录后投票
   发表时间:2005-02-04  
首先,对这类event handling的东西,我并不推荐用jaskell这种脚本,至少是看不出太多好处。

函数式的优势在于对一些业务逻辑的声明性编成,或者灵活组合不同的模块,起一个胶水的作用。

而对event handler这种OO的传统强项,函数式恐怕看不出太多优势。

不过,也不是不能做。

只是,你的这个例子我没有看得太懂。
你的这个trace似乎还是硬编码近来的。如果如此,你为什么不这样?

final Action act = new SimpleAction("折扣2 = 3%", "数量 > 10 and 数量 < 100");.
  .setBefore(ac_trace_action);
  .setAfter(ac_trace_action);;

acs.New(act);; 

我自己觉得这比用current_ac更好。
而这种设计也更加functional,是immutable的。用函数式也很容易做到。

而如果你需要的是更加动态,类似aop风格的trace织入,比如:
Actions new_acts = 
acts.setBefore("折扣2 = 3%", ac_trace_action);
.setAfter("折扣2 = 3%", ac_trace_action);;


这用jaskell这种动态语言也很容易:

let
  key = "折扣2 = 3%";
  old_act = acts@key;
  weave_trace a x = let
    _ = ac_trace_action;
    r = a x;
    _ = ac_trace_action;
    in r;
  new_acts = extend acts key (weave_trace old_act);;
in
  new_acts



这应该就算aop了吧?
0 请登录后投票
   发表时间:2005-02-04  
看了2天的jaskell, 偶的小脑袋已经接近发疯的边缘

ajoo 写道

我做这个东西的初衷是要非程序员的业务用户也能用,所以采用函数式就比较合适。毕竟不是所有business analyst都懂得“赋值”是什么意思。

偶觉得好像脱离了你的设计初衷, 对于这些业务用户来说重要是lib, 他们只用知道fact 10 或者 fact (10) 是计算10的阶乘, 用discount(customer, product)能够获得打折的数值, 不能指望他能够用jaskell写出多复杂函数式来, 他也不关心具体的实现是尾递归,lamda之类的.

对于这些业务用户来说, 越简单越好, 比如获得当前时间,并进行格式化, 最简单的就是提供now和format 2个函数:
format(now(), "yyyy-MM-dd")

如果让他们写成:
$SimpleDateFormat.new"yyyy-MM-dd".format $Date.new 之类的, 就太繁琐了.

ajoo 写道

此时,可以让一个不懂java的维护人员花一个小时熟悉一下jaskell的基本语法,就可以写各种不同的逻辑规则了。

如:
if north_america_sales + asian_sales > central_sales then north_america_sales - 100 else central_sales
where
north_america_sales = canada_sales+mexico_sales+united_states_sales 
..


他需要了解if, else, where 还有 .. 这些keyword

偶认为简单的做法就是提供if(boolean expression, true return value, false return value)这样一个if函数
if(north_america_sales + asian_sales > central_sales, north_america_sales - 100, central_sales);
where north_america_sales = canada_sales+mexico_sales+united_states_sales


总之, 各种应用, 用户只要会查函数手册以及学一个定义变量的关键字就够了

而jaskell其他的高级特性, 不是语法太怪异, 就是需要用户有良好的数学背景, 用户群太小
0 请登录后投票
   发表时间:2005-02-04  
语法怪,是你impretive 语言用多了。
0 请登录后投票
   发表时间:2005-02-04  
Readonly 写道

偶觉得好像脱离了你的设计初衷, 对于这些业务用户来说重要是lib, 他们只用知道fact 10 或者 fact (10) 是计算10的阶乘, 用discount(customer, product)能够获得打折的数值, 不能指望他能够用jaskell写出多复杂函数式来, 他也不关心具体的实现是尾递归,lamda之类的.

对于这些业务用户来说, 越简单越好, 比如获得当前时间,并进行格式化, 最简单的就是提供now和format 2个函数:
format(now(), "yyyy-MM-dd")

如果让他们写成:
$SimpleDateFormat.new"yyyy-MM-dd".format $Date.new 之类的, 就太繁琐了.

可以这样啊。写个外围函数库就是了。就是一个now函数和一个format函数而已。或者可以写成
now.format "yyyy-MM-dd"
可能更好看些吧?
本来就不指望他们能写递归。只要能写公式,定义简单的函数就行了。

Readonly 写道

ajoo 写道

此时,可以让一个不懂java的维护人员花一个小时熟悉一下jaskell的基本语法,就可以写各种不同的逻辑规则了。

如:
if north_america_sales + asian_sales > central_sales then north_america_sales - 100 else central_sales
where
north_america_sales = canada_sales+mexico_sales+united_states_sales 
..


他需要了解if, else, where 还有 .. 这些keyword

偶认为简单的做法就是提供if(boolean expression, true return value, false return value)这样一个if函数
if(north_america_sales + asian_sales > central_sales, north_america_sales - 100, central_sales);
where north_america_sales = canada_sales+mexico_sales+united_states_sales



我已经删掉".."了。直接用分号就是了。最后的那个函数甚至不需要分号。

我是觉得if-then-else比你提的函数要清楚,更接近自然语言。也许更为业务用户所接受。

不过如果if是个函数的话,倒是有一个好处:currying。我可以写
if true, if x a等等partial application的东西。

而且语言也更简练,连if-then-else这三个关键字都没了,有的只是一个库定义的if函数。true和false也可以由库定义。这样关键字就剩下
where, let, in, and, or了。

坏处是,因为if是函数,而函数调用的优先级最高,如果你用haskell式的空格分隔法写函数调用,碰巧你比较懒,省括号过了头,写成这样
if 1>2 
   "a"
    "b"
却被解释成:
(if 1); > 2 "a" "b"
。然后报错。

你必须或者写成:
if(1>2); "a" "b"

或者写成
if(1>2, "a", "b");


总而言之,是给程序员留下了一处陷阱。
而if-then-else却没有这个问题。

何去何从,倒是有点费脑筋呢。
我其实是很希望能说服自己用函数,这样语言更加简单,而我喜欢简单。

trustno1意见如何? if-then-else是函数好还是关键字好?
是内建于语言还是外建于库?



当然,也可以自己定义一个函数
ifelse cond yes no = if cond then yes else no;

然后让用户用ifelse函数好了。

对了,看来你已经深谙jaskell的lazy之道了呀。
在strict的语言里,比如java/c++,你是不可能用函数来模拟if-else,、因为if(true, 1, throw new Exception());
会出错,而不是象
if (true); return 1; else throw new Exception();;

那样返回1。


其实,jaskell的keyword已经尽量精简了。只有:
if, then, else, where, let, in, true, false, and , or。
再有,就是一个定义在顶级名字空间的not函数。
就这些了,再没有了。
而且一个业务员可能还不需要了解let和in。就是8个关键字和定义函数,调用函数的语法。

Readonly 写道

总之, 各种应用, 用户只要会查函数手册以及学一个定义变量的关键字就够了

我不认为让业务用户查函数手册是个可以让人满意的解决方法。如果需要定义一些函数给业务用户用,这个函数库一定要精简,最好就那么三五个意义不言自明的函数。

Readonly 写道

而jaskell其他的高级特性, 不是语法太怪异, 就是需要用户有良好的数学背景, 用户群太小

举个例子?语法怪异的我看看能不能改进。需要良好数学背景的你是指高阶函数? 可是你不见得需要用它呀。

:
0 请登录后投票
   发表时间:2005-02-05  
用函数,还是关键字对用户来说没有什么根本差别。
如果用函数的话,还不如用三目算符呢。如果用函数的话,我估计会演变成lisp的风格。这就会很好看。
0 请登录后投票
   发表时间:2005-02-06  
ajoo 写道
首先,对这类event handling的东西,我并不推荐用jaskell这种脚本,至少是看不出太多好处。

函数式的优势在于对一些业务逻辑的声明性编成,或者灵活组合不同的模块,起一个胶水的作用。

而对event handler这种OO的传统强项,函数式恐怕看不出太多优势。

不过,也不是不能做。

只是,你的这个例子我没有看得太懂。
你的这个trace似乎还是硬编码近来的。如果如此,你为什么不这样?

final Action act = new SimpleAction("折扣2 = 3%", "数量 > 10 and 数量 < 100");.
  .setBefore(ac_trace_action);
  .setAfter(ac_trace_action);;

acs.New(act);;

我自己觉得这比用current_ac更好。
而这种设计也更加functional,是immutable的。用函数式也很容易做到。

而如果你需要的是更加动态,类似aop风格的trace织入,比如:
Actions new_acts = 
acts.setBefore("折扣2 = 3%", ac_trace_action);
.setAfter("折扣2 = 3%", ac_trace_action);;


这用jaskell这种动态语言也很容易:

let
  key = "折扣2 = 3%";
  old_act = acts@key;
  weave_trace a x = let
    _ = ac_trace_action;
    r = a x;
    _ = ac_trace_action;
    in r;
  new_acts = extend acts key (weave_trace old_act);;
in
  new_acts



这应该就算aop了吧?


事实上所有的代码都是硬编的,因为我提供的是类库而不是脚本解释器,主要是用于模拟脚本语言,这样做的好处是直观易懂、灵活、易于扩展。

引用

我自己觉得这比用current_ac更好。
而这种设计也更加functional,是immutable的。用函数式也很容易做到。
final Action act = new SimpleAction("折扣2 = 3%", "数量 > 10 and 数量 < 100");.
  .setBefore(ac_trace_action);
  .setAfter(ac_trace_action);;

acs.New(act);; 


这样写有一个坏处,就是会破坏脚本语言的直观性,因为我们并不是任何时候都需要setBefore和setAfter,这些非必要的代码必须能够随意加入和删除,同时不能对原有代码造成任何影响,要做到这一点就需要使用acts.current_ac。

引用

而如果你需要的是更加动态,类似aop风格的trace织入,比如:
Actions new_acts = 
acts.setBefore("折扣2 = 3%", ac_trace_action);
.setAfter("折扣2 = 3%", ac_trace_action);;



这种方法本来不错,但是有一个缺点,就是必须为每一行语句命名,并且必须保证命名的唯一性,不过如果真要为每行代码去命名的话相信大部分人都会受不了。

引用

这用jaskell这种动态语言也很容易:
let
  key = "折扣2 = 3%";
  old_act = acts@key;
  weave_trace a x = let
    _ = ac_trace_action;
    r = a x;
    _ = ac_trace_action;
    in r;
  new_acts = extend acts key (weave_trace old_act);
in
  new_acts
这段就不评论了,我已经看傻眼了。 jaskell的语法怎么看都不象是面向大众设计的,业务专家要使用这个东西恐怕得先修炼成为jaskell专家才行。
0 请登录后投票
   发表时间:2005-02-06  
我觉得设计面向大众的程序设计语言基本上是mission impossible.不过图形化的语言,比如以前的authorware那种东西,还有那个十么易语言。倒是可能成功的方向。
把脚本语言定在Business logic 的方向,我觉得应用也不会太大。一个系统真的要用script来做business logic的地步的话,估计已经是大的不成样子了。
Jaskell目前能有十么应用,我至少没有看出来。不过我建议设计语言应该小步快走,边用边改.
所以我想,ajoo首先应该在实际的项目中用用看。如果设计者都无法在项目中使用它,只能当个Toy了。
0 请登录后投票
   发表时间:2005-02-06  
引用


这样写有一个坏处,就是会破坏脚本语言的直观性,因为我们并不是任何时候都需要setBefore和setAfter,这些非必要的代码必须能够随意加入和删除,同时不能对原有代码造成任何影响,要做到这一点就需要使用acts.current_ac。

可是你那个current_ac的代码仍然是对原有代码造成影响了呀。你还要改变原有代码(通过插入这两行trace代码)。

引用

这种方法本来不错,但是有一个缺点,就是必须为每一行语句命名,并且必须保证命名的唯一性,不过如果真要为每行代码去命名的话相信大部分人都会受不了。

这倒是。但是,至少你可以允许为某一行命名吧?
给一行命名总比在这行前后插入trace代码好吧?


引用

这用jaskell这种动态语言也很容易:

let
  key = "折扣2 = 3%";
  old_act = acts@key;
  weave_trace a x = let
    _ = ac_trace_action;
    r = a x;
    _ = ac_trace_action;
    in r;
  new_acts = extend acts key (weave_trace old_act);
in
  new_acts

引用

这段就不评论了,我已经看傻眼了。
jaskell的语法怎么看都不象是面向大众设计的,业务专家要使用这个东西恐怕得先修炼成为jaskell专家才行。

我想主要是因为很多语法都没有解释,我的tutorial也很不详细。
先解释一下:
let - in中间的是一些变量定义, 后面的是使用这些变量的表达式。

操作符@就是下标操作,acts@key就等价于c++中的acts[key]。这个语法确实不太符合习惯,这也是不得已。如果要批评这个语法,我只好听着,暂时没有办法。唉。

_ = ...; 的意思是我不在乎返回值,只在乎这个表达式的副作用。

extend函数是动态改变一个tuple的内容。

weave_trace函数把trace动作编织进某一个方法中去。

我相信,你即使用java或者aspectJ也不会有更简洁的语法的。因为上面的代码几乎没有任何废话。你可以试试·用java来描述这种动态织入,看看是否更简单。

至于说这段代码,本来就不是面向非程序员的。这我前面已经说过了。业务用户要做的就是简单的公式定义和函数定义。他们不可能去搞什么高阶函数,什么OO,什么AOP。
你要是能找出一个语言来让非程序员用户可搞这种aop(除了通过wizard, GUI什么的),我可真要佩服了。

jaskell有目标有两个,一方面让非程序员用户可以简单的使用;另一方面让熟悉高阶函数的程序员可以获得强大的能力。就象数学一样,小学生也可以学1+1,但是研究生,博士生也仍然不会认为数学是个容易的东西。我们不能拿一个微分方程然后批评数学不大众化吧?
0 请登录后投票
   发表时间:2005-02-06  
Trustno1 写道
我觉得设计面向大众的程序设计语言基本上是mission impossible.不过图形化的语言,比如以前的authorware那种东西,还有那个十么易语言。倒是可能成功的方向。
把脚本语言定在Business logic 的方向,我觉得应用也不会太大。一个系统真的要用script来做business logic的地步的话,估计已经是大的不成样子了。
Jaskell目前能有十么应用,我至少没有看出来。不过我建议设计语言应该小步快走,边用边改.
所以我想,ajoo首先应该在实际的项目中用用看。如果设计者都无法在项目中使用它,只能当个Toy了。

我是在工作过程中,发现确实存在这种用户要灵活定义公式的需求。
这些公式可能被用在data-entry和report中。
这种东西如果每次改变都要开发员介入,效率不高。

jaskell面对业务客户的东西很少,就是一个公式定义和简单的函数定义,if-else, 加减乘除,大于小于。这些对业务用户已经够了。


而如果先提出一个需要程序员来解决的需求,然后批评代码业务员看不懂,我觉得好像有点那个吧?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics