首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Logtalk: meta::map,lambda表达式和对私有方法的访问

Logtalk: meta::map,lambda表达式和对私有方法的访问
EN

Stack Overflow用户
提问于 2012-02-27 14:21:23
回答 1查看 201关注 0票数 2

我认为这是一个与范围相关的问题。如果我对我的对象有这样的规则:

代码语言:javascript
复制
:- public(new/2).
:- mode(new(+list, -object_identifier), one).
new(Args, Instance) :-
    self(Self),
    create_object(Instance, [instantiates(Self)], [], []),
    Instance::process_arguments(Args).

如果我跳这个舞,我发现这个效果很好:

代码语言:javascript
复制
:- object(name, instantiates(name)).

我不完全理解为什么这是必要的,但我怀疑它与我的实际问题有关,即如果我在我的对象中有您的标准Prolog循环,如下所示:

代码语言:javascript
复制
process_arguments([Arg|Args]) :- process_arg(Arg), process_arguments(Args).
process_arguments([]).

process_arg(Arg) :- ::asserta(something(Arg)).

我发现使用::asserta将事实放在正确的名称空间中(在新创建的实例上)。但是,如果我变得机智起来,将process_arguments/1的主体替换为这个lambda表达式:

代码语言:javascript
复制
process_arguments(Args) :- meta::map([Arg]>>process_arg(Arg), Args).

然后,我将我的事实添加到父类中,并由所有实例共享。如果我将其替换为:

代码语言:javascript
复制
process_arguments(Args) :-
    self(Self),
    meta::map([Arg]>>(Self::process_arg(Arg)), Args).

然后它就可以工作了,但是当我不想这样做的时候,我不得不让process_arg/1成为一个公共规则。我遗漏了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-02-28 06:55:21

让我首先从上面的代码片段开始,其中对象name实例化它自己。在执行此操作时,您将使name成为它自己的类。哪里没什么问题。在支持元类的语言中,比如Smalltalk和Logtalk,让一个类成为自己的元类是避免无限回归的经典方法。例如,请参阅维基百科关于元类的条目(http://en.wikipedia.org/wiki/Metaclass)。另请参阅Logtalk发行版中的“反射”示例。通过使对象name实例化自身,它既充当实例的角色(当它实例化对象时),又扮演类的角色(因为它由对象实例化)。如果您将name定义为独立对象,即与其他对象无关的对象,则它将被编译为原型。

现在来回答你的问题。在Logtalk中,元谓词(如meta::map/2)在发送方的上下文中调用。如果在name中定义了process_arguments/1谓词,则执行上下文(包括self的值)将为name。因此,将在name中断言something/1的子句。您的变通方法(通过使用内置方法self/1)可以按预期工作,但它确实会强制您声明process_arg/1公共谓词。这是稳定Logtalk版本中的一个错误,因为它也应该通过声明process_arg/1谓词protected或private来工作(因为发送者是name,并且谓词是在发送者中声明的)。例如:

代码语言:javascript
复制
:- object(name,
    instantiates(name)).

    :- public(new/2).
    :- mode(new(+list, -object_identifier), one).
    new(Args, Instance) :-
        self(Self),
        create_object(Instance, [instantiates(Self)], [set_logtalk_flag(dynamic_declarations, allow)], []),
        meta::map({Instance}/[Arg]>>(Instance::process_arg(Arg)), Args).

    :- private(process_arg/1).
    process_arg(Arg) :-
        ::asserta(something(Arg)).

:- end_object.

我将在本周晚些时候将错误修复推到公开可用的Logtalk开发版本中。谢谢你让我注意到这个bug。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9460835

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档